PowerMTA Per-Domain Source IP Routing: Complete 2026 Operator Guide

← PowerMTA Operations

PowerMTA Per-Domain Source IP Routing: Complete 2026 Operator Guide

February 20, 2027·12 min read·Henrik Larsen

Why per-domain routing matters

Per-domain source IP routing is the practice of sending mail to a specific recipient domain from a specific source IP. The reason it matters comes down to reputation: a source IP builds a reputation with each receiving ISP independently, and routing decisions determine which IP carries which reputation. An operator who wants Gmail-bound mail to go from a particular IP, perhaps one warmed and tuned specifically for Gmail, needs per-domain routing to make that happen.

This guide exists because PowerMTA offers several routing mechanisms and operators frequently use them without a clear picture of which mechanism does what. The domain block, the X-Virtual-MTA header, the queue-to directive, the VMTA pool: each plays a role, and per-domain source IP routing specifically draws on the domain block most directly. The structure of this guide: the routing mechanisms PowerMTA provides, config-based domain block routing in detail, header-based X-Virtual-MTA routing, combining the two, the queue-to directive for shared queues, the strategic question of when to dedicate an IP to a single ISP, the interaction with VMTA pools, reputation isolation per destination, and the diagnostic workflow when routing does not behave as configured.

The PowerMTA routing mechanisms

PowerMTA provides several mechanisms that together determine which source IP handles a given message:

MechanismWhat it controlsDecided by
VMTA smtp-source-hostWhich IP a VMTA binds toConfig
Domain block VMTA assignmentWhich VMTA handles a recipient domainConfig (recipient domain)
X-Virtual-MTA headerWhich VMTA handles a messageApplication (per message)
queue-to directiveWhich queue a domain routes intoConfig (recipient domain)
VMTA poolA group of VMTAs to rotate amongConfig

The foundation is the VMTA: each VMTA is bound to a source IP through its smtp-source-host directive. Routing a message to a VMTA therefore routes it to that VMTA's IP. Everything else is about which VMTA a message goes to.

For per-domain source IP routing specifically, where the goal is routing recipient domains to specific IPs, the domain block VMTA assignment is the most direct mechanism, because the recipient domain is exactly what PowerMTA can see and route on without any application involvement.

Config-based domain block routing

The domain block is the natural place to express per-domain source IP routing. A domain block for a recipient domain can specify which VMTA handles it, and since each VMTA is bound to an IP, this assigns the domain's traffic to that IP.

The basic pattern. First define VMTAs bound to the IPs:

<virtual-mta gmail-ip>
    smtp-source-host 203.0.113.40 mail-g.example.com
    domain-key k1,example.com,/etc/pmta/keys/example.pem
</virtual-mta>

<virtual-mta microsoft-ip>
    smtp-source-host 203.0.113.41 mail-m.example.com
    domain-key k1,example.com,/etc/pmta/keys/example.pem
</virtual-mta>

<virtual-mta general-ip>
    smtp-source-host 203.0.113.42 mail-x.example.com
    domain-key k1,example.com,/etc/pmta/keys/example.pem
</virtual-mta>

Then assign VMTAs to recipient domains via domain blocks:

<domain gmail.com>
    virtual-mta gmail-ip
    max-msg-rate 3000/h
    max-smtp-out 15
</domain>

<domain hotmail.com>
    virtual-mta microsoft-ip
    max-msg-rate 5000/h
    max-smtp-out 5
</domain>

<domain default>
    virtual-mta general-ip
    max-msg-rate 1000/h
</domain>

With this configuration, PowerMTA routes every message based on its recipient domain: messages to gmail.com go out from 203.0.113.40, messages to hotmail.com from 203.0.113.41, and everything else from 203.0.113.42. The application submitting the messages does not need to know anything about VMTAs or IPs; it hands PowerMTA the messages and PowerMTA routes them by recipient domain.

The domain default block is important: it is the catch-all for any recipient domain not matched by a specific domain block. Without a default, unmatched domains fall to PowerMTA's default handling, which may not be what the operator intends.

Header-based X-Virtual-MTA routing

The X-Virtual-MTA header lets the submitting application choose the VMTA per message. The application injects a header naming the VMTA, and PowerMTA honors it.

For PowerMTA to honor the header, the listener and source must be configured to process it:

<smtp-listener 127.0.0.1:25>
    process-x-virtual-mta yes
</smtp-listener>

<source 127.0.0.1>
    always-allow-relaying yes
    process-x-virtual-mta yes
</source>

The application then injects the header:

X-Virtual-MTA: gmail-ip

When PowerMTA receives a message with that header, it routes the message through the named VMTA regardless of the recipient domain. This puts the routing decision in the application's hands.

Header-based routing is the right choice when the routing decision depends on something the application knows but PowerMTA cannot see. The recipient domain is visible to PowerMTA, so routing by recipient domain does not need the header. But routing by customer, by campaign type, by stream (marketing versus transactional), by warmup status, those distinctions are not in the recipient domain, and only the application knows them. For those, the application injects X-Virtual-MTA to express the routing decision.

Combining config and header routing

The two approaches combine cleanly, and the combination is the common production pattern.

The typical arrangement: the application uses X-Virtual-MTA to select a VMTA pool based on the stream or customer, and then within that selection, config-based domain blocks or the pool composition handles per-destination routing.

For example, the application injects X-Virtual-MTA: marketing-pool to put a message into the marketing stream. The marketing-pool is a VMTA pool, and the config can route within the pool or use domain blocks to send specific recipient domains through specific pool members.

The precedence: when an X-Virtual-MTA header is present, PowerMTA honors it. The config-based domain block routing applies when there is no header, or the header points to a pool and the per-domain routing happens within the pool. The operator designs the combination so the application controls the coarse routing (which stream, which customer) and the config controls the fine routing (which IP for which ISP).

The substantive design principle: put each routing decision where the information lives. Stream and customer routing live in the application, so the application sets X-Virtual-MTA for those. Per-ISP routing depends only on the recipient domain, which PowerMTA sees, so config-based domain blocks handle that. Combining them gives clean routing without the application needing to know per-ISP IP assignments.

queue-to for shared queues

The queue-to directive serves a related but distinct purpose: it makes multiple recipient domains route into a single shared queue, so they share throttling and reputation accounting.

<domain yahoo.com>
    virtual-mta yahoo-ip
    max-msg-rate 2500/h
</domain>

<domain ymail.com>
    queue-to yahoo.com
</domain>

<domain aol.com>
    queue-to yahoo.com
</domain>

<domain comcast.net>
    queue-to yahoo.com
</domain>

With this configuration, mail to ymail.com, aol.com, and comcast.net all route into the yahoo.com queue. They share the yahoo.com domain block's VMTA assignment, throttling, and retry behavior, and PowerMTA accounts for them together.

The relationship between queue-to and per-domain source IP routing: queue-to is how an operator makes a family of related domains share a single routing configuration. Because the Yahoo family of domains all delivers through Yahoo infrastructure, they should share throttling and source IP routing, and queue-to is the mechanism. The yahoo.com domain block's virtual-mta directive assigns the source IP, and queue-to brings the rest of the family onto that same IP and throttling.

queue-to is essential for the ISP families: the Yahoo family (yahoo.com, ymail.com, aol.com, and now comcast.net and att.net after the 2025 consolidation), the Microsoft family (hotmail.com, outlook.com, live.com, msn.com), and any other group of recipient domains that share backend infrastructure. Routing them through a shared queue with queue-to makes their source IP routing and throttling reflect the reality that the ISP evaluates them together.

When to dedicate an IP to one ISP

A strategic question that per-domain routing enables: should an operator dedicate a source IP to a single ISP, a Gmail-only IP, a Microsoft-only IP?

The case for dedicating an IP to one ISP is reputation isolation. A Gmail-only IP builds a reputation specifically with Gmail. A reputation problem with one ISP does not spill onto sending to others, because they are on different IPs. The IP's reputation is cleanly attributable to one ISP's view.

The case against it, at lower volume, is the consistency requirement. A dedicated IP needs sustained consistent volume to build and hold reputation. Splitting a modest total volume across one IP per ISP can leave each IP with too little traffic to maintain its reputation.

Volume to each ISPRecommendation
High, consistent daily volume per ISPDedicated IP per ISP, full isolation
Moderate volumeFewer IPs, each handling multiple ISPs
Low or inconsistent volumeShared approach or VMTA pool rotation

The practical guidance: dedicate IPs per ISP only when the volume to each ISP is high enough to keep that IP consistently and substantially active. Below that threshold, a smaller number of IPs each handling multiple ISPs, or a VMTA pool with rotation, maintains reputation better than thinly spread per-ISP IPs.

The decision is the same volume-and-consistency calculation that governs whether to use a dedicated IP at all, applied per ISP. An operator with high Gmail volume but low Yahoo volume might dedicate an IP to Gmail and route Yahoo through a shared IP, matching the IP strategy to the volume per destination.

Interaction with VMTA pools

Per-domain routing and VMTA pools interact, and understanding the interaction prevents confusion.

A VMTA pool is a group of VMTAs that PowerMTA rotates among. A domain block can assign a pool rather than a single VMTA:

<virtual-mta-pool gmail-pool>
    virtual-mta gmail-ip-1
    virtual-mta gmail-ip-2
    virtual-mta gmail-ip-3
</virtual-mta-pool>

<domain gmail.com>
    virtual-mta-pool gmail-pool
    max-msg-rate 9000/h
</domain>

Here, gmail.com mail routes through the gmail-pool, and PowerMTA rotates among the three Gmail IPs. This combines per-domain routing (Gmail goes to the Gmail pool) with multi-IP rotation (within the pool, the three IPs share the load).

The design choice between a single VMTA and a pool per domain: a single VMTA per domain means one IP per ISP, maximum isolation, simplest accounting. A pool per domain means multiple IPs per ISP, which distributes the volume and provides redundancy if one IP develops a problem. The choice depends on the volume to that ISP: high volume justifies a pool of IPs, moderate volume is fine with a single IP.

The throttling interaction: when a domain block assigns a pool, the domain block's max-msg-rate applies across the pool, and per-IP rates can be set with source-ip-max-msg-rate to limit each IP within the pool individually. This lets the operator control both the total rate to the ISP and the per-IP rate.

Reputation isolation per destination

The strategic value of per-domain source IP routing is reputation isolation, and it is worth being explicit about what isolation does and does not achieve.

What per-domain routing isolates. Routing each major ISP through its own IP means each IP's reputation is built from and attributable to one ISP's view. If Gmail develops a negative view of the Gmail IP, that does not affect the Microsoft IP's standing with Microsoft, because Microsoft never sees the Gmail IP. A reputation incident is contained to the IP and the ISP involved.

What per-domain routing does not isolate. Per-domain source IP routing does not isolate the underlying causes of reputation problems. If the cause of a Gmail reputation problem is poor list quality or high complaint rates, that same poor list quality will eventually cause problems on the Microsoft IP too, because the underlying sending practice is the problem. Per-domain routing isolates the symptom (the IP reputation) but not the disease (the sending practice). It buys containment and diagnostic clarity, not immunity.

The diagnostic clarity is itself valuable: when each ISP is on its own IP, a reputation problem isolated to one IP tells the operator the problem is specific to that ISP's evaluation, which narrows the investigation. A reputation problem appearing across all the per-ISP IPs simultaneously tells the operator the problem is in the sending practice, not ISP-specific. The routing turns the pattern of which IPs are affected into a diagnostic signal.

Per-domain routing contains symptoms, it does not fix sending practices

An operator who routes each ISP through its own IP and then sends a poor-quality list will see the reputation problems appear one IP at a time as each ISP independently reaches the same negative conclusion. The per-domain routing does not prevent this; it just spreads the same problem across separate IPs. Per-domain source IP routing is a containment and diagnostic tool, valuable for isolating incidents and reading the pattern, but it is not a substitute for good list hygiene, proper authentication, and sound sending practices. Fix the sending practice; use the routing to contain and diagnose.

Diagnosing routing problems

When per-domain routing does not behave as configured, the diagnostic procedure:

Step 1: confirm what IP is actually being used. Query the PowerMTA accounting log for the source IP field on recent deliveries to the destination in question. Is the mail actually going out from the IP the configuration intends?

SELECT
    rcptDomain,
    coalesce(dlvProxyServerIp, dlvSourceIp) AS source_ip,
    count() AS deliveries
FROM pmta_accounting
WHERE type = 'd'
  AND timeLogged >= now() - INTERVAL 1 DAY
GROUP BY rcptDomain, source_ip
ORDER BY rcptDomain, deliveries DESC;

This shows which source IP each recipient domain's mail actually used. If gmail.com mail is going out from the wrong IP, the routing is not working as intended.

Step 2: check for an X-Virtual-MTA header overriding the config. If the application is injecting X-Virtual-MTA, that header overrides the config-based domain block routing. A common cause of unexpected routing is an X-Virtual-MTA header the operator forgot the application was setting. Check whether the application injects the header.

Step 3: verify the domain block matches the recipient domain. PowerMTA matches the recipient domain against the domain blocks. If the domain block is for gmail.com but the mail is to googlemail.com, the gmail.com block does not match. Verify the domain block names cover the actual recipient domains, and use queue-to to bring variants onto the right routing.

Step 4: check the queue-to chain. If a domain uses queue-to, verify the chain leads where intended. A domain queue-to'd to yahoo.com inherits the yahoo.com block's VMTA assignment; if that assignment is wrong, every queue-to'd domain inherits the wrong routing.

Step 5: verify process-x-virtual-mta if using headers. If the routing depends on X-Virtual-MTA headers, confirm process-x-virtual-mta yes is set on both the smtp-listener and the source. Without it, PowerMTA ignores the header and falls back to config-based routing.

Step 6: check the default domain block. If a recipient domain matches no specific domain block, it falls to the domain default block. If mail is unexpectedly going through the general IP, the recipient domain may not be matching the intended specific block and is hitting default instead.

Step 7: verify with pmta show settings. After a config change to routing, confirm with pmta show settings that the change took effect, because a config that parsed may not be applying as the operator intended.

The routing that the application was quietly overriding

An operator we worked with had carefully configured per-domain source IP routing: a domain block for gmail.com assigning a dedicated, well-warmed Gmail IP, similar blocks for the other major ISPs. The configuration looked correct. But the accounting log showed Gmail mail going out from the general IP, not the dedicated Gmail IP, and the operator could not understand why the domain block was being ignored. The cause was an X-Virtual-MTA header. The application, configured years earlier by a previous engineer, was injecting X-Virtual-MTA naming the general VMTA on every message, for every destination. Because X-Virtual-MTA overrides config-based domain block routing, every message went through the general VMTA regardless of the carefully written domain blocks. The domain blocks were not broken; they were simply being overridden by a header the operator did not know the application was setting. The fix had two options: remove the X-Virtual-MTA injection from the application so the config-based domain block routing would take effect, or change the application to inject the correct per-destination VMTA. They chose to remove the blanket header injection, since the recipient-domain-based routing they wanted was exactly what the config-based domain blocks did automatically. With the header gone, the domain blocks took effect, and Gmail mail started flowing from the dedicated Gmail IP as intended. The lesson: when per-domain routing does not behave as the config says it should, check for an X-Virtual-MTA header overriding it. The header always wins over the config, and an application quietly injecting one is a common and confusing cause of routing that ignores the carefully written domain blocks.

Per-domain source IP routing in PowerMTA is built on the domain block, which assigns a VMTA, and therefore a source IP, to each recipient domain. Config-based domain block routing is the natural mechanism because the recipient domain is exactly what PowerMTA can route on without application involvement. The X-Virtual-MTA header offers application-controlled routing for distinctions PowerMTA cannot see, and the two combine cleanly with each routing decision placed where the information lives. queue-to brings ISP families onto shared routing. The strategic question of dedicating an IP per ISP comes down to whether the volume to each ISP justifies it. The value of per-domain routing is reputation isolation, valuable for containing incidents and reading diagnostic patterns, though it contains symptoms rather than fixing sending practices. Operators who understand the mechanisms and place each routing decision deliberately get clean, predictable per-domain routing; operators who mix mechanisms without understanding the precedence get the confusing override behavior that the diagnostic workflow exists to untangle.

H
Henrik Larsen

Email Infrastructure Engineer at Cloud Server for Email. Designs per-domain and per-stream routing architectures for PowerMTA deployments across ESP clients. Related: smtp-listener Configuration, Domain Block Reference, Cold Email vs Bulk Separate Pools.