Contents
Why bounce processing matters
Every message a sender delivers either reaches its recipient or bounces, and the bounces are not waste, they are information. A bounce tells the sender that an address is dead, or that a mailbox is full, or that a receiver rejected the message for a policy reason. Acting on that information, suppressing the dead addresses, reading the policy bounces as reputation signals, is what keeps a sending list clean and a sender's reputation intact. Bounce processing is the discipline of capturing the bounces and routing their information to the right action.
This guide exists because bounce processing in PowerMTA spans two parts that operators sometimes conflate: what PowerMTA does, capturing and categorizing bounces in the accounting log, and what the operator must build around it, the pipeline that reads those bounces and feeds suppression. The structure of this guide: why bounce processing matters, how PowerMTA records bounces, the important in-band versus out-of-band distinction, the bounce-after directive that decides when a retried message becomes a bounce, building the suppression pipeline, the relationship to the bounce categories, and the diagnostic workflow when bounce processing does not feed suppression correctly.
How PowerMTA records bounces
PowerMTA records bounces in its accounting log, the same log it uses for every delivery event. When a delivery attempt bounces, PowerMTA writes an accounting record marking the event as a bounce, with a record type distinguishing it from a successful delivery.
The bounce record carries what is needed to act on the bounce: the recipient address that bounced, the receiving domain, the SMTP code the receiver returned, the diagnostic text, the bounce category PowerMTA assigned by pattern matching, and the timestamp.
Bounce records are included in the accounting log through the records directive on the accounting file definition, which lists the record types to capture:
<acct-file /var/log/pmta/accounting.csv>
records d,b,t,rb,f
</acct-file>
The record types here include d for deliveries, b for bounces, t for transient failures, and others. For bounce processing, the b records are the bounces, and the configuration must include them so the bounces are captured.
The accounting record is the canonical capture of the bounce. PowerMTA's role in bounce processing is to record and categorize; the acting on the bounce, the suppression and the analytics, is the downstream pipeline the operator builds reading those accounting records. Understanding this division, PowerMTA captures, the operator's pipeline acts, is the foundation of getting bounce processing right.
In-band versus out-of-band bounces
A crucial distinction in bounce processing is between in-band and out-of-band bounces, because they reach the sender differently and are captured differently.
| Aspect | In-band (synchronous) | Out-of-band (asynchronous) |
|---|---|---|
| When it happens | During the SMTP transaction | After the message was accepted |
| How it arrives | An SMTP rejection PowerMTA sees | An email to the return path |
| Captured by | PowerMTA's accounting log automatically | Return-path mailbox processing |
An in-band bounce happens during the SMTP transaction. PowerMTA connects to the receiving server, attempts delivery, and the server rejects the message then and there with an SMTP error code. PowerMTA sees the rejection immediately and records it as a bounce in the accounting log. Most modern bounces are in-band, receivers reject bad mail during the SMTP conversation.
An out-of-band bounce happens after the SMTP transaction completed. The receiving server accepted the message during the SMTP conversation, returning success, but later could not deliver it and generated a non-delivery report, an email sent back to the message's return path address.
The handling difference matters. In-band bounces are captured automatically by PowerMTA's accounting log, because PowerMTA witnesses the rejection. Out-of-band bounces are not, because they arrive as separate email messages after the fact. Capturing out-of-band bounces requires processing the mail that arrives at the return path address, parsing those non-delivery reports to extract the bounced address and reason.
A complete bounce processing setup handles both. PowerMTA's accounting captures the in-band bounces. A return-path mailbox processing system, a system that receives and parses the bounce messages arriving at the return path, captures the out-of-band ones. An operator who configures only PowerMTA's accounting captures the in-band bounces, the majority, but misses the out-of-band bounces entirely unless the return-path processing is also built.
The bounce-after directive
The bounce-after directive controls how long PowerMTA keeps retrying a message before giving up and treating it as a permanent bounce.
When a delivery attempt results in a temporary failure, a 4xx response, a connection problem, PowerMTA does not bounce the message immediately. It queues the message for retry, because a temporary failure may succeed on a later attempt. But PowerMTA cannot retry forever, and bounce-after sets the limit: if a message has been undeliverable for the bounce-after duration, PowerMTA stops retrying and bounces it.
# Global bounce-after, with a per-domain override
bounce-after 4d12h
<domain example-isp.com>
bounce-after 5d
</domain>
The bounce-after value is a balance:
- Set too short, PowerMTA gives up on messages that would have delivered if retried longer, turning recoverable soft failures into premature bounces, a temporarily full mailbox, a briefly deferring receiver.
- Set too long, PowerMTA holds undeliverable messages in the queue excessively, consuming queue space and delaying the bounce notification downstream processing needs.
A common bounce-after value is a few days, often around four to five, giving transient problems ample time to resolve without holding genuinely undeliverable mail indefinitely. The directive can be set globally and overridden per domain block, so a domain with particular retry characteristics can have its own value.
The bounce-after directive belongs to bounce processing because it determines the moment a message transitions from being retried to being a recorded bounce, the moment it becomes a bounce that the suppression pipeline acts on.
Building the suppression pipeline
PowerMTA captures and categorizes bounces; turning those captured bounces into actual suppression is the pipeline the operator builds.
The suppression pipeline reads the bounce records from PowerMTA's accounting log, and the bounce messages from the return-path processing, and applies the suppression logic. The components:
Ingesting the accounting log. The pipeline reads the b records from the accounting log, the in-band bounces, getting the bounced address, the category, the code, and the diagnostic text.
Ingesting the return-path bounces. The pipeline also processes the out-of-band bounce messages arriving at the return path, parsing them for the bounced address and reason.
Applying the suppression logic. For each bounce, the pipeline decides whether to suppress the address, based on the bounce category. A hard bounce, a non-existent address, drives immediate suppression. A soft bounce does not suppress on a single occurrence, but a soft bounce that persists across many attempts may eventually warrant suppression. A policy or spam bounce generally does not suppress the recipient address, because it is a sender-side signal.
Maintaining the suppression list. The pipeline maintains the suppression list, the authoritative record of addresses that should not be mailed, and ensures that list is consulted before each send.
Closing the loop to sending. The suppression list must actually be applied: the sending application, before submitting a message to PowerMTA, checks the address against the suppression list and does not send to suppressed addresses.
The most common bounce processing failure is a setup where PowerMTA diligently captures and categorizes bounces in the accounting log, but the pipeline that turns those captures into actual suppression is incomplete or missing. The bounces are recorded perfectly, and nobody acts on them, so dead addresses keep being mailed campaign after campaign. Bounce processing is only complete when the pipeline closes the loop: the bounce captured by PowerMTA must flow through to the suppression list, and the suppression list must be consulted before the next send. A bounce sitting in the accounting log that never reaches the suppression list has accomplished nothing.
Bounce processing and the categories
Bounce processing depends on the bounce categories, because the category is what the suppression logic acts on.
PowerMTA categorizes each bounce by matching the bounce response against its bounce-category-patterns, assigning a category, bad mailbox, full mailbox, spam-related, policy, transient, and recording that category in the accounting record. The suppression pipeline reads that category to decide the action.
The relationship is direct: accurate categorization makes accurate suppression possible, and inaccurate categorization undermines it. A bounce miscategorized as soft when it is a dead address means the address is never suppressed; a bounce miscategorized as hard when it is a transient failure means a good address is wrongly suppressed.
This is why bounce processing and bounce categorization are connected concerns. The categorization, which custom ISP-specific patterns improve, is the quality of the input; the processing pipeline is what acts on that input. An operator building bounce processing should ensure the categorization is accurate for their receiving environment, supplementing the built-in bounce-category-patterns with custom patterns for their actual receiving providers, because the best-built suppression pipeline still produces wrong results if the categories feeding it are wrong.
The two together, accurate categorization plus a complete processing pipeline, are what good bounce handling requires. PowerMTA provides the categorization mechanism and records the result; the operator ensures the patterns are accurate and builds the pipeline that acts on the categorized bounces.
When bounce processing does not feed suppression
When bounce processing is not feeding suppression correctly, the symptom is usually that dead addresses keep being mailed, or that the bounce rate stays elevated. The diagnostic workflow:
Step 1: confirm PowerMTA is recording bounces. Check the accounting log for b records. Confirm the records directive includes bounce records and that bounces are appearing in the log.
Step 2: check whether out-of-band bounces are captured. Confirm the return-path mailbox is being processed. If only PowerMTA's accounting is feeding the pipeline, the out-of-band bounces are being missed.
Step 3: verify the pipeline ingests the accounting log. Confirm the suppression pipeline is actually reading the bounce records from the accounting log, and reading them promptly, not lagging.
Step 4: check the categorization. Examine whether bounces are landing in the correct categories. Bounces miscategorized into a generic category may not be triggering suppression. This points to needing custom bounce-category-patterns.
Step 5: verify the suppression logic. Confirm the pipeline's suppression logic is acting correctly on the categories, suppressing hard bounces, handling soft bounces appropriately, not over-suppressing.
Step 6: confirm the suppression list reaches the sender. Verify the suppression list is actually consulted before each send. A suppression list that is maintained but not checked at send time accomplishes nothing.
Step 7: check the bounce-after value. If messages seem to bounce too quickly or linger too long, review the bounce-after directive.
An operator we worked with was troubled by a bounce rate that stayed stubbornly high across campaigns. They were confident their bounce processing was working, because they could see bounces being recorded, the accounting log was full of b records, every bounce neatly captured with its category, its code, its diagnostic text. PowerMTA was clearly doing its job. Yet the same addresses kept bouncing on campaign after campaign, which should not happen if dead addresses were being suppressed. The investigation traced the pipeline. PowerMTA was recording the in-band bounces perfectly. The bounce-category-patterns were categorizing them reasonably. But the pipeline that was supposed to read those bounce records and feed the suppression list had a gap: it had been built to ingest the accounting log, but at some point the accounting file path had changed as part of an unrelated configuration update, and the pipeline was still looking at the old path. So the pipeline was reading an accounting file that was no longer being written to. PowerMTA was capturing every bounce in the new accounting file; the suppression pipeline was reading an old, stale file and finding nothing. The bounces were captured and the suppression pipeline was running, but the two were no longer connected. The result was that for the period since the path change, no bounce had reached the suppression list, dead addresses were never suppressed, and every campaign re-mailed all of them, keeping the bounce rate elevated. The fix was to point the pipeline at the current accounting file path, after which the captured bounces flowed through to suppression, the accumulated dead addresses were suppressed, and the bounce rate dropped. The lesson is the central warning of this guide: capturing bounces is not the same as acting on them. PowerMTA can record every bounce flawlessly, and if the pipeline from the accounting log to the suppression list is broken, even by something as small as a stale file path, the bounces accomplish nothing. Bounce processing must be verified end to end, from the bounce PowerMTA records to the suppression actually applied at send time.
PowerMTA bounce processing has a clear division of labor: PowerMTA captures bounces in the accounting log and categorizes them, and the operator builds the pipeline that reads those captured bounces and feeds the suppression list. Getting it right means handling both in-band bounces, which PowerMTA's accounting captures automatically, and out-of-band bounces, which require return-path mailbox processing; setting a sensible bounce-after value so messages transition from retry to bounce at the right time; ensuring the bounce categorization is accurate, which custom ISP patterns support; and above all building a complete suppression pipeline that closes the loop, so a bounce captured by PowerMTA flows through to the suppression list and the suppression list is consulted before the next send. Operators who build and verify the whole pipeline end to end get clean lists and controlled bounce rates; operators who configure PowerMTA's capture but leave the pipeline incomplete find their bounces recorded perfectly and acted on not at all.