Knowledge base

How the policy for a receiver is assembled

critical

<domain> matching and merging
The most precise match wins, not the last one in the file

Receiver blocks are written not one per domain but by pattern, and several usually match a single message. The engine does not pick one of them but merges them — from the most general to the most precise.

The order in the file means nothing. The manual says this twice, and for good reason: in almost all configuration formats the last entry wins, but here the most precise one does. The <domain *> block can be written first, last or in the middle: it will still remain the base on top of which the others are laid.

What merging looks like in practice. An example from the manual: three blocks in a row — discard.port25.com, *.port25.com and [*.]port25.com. A message to discard.port25.com gets bounce-after 1h from the first block, log-commands yes from the second and everything else from the third. No setting was lost and none canceled another entirely — each came from where it was written most precisely.

The difference from sender matching. The merging mechanism is exactly the same as for source-matching, but it decides something else: there — whether the message will be accepted; here — at what rate, with how many connections, with which retries and with what encryption requirement it will be carried.

The pattern forms are described separately — there are five of them, and one is a trap; see the config-syntax-types page.

The main trap is the asterisk with a dot. The pattern *.port25.com matches only subdomains and does not match port25.com itself. The manual illustrates this with its own example: commands are logged for all proper subdomains and are not logged for the domain as such. The form that catches both is written differently — [*.]port25.com. The difference is two brackets, and the consequence is that a policy written for a large receiver does not apply to the receiver itself.
What the Hub does. It assembles the receiver policy from provider groups and the warm-up state and writes it as a <domain *> block inside the sending address block: rate, backoff mode, retry schedule. This way each address gets a policy of its own — different addresses are at different warm-up stages.

The Hub does not yet write patterns more precise than the asterisk: the split by provider lives in its scheduler, not in the node configuration. When provider profiles make it into the config, they will have to be written in the [*.]domain form — precisely because *.domain does not catch the domain itself.

Recommended values

The mechanism has no values of its own — the directives’ values are what merge. The choice is not between values but between pattern forms:

Form What it catches When to write it
* all domains the base: what holds for everyone
[*.]domain the domain and all its subdomains a receiver profile — the usual choice
*.domain only subdomains, not the domain itself rarely: when the domain and subdomains must be separated
exact name one domain an exception for one receiver
[ip/mask] domains written as four numbers address literals, [0/0] — all of them

The rule is simple: [*.] almost always, *. almost never. The second form is needed exactly when different policies are intended for the domain and its subdomains — and then both forms are written side by side so that the intent is visible.

The table and the rule for choosing a form are ours. From the manual here are the merge order itself, the independence from order in the file, the set of forms and the example with three port25.com blocks.
Example configuration
# the order of lines means nothing — what matters is the pattern's precision
<domain discard.port25.com>     # only this host
    bounce-after 1h
</domain>
<domain *.port25.com>           # subdomains, but NOT port25.com
    log-commands yes
</domain>
<domain [*.]port25.com>         # both the domain and its subdomains    bounce-after 4d
</domain>
The manual’s example in full. A message to discard.port25.com gets an hour to bounce from the first block, the command log from the second and everything else from the third. A message to port25.com itself gets four days and no command log — the middle block does not catch it.
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▶

Writing an asterisk with a dot while meaning the domain and its subdomains

§ 3.3.10

What it costsA pattern with an asterisk and a dot does not catch the domain itself. A policy written for a large receiver does not apply to its main domain — and that is where almost all the mail goes.
How to spot itThe settings are visible in the file, but the queue settings command prints defaults for the domain itself and what was written for a subdomain.
How to do it rightWrite [*.]domain. Keep the asterisk form only where different policies are intended for the domain and its subdomains.

Rearranging blocks in the hope of changing priority

§ 3.3.10

What it costsThe order in the file plays no part in matching at all. Rearranging changes nothing, time is wasted — and a feeling remains that the engine behaves unpredictably.
How to spot itThe block has been moved to the beginning or end of the file, and the behavior is the same.
How to do it rightChange not the position but the pattern’s precision: for a setting to win, it has to be written in a narrower block.

Looking for the effective policy in a single block

§ 3.3.10

What it costsIt is not in any single block: the policy is the result of merging several blocks and several levels. Reading one block gives part of the picture and the confidence that you see everything.
How to spot itIn conversation you hear “for this receiver we have…”, while the engine prints a different value.
How to do it rightLook at the queue settings output — it is the result of the merge. Read the file after it, not instead of it.
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.
Inheritance
Merging goes from the general pattern to the exact one, and the exact one overrides the general one setting by setting, not block by block. A second dimension is added to this: a receiver block can sit at the node level, inside a pool and inside a sending address — then the patterns are combined first and the levels second, and the narrowest level turns out to be the strongest. It is picked up by pmta reload.
How to check on the node
Reading the merge from the file is the surest way to get it wrong. The engine prints the effective policy:
pmta show settings discard.port25.com/mta-news-1
pmta show settings port25.com/mta-news-1
Two commands in a row, for a domain and for its subdomain, are the fastest way to catch the asterisk trap: if the lines differ where they should not, the pattern was written in the *.domain form instead of [*.]domain.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Troubleshoot deliverability · Tune the pace for a provider
Priority
critical