The most expressive of the six methods and the only one that does not need the sender’s consent. The rule list is declared once with a <pattern-list> block and attached to a source with the pattern-list directive. Inside the list, rules match the envelope return address (mail-from), the recipient address (rcpt-to) or an arbitrary header (header) — and each names a stream or pool.
Order matters and is stated: the first match wins. That means the list is not a set of independent rules but a priority queue. The most likely patterns are put first, and a rule added at the end may never fire.
Exactly one list is attached to a source. Everything that source needs has to be expressed inside it; for several platforms on one source — in one shared ordered list.
Conditional rules are allowed. A rule can open a nested list — “the return address is this AND the recipient is that” — with an asterisk meaning “everything else.” A separate technique is call-to:, a jump to another named list.
The dialect is Perl regular expressions (PCRE), and by default they are case-insensitive. Case sensitivity can be restored with the (?-i) modifier inside a pattern.
The Hub’s rule order is flat: one per domain, no overlaps, so “first match” creates no surprises here. The Hub does not write recipient rules — precisely because of the behavior with several addressees.
The Hub rewrites the return address to bounce@bounce.<domain> for bounce reception, but the rules match the original one: verified on a node on Sep 15, 2026 — messages submitted with the shared login and no X-Virtual-MTA went through the streams of their own domains, while accounting already showed the rewritten address for them.
The mechanism has no values of its own: the values are the rules themselves. What is worth remembering when putting a list together:
| What to match | When to use it | What you risk |
|---|---|---|
| return address | almost always: it is stable and belongs to you | nothing |
| header | when only the header distinguishes the sender | a header is easy to change on the sender’s side |
| recipient | only for messages with one addressee | with several recipients the stream is taken from the first match |
A rule can set not only a stream but also the recipient priority (recipient-priority=N, scale 0–100, default 50) — separately or together with the stream.
# the manual’s order: the list is declared above the source that refers to it <pattern-list mta-hub-senders> mail-from /@shop\.example\.com$/ virtual-mta=shop-example-com mail-from /@news\.example\.com$/ virtual-mta=news-example-com </pattern-list> <source {pmta-auth}> pattern-list mta-hub-senders default-virtual-mta mta-hub-pool </source>
what people get wrong and how it ends3 mistakes▶
§ 3.3.14.3
§ 9.4.2
§ 3.3.7.42
2 relations
pmtaacctfind --output csv[vmta,orig,rcpt] /var/log/pmta/acct-*.csv | head -50
3 articles
◇Six ways to choose a stream and the order among themA message’s stream is set by a merge variable, an API call, a header, a pattern rule, a listener and a source default — the manual lists them by precedence.◇Reserved merge variable namesSome merge variable names are taken by the engine: you cannot give your own variables these names.◇A license for a fleet, not for a serverThe license is not bound to a server: it is installed on as many machines as the instance limit allows, and the nodes send volume statistics to the vendor every hour.