critical
Every accounting record about a bounce has a bounceCat field — the category. Until this section of the manual it looks like a closed dictionary of seventeen values: bad-mailbox, quota-issues, spam-related and others. It is not.
Rules choose the category, and you can write your own rules. An unnamed <bounce-category-patterns> block is evaluated before the vendor defaults from the defaults file; a named block can be tied to a specific receiver, and it is evaluated before both. The order is: the receiver’s rules, then your own general ones, then the vendor’s.
A rule has three parts. An optional session stage, a regular expression and a category name: rcpt-to /invalid recipient/ recipient-related. There is currently only one stage — rcpt-to; it limits the match to replies to the command that carries the recipient address. Without a stage, replies from any stage match.
Your own category names are explicitly allowed. The dictionary is not closed: you can create a category the vendor does not have, and it lands in accounting as is. This is exactly what makes the mechanism valuable — classification moves to where the reply arrives, before the accounting record is written.
Matching works the same way as in SMTP pattern lists — the manual refers to <smtp-pattern-list> for the details.
The list of hard categories is one for the whole Hub — bad-mailbox, inactive-mailbox, bad-domain (PmtaEventNormalizer::HARD_CATEGORIES). It used to lie in copies in four places and diverged exactly on no-answer-from-host; now that category is soft everywhere.
This mechanism is a way to remove the translation step entirely. If the rules are written by us, the node can write our category, taken from the receiver’s words, straight into accounting, rather than the vendor’s one that then has to be interpreted. One step between a bounce and a decision about the address disappears.
What is worth creating as your own rules:
| Category | What to catch | Why |
|---|---|---|
| “no such address” | no such user, unknown recipient, 5.1.1 at the recipient stage | direct grounds to remove the address |
| “mailbox full” | mailbox full, over quota | the mailbox is alive, the address must not be removed |
| “held for reputation” | spam, blocked, spamhaus | not about the address at all — about us |
| “server is silent” | timeouts and dropped connections | neither about the address nor about reputation |
The rcpt-to stage is worth specifying almost always where the address is concerned. A “no such user” reply given at the data stage refers to the whole message, not to a single recipient, and must not be treated as a verdict on the address.
Your own category name is better than the vendor’s when the meaning matches none of the seventeen vendor ones: a name of your own is more honest than someone else’s stretched to fit.
# your own rules are evaluated before the vendor's <bounce-category-patterns> /mailbox +(is +)?full/ quota-issues rcpt-to /[45]\.\d+\.\d+/ recipient-related</bounce-category-patterns> <bounce-category-patterns custom> /no longer available/ quota-issues </bounce-category-patterns> <domain hotmail.com> bounce-category-patterns custom </domain>
what people get wrong and how it ends3 mistakes▶
§ 12
§ 11.7.1
§ 11.7.1
3 relations
Permanently bouncedThe patterns that assign this category. § 12.6The receiver is misconfiguredThe category is assigned by a pattern, and the pattern list can be extended with your own patterns and your own names. § 12.6Connection problemThe category is assigned by a pattern, and the pattern list can be extended with your own patterns and your own names. § 12.6The domain does not existThe category is assigned by a pattern, and the pattern list can be extended with your own patterns and your own names. § 12.6The address does not existThe category is assigned by a pattern, and the pattern list can be extended with your own patterns and your own names. § 12.6Held back over contentThe category is assigned by a pattern, and the pattern list can be extended with your own patterns and your own names. § 12.6
pmtastats bounce-categories --bounceCat all /var/log/pmta/acct-*.csv grep -n -A6 '^<bounce-category-patterns' /etc/pmta/config
3 articles
◇Parsing bounces that arrive as messagesBounce reports that arrive as messages are parsed by a separate processor — and it runs before the complaint processor.◇Two inbound report processors and what to do with themBounces by message and complaints are parsed by two identically structured blocks; each has its own address list and its own pair of decisions about the message’s fate.◇Address lists — named and unnamedA list of addresses, domains, patterns or hashes; a named one is attached by directives such as suppression, an unnamed one lives inside an inbound mail processor.