Knowledge base

PMTA knowledge base›Block <domain>›Directive§ 3.3.10.100

smtp-hosts

<domain>

Explicit delivery servers instead of the usual DNS lookup
in the configuration this is a linesmtp-hostsinside the block <domain>
Where to connect if not where DNS points

Normally the node asks DNS for the recipient domain’s MX records and follows them. This line replaces or modifies that lookup: you name the servers yourself — by names, addresses or an instruction to take the MX records of another domain.

The list is structured like real MX records. A comma separates hosts within one preference level — the node rotates through them; a semicolon starts the next level, which is used only if the first one does not respond. An address is written in brackets — [10.1.1.1] or [IPv6:2001::1] — and a port can be given after a colon.

A separate kind is lookup-mx:. It does not cancel DNS but redirects the question: “take the MX records of this domain.” This is how combined queues whose names do not exist in DNS work: queue-to and wildcard combining do not work at all without it.

The main trap is that everything that depends on the MX lookup is quietly switched off. There is no MX query anymore, which means bounce-upon-no-mx does not trigger with any value: there is nothing to check the absence of a record against. In the same way, all decisions tied to iterating over MX records stop working. The line looks like “refining the route,” but in fact it removes a whole layer of checks.
What the Hub does. It does not write it. The Hub leaves the route to the receiver to the domain name system: a hand-typed server list goes stale silently — the receiver changes gateways, and the configuration keeps knocking on the old ones. The line will be needed when the Hub learns to combine queues: there it is indispensable.
Recommended values

lookup-mx: is preferable to a list. It does not go stale: if the receiver changes gateways, the node learns about it from DNS. An explicit list cannot do that.

Preference levels are not decoration. Everything listed with commas is used by the node in rotation; it moves to the next level only when the previous one is unavailable. A list with one level is load balancing, with two levels it is a backup.

Set the port here, not separately. A port given after a colon overrides default-smtp-port for this recipient domain.

The advice to prefer redirecting the MX query to another domain is ours. From the manual here come the level syntax, writing addresses in brackets, specifying the port, the lookup-mx: form and clearing with an empty string.
Example configuration
# a combined queue has no domain of its own in DNS — we take someone else's MX
<domain hotmail.queue>
    smtp-hosts lookup-mx:hotmail.com</domain>

# two in rotation, then a backup address with a non-standard port,
# then the last resort
<domain email.test.com>
    smtp-hosts h1.test.com, h2.test.com; [10.1.1.1]:2525; last.test.com</domain>
The second block has three preference levels: h1 and h2 work in rotation, the address is used only when they are unavailable, and last.test.com — when the first two levels are unavailable.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends3 mistakes▶

Typing in a list of addresses instead of lookup-mx:

our experience

What it costsThe receiver moves, changes gateways, retires addresses — while the configuration keeps knocking on the old ones. DNS knows about this, but nobody asks it anymore.
How to spot itConnections to the recipient domain stopped being established, while dig MX returns different names than those in the configuration.
How to do it rightReplace the list with lookup-mx: and the name of the real domain, keeping explicit addresses only where DNS really does not return what is needed.

Setting a list and counting on a refusal for a missing MX

§ 3.3.10.69

What it costsNo MX query takes place, and bounce-upon-no-mx stays silent with any value. The protection is believed to be on, but it is not there.
How to spot itThe missing-MX refusal line is set but never triggers.
How to do it rightRemove one of the two lines: they describe mutually exclusive ways to reach the receiver.

Listing backup servers with commas

our experience

What it costsA comma means one preference level: the node rotates through all the listed servers. A server intended as a backup gets its share of the regular flow.
How to spot itThe receiver’s backup server gets messages constantly, not only when the primary fails.
How to do it rightSeparate levels with a semicolon, not a comma.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Reference data
Syntax
smtp-hosts <host-list>
Values
a list of hosts or addresses; a comma separates hosts of one preference level, a semicolon starts the next level; an address in square brackets, a port after a colon; or lookup-mx: and a domain name; an empty string removes the inherited value
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<domain>
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The value merges across <domain> blocks from general to specific: the best-matching block wins, not the last one in the file. An empty string (“”) removes the inherited value — this is how a domain gets its usual DNS lookup back if the list is set by a wildcard block. It is picked up by pmta reload; it does not affect open connections.
How to check on the node
The effective list is printed by the queue settings command; where messages actually went is visible from the receiver address in accounting:
pmta show settings hotmail.queue/vmta1 | grep -i smtp-hosts
dig +short MX hotmail.com | sort -n
The second command shows what DNS would return: the mismatch with the explicit list is the price of a manual route. The Hub does not set routes and does not track this mismatch.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Configuration lifecycle