PowerMTA's configuration file controls every aspect of high-volume email delivery: how many concurrent connections each IP makes to each ISP, which IP addresses different message streams use, how DKIM signing is applied, how bounces are classified and acted upon, and how the system behaves when ISPs throttle or block traffic. A misconfigured PowerMTA can bottleneck throughput, damage IP reputation through over-aggressive connection behaviour, or fail to process bounces — making it impossible to maintain list hygiene at scale. This guide covers the core configuration structure, per-ISP delivery tuning, DKIM integration, bounce management, and the monitoring setup required to operate PowerMTA in production.

vMTA
virtual MTA — separate IP/sending identity per client or domain
20M+/day
PowerMTA throughput ceiling on enterprise hardware
PowerMTA config block for per-domain routing rules
port25
PowerMTA vendor — acquired by Message Systems, now Momentum

PowerMTA Delivery Performance — ISP Throughput with Tuned vMTA Config

98%Gmail94%Microsoft91%Yahoo97%Comcast93%iCloud84%Orange

Configuration File Structure

PowerMTA's primary configuration file is located at /etc/pmta/config (path may vary by installation). Unlike Postfix's separate main.cf and master.cf files, PowerMTA uses a single hierarchical configuration with nested block structures:

# /etc/pmta/config — basic structure

# Global settings
host-name mail.yourdomain.com
smtp-listener 0/0:25

# License
license /etc/pmta/license

# Logging paths
log-file /var/log/pmta/pmta.log
log-rotate-size 200M

# Virtual MTA definitions
<virtual-mta vmta-main>
  smtp-source-ip 203.0.113.10
  ehlo-hostname mail.yourdomain.com
</virtual-mta>

# Per-ISP delivery policies (domain blocks)
<domain gmail.com>
  max-smtp-out 10
  max-msg-per-connection 100
</domain>

# Accounting (bounce and delivery logging)
<acct-file /var/log/pmta/acct.csv>
  records d
  record-fields d timeLogged,orig,rcpt,vmta,jobId,dlvStatus,dsnStatus,dsnDiag
</acct-file>

Server Identity and Basic Settings

# /etc/pmta/config — global settings section

# Hostname used in EHLO and logging
host-name mail.yourdomain.com

# SMTP listener — 0/0:25 = all interfaces, port 25
# For injection-only (relay): listen on localhost only
smtp-listener 127.0.0.1:25

# For receiving messages from external campaign systems
smtp-listener 0/0:25

# Injection port (where your email platform injects messages)
# Use a non-standard port to separate injection from MTA-to-MTA
smtp-listener 0/0:587
smtp-smarthost-port 587

# Maximum queue size
max-queue-size 500M

# Worker threads
smtp-server-threads 30
smtp-client-threads 200

# Postmaster address (receives FBL reports and admin messages)
postmaster postmaster@yourdomain.com

# Log settings
log-file /var/log/pmta/pmta.log
log-rotate-size 200M
log-rotate-count 10

Virtual MTA: Stream Isolation

Virtual MTAs (vMTAs) are the core stream isolation mechanism in PowerMTA. Each vMTA has its own IP address, its own delivery queues, and its own per-ISP connection behaviour. Messages injected with a specific X-Binding or X-VirtualMTA header route to the named vMTA.

PowerMTA config.xml — vMTA per client with IP binding
<virtual-mta name="client-acme">
  <smtp-source-host>203.0.113.10</smtp-source-host>
  <domain-key name="acme" domain="acme.com" path="/etc/pmta/keys/acme.pem"/>
  <max-smtp-out>10</max-smtp-out>
  <max-msg-rate>200/h</max-msg-rate>
</virtual-mta>

<domain name="gmail.com">
  <max-smtp-out>10</max-smtp-out>
  <smtp-pattern-list name="gmail-deferrals">
    <smtp-pattern response="421*" action="defer" period="60s"/>
  </smtp-pattern-list>
</domain>
# Stream isolation: transactional vs marketing on separate IPs
<virtual-mta vmta-transactional>
  smtp-source-ip 203.0.113.10
  ehlo-hostname tx.yourdomain.com
  # Maximum simultaneous outbound connections from this vMTA
  max-smtp-out 100
  # Per-connection message limit
  smtp-retries-after-shutoff 5
</virtual-mta>

<virtual-mta vmta-marketing>
  smtp-source-ip 203.0.113.11
  smtp-source-ip 203.0.113.12    # multiple IPs rotate across connections
  ehlo-hostname mkt.yourdomain.com
  max-smtp-out 80
  smtp-retries-after-shutoff 3
</virtual-mta>

<virtual-mta vmta-bulk>
  smtp-source-ip 203.0.113.20
  smtp-source-ip 203.0.113.21
  smtp-source-ip 203.0.113.22
  ehlo-hostname bulk.yourdomain.com
  max-smtp-out 150
</virtual-mta>

# vMTA pools allow automatic load distribution
<virtual-mta-pool pool-marketing>
  virtual-mta vmta-marketing
  virtual-mta vmta-bulk
</virtual-mta-pool>

Your injection application (MailWizz, custom code, or any SMTP client) targets a specific vMTA by setting the X-Binding: vmta-name SMTP header when injecting messages.

Per-ISP Domain Blocks: Delivery Tuning

Domain blocks in PowerMTA configure the delivery behaviour for specific receiving domains or MX patterns. This is where per-ISP throttling is implemented — the most impactful configuration for inbox placement at scale.

# Gmail — engagement-sensitive, allow reasonable concurrency
<domain gmail.com>
  max-smtp-out 10              # max concurrent connections to Gmail MXs
  max-msg-per-connection 100   # messages per SMTP session
  retry-after 421 4.7.0 15m   # Gmail "unsolicited" throttle — wait 15min
  retry-after 421 4.3.0 5m    # Gmail infrastructure throttle — retry after 5min
  max-msg-rate 500/m           # max messages per minute to Gmail total
</domain>

# Microsoft — conservative; aggressive sends trigger 421 4.7.650
<domain outlook.com hotmail.com live.com msn.com>
  max-smtp-out 5
  max-msg-per-connection 50
  retry-after 421 4.7.650 30m  # Microsoft reputation throttle
  retry-after 421 4.7.0 20m
  max-msg-rate 200/m
</domain>

# Yahoo / AOL — watch for TS codes
<domain yahoo.com ymail.com aol.com>
  max-smtp-out 8
  max-msg-per-connection 50
  retry-after 421 TS01 60m    # TS01 = complaint rate issue — wait an hour
  retry-after 421 TS03 15m    # TS03 = connection rate — 15min then retry
</domain>

# Apple iCloud
<domain icloud.com me.com mac.com>
  max-smtp-out 10
  max-msg-per-connection 100
</domain>

# Conservative policy for ISPs not specifically configured
<domain *>
  max-smtp-out 20
  max-msg-per-connection 200
  max-msg-rate 1000/m
</domain>

DKIM Signing Configuration

PowerMTA supports DKIM signing natively for domains configured with private keys. The configuration maps each sending domain to its DKIM private key and selector:

# DKIM signing in /etc/pmta/config
# Method 1: Direct private key reference (simple setup)
<dkim>
  domain yourdomain.com
  selector mail
  private-key-file /etc/pmta/dkim/yourdomain.com.private.key
  header-list from:to:subject:date:message-id:content-type
  canonicalization relaxed/simple
  sign-hash sha256
</dkim>

# Method 2: Multiple domains with domain-key blocks
<domain-key mail._domainkey.yourdomain.com>
  type DK
  private-key /etc/pmta/dkim/yourdomain.com.private.key
  domain yourdomain.com
  selector mail
</domain-key>

<domain-key mail._domainkey.anotherdomain.org>
  type DK
  private-key /etc/pmta/dkim/anotherdomain.org.private.key
  domain anotherdomain.org
  selector mail
</domain-key>

Generate 2048-bit DKIM keys for PowerMTA:

# Generate key pair
openssl genrsa -out /etc/pmta/dkim/yourdomain.com.private.key 2048
openssl rsa -in /etc/pmta/dkim/yourdomain.com.private.key \
  -pubout -out /etc/pmta/dkim/yourdomain.com.public.key

# Set permissions — private key must be readable by pmta user only
chown pmta:pmta /etc/pmta/dkim/yourdomain.com.private.key
chmod 600 /etc/pmta/dkim/yourdomain.com.private.key

# Get the DNS record value
openssl rsa -in /etc/pmta/dkim/yourdomain.com.private.key \
  -pubout 2>/dev/null | grep -v -- '---' | tr -d '\n'
# Publish this value in: mail._domainkey.yourdomain.com TXT "v=DKIM1; k=rsa; p=..."

Bounce Classification and Accounting

PowerMTA's accounting system writes delivery events (bounces, successful deliveries, FBL complaints) to CSV files for processing by downstream list management systems. The accounting configuration determines what data is captured and how often files are rotated:

# Accounting file configuration
# Bounce log — records every bounce event
<acct-file /var/log/pmta/bounce.csv>
  move-interval 1h
  move-to /var/log/pmta/accounting/
  world-readable yes
  records b
  record-fields b timeLogged,bounceCat,vmta,orig,rcpt,srcMta,dlvSourceIp,jobId,dsnStatus,dsnMta,dsnDiag
</acct-file>

# Full delivery accounting
<acct-file /var/log/pmta/acct.csv>
  move-interval 24h
  move-to /var/log/pmta/accounting/
  world-readable yes
  records d
  record-fields d timeLogged,orig,rcpt,vmta,jobId,dlvStatus,dsnStatus
</acct-file>

# FBL (complaint) log
<acct-file /var/log/pmta/fbl.csv>
  move-interval 24h
  move-to /var/log/pmta/accounting/fbl/
  world-readable yes
  records feedback-loop
  record-fields f timeLogged,format,header_To,header_Return-Path,reportedDomain,header_X-FBLId
</acct-file>

Automatic bounce suppression rules

# Automatic actions based on bounce category
<bounce-action>
  type permanent
  match bad-mailbox bad-domain routing-errors inactive-mailbox
  action suppress
</bounce-action>

<bounce-action>
  type transient
  match quota-issues bad-connection
  action retry
  retry-after 4h
</bounce-action>

<bounce-action>
  type transient
  match spam-related
  action retry
  retry-after 6h
  max-tries 3
</bounce-action>

Access Control and Security

# Restrict SMTP injection to trusted sources only
# Messages can only be injected from these IPs
<smtp-server>
  allow-unencrypted-plain yes      # Allow password authentication without TLS for localhost
  max-smtp-in 50                   # Maximum incoming injection connections
</smtp-server>

# Source IP allowlist — only these IPs can inject mail
<source 127.0.0.1/8>
  relay yes
</source>

<source 10.0.0.0/8>
  relay yes
</source>

# All other sources — no relay
<source *>
  relay no
</source>

Monitoring and Management

Web monitoring interface

# Enable web management interface
<http>
  port 8080
  address 127.0.0.1   # Restrict to localhost; use SSH tunnel for remote access
  enable-config-editing yes
</http>

Essential CLI monitoring commands

# Overall system status
pmta status

# Queue depth per virtual MTA
pmta show status detail

# Per-domain delivery statistics
pmta show domain gmail.com

# Active queue depth
pmta show queue

# Inspect bounce log (last 100 lines)
tail -100 /var/log/pmta/bounce.csv | cut -d',' -f1,2,4,5,10

# Reload configuration after changes (no restart required)
pmta reload

# Flush deferred messages to a specific domain (use carefully)
pmta resume domain gmail.com

# Check suppression list
pmta show suppressed address@example.com

Hardware and Capacity Planning

PowerMTA's throughput ceiling is determined by hardware, not software configuration. Key sizing guidelines:

Daily volume targetCPURAMStorageIPs
Up to 500K/day4 cores8GBSSD 100GB1–3
500K–2M/day8 cores16GBNVMe 200GB3–10
2M–10M/day16 cores32GBNVMe RAID 500GB10–30
10M+/dayMulti-server cluster64GB+NVMe RAID per node30+

The most common bottleneck at high volume is disk I/O — PowerMTA queues are disk-based. NVMe storage is effectively mandatory above 1M/day. The second common bottleneck is DNS resolution — run a local caching resolver (Unbound or Bind) so MX lookups don't serialise delivery at repeated popular destination domains.