Knowledge base

header

<pattern-list>

A rule on a named message header that selects a stream or a priority
in the configuration this is a lineheaderinside the block <pattern-list>
Selecting a stream by any message header

The only rule in the list with a parameter: first the header name, then the pattern, then the result. Any header can be matched — a service one like x-eval or an ordinary one like subject and from.

The entire header content is matched as a whole — along with the spaces, tabs and line breaks left in it. The manual puts special emphasis on this: if you anchor the pattern with ^ and $, leave room for spaces — the \s metacharacter is there for that.

The From header is not the return address. A rule on from matches what the recipient sees, and the sender is free to write anything there. For reliable routing, the envelope is used, not the header.

The main trap is the space after the colon. The header arrives as value, with a leading space, and the pattern /^value$/ will never match. The correct form is /^\s*value\s*$/. The mistake is silent: the rule looks correct and simply does not fire.
What the Hub does. It does not write it. Its own submission names the stream with the X-Virtual-MTA header — a separate mechanism that stands higher on the ladder and needs no list. A header rule remains for a platform that cannot set service headers but does set its own identifying one: then that header becomes the routing key.
Recommended values

What to match and what it risks:

Header Suitable Caveat
the platform’s own service header yes the most stable option
subject sometimes changes from campaign to campaign
from with caution it is not the envelope: the sender writes whatever they want there

A mandatory habit is to allow spaces around the value: /^\s*pattern\s*$/. The header content arrives as is, including spaces after the colon and line breaks inside long values.

The requirement to account for spaces and the \s metacharacter comes from the manual, as a separate warning. The “what to match” table is ours.
Example configuration
# the platform's identifying header as a routing key
<pattern-list partner-selector>
    header x-platform /^\s*partner-crm\s*$/ virtual-mta=partner-crm    mail-from /@partner\.example\.com$/ virtual-mta=partner-crm
</pattern-list>
The spaces around the value are allowed on purpose: the header arrives with a leading space after the colon. The second rule is insurance in case the platform stops setting its header.
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 ends2 mistakes▶

Anchoring the pattern without allowing for spaces

§ 3.3.14.1

What it costsThe header content arrives together with the spaces after the colon. The pattern /^value$/ will never match, and the rule will be silently skipped.
How to spot itThe rule is in the configuration, the header is in the message, and the stream is taken from the default.
How to do it rightWrite /^\s*value\s*$/. The manual gives this as a separate requirement for header rules.

Routing by the From header

§ 3.3.14.2

What it costsThe From header is what the recipient sees, and the sender fills it in themselves. A route built on it changes along with the message design and is not protected by anything.
How to spot itAfter a change in the mailing’s design, messages start going out through a different stream.
How to do it rightRoute by the envelope return address — it is set at submission and visible in accounting in the orig field.
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
header <regex-rule>
Values
a header name, a pattern in slashes and a result — virtual-mta=name, recipient-priority=N or call-to:name
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<pattern-list>
How many times
may be repeated
Everything here comes from the manual, with the section.
Inheritance
The rule has no inheritance: it acts inside its <pattern-list> block. What is inherited is the reference to the list — pattern-list is written in <source> and merges by the source rule, with a narrow block replacing the list entirely.
How to check on the node
Headers are not written to accounting, so the check has to be done by the result — which stream was selected:
pmtaacctfind --output csv[vmta,orig,jobId] /var/log/pmta/acct-*.csv | head -30
If the stream comes from the default while the header is in the message, the cause is almost always spaces: a pattern anchored without \s does not match the actual header content.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Sending address rotation · Connect a sending platform