How to normalize bounce codes across providers?
Still have a question, spotted an error, or have a better explanation or a source we should cite?
Every mail server speaks SMTP but they don't all speak it consistently. A "user doesn't exist" error from Gmail looks different from the same error at a small corporate mail server. If you're processing bounce data from multiple ESPs or building your own bounce handling, normalizing those codes into consistent categories is how you make the data usable.
The underlying structure. SMTP responses have a three-part code: a basic status code (5xx for permanent failures, 4xx for temporary), an enhanced status code that adds more specificity (like 5.1.1 for "address not found"), and a text explanation. The enhanced code is your most reliable normalization target, because the text varies wildly between providers but the enhanced code is more standardized.
The core normalization categories most systems use:
- Invalid address (map from 5.1.0, 5.1.1, 5.1.2, 5.1.3): The address or domain doesn't exist. Treat as hard bounce, suppress immediately.
- Mailbox full (4.2.2, 5.2.2): Temporary if 4xx, potentially permanent if 5xx. Retry first, suppress after repeated failures.
- Policy rejection (5.7.0, 5.7.1, 5.7.2, 5.7.26): Reputation, content, or blocklist issue. Don't suppress the address. Investigate the sending domain or IP instead.
- Rate limit / connection refused (4.4.2, 4.7.0): Throttling from the receiving server. Back off and retry with slower sending speed.
- Message too large (5.2.3): Content size issue, not a list problem. Reduce attachment size or link to hosted content instead.
- Greylisted (4.5.1, 4.7.1 with greylist text): Temporary hold. Retry after the specified delay.
The challenge: providers often use the same code for different reasons or use non-standard text. Google Workspace and Outlook are the most consistent. Small hosting providers and self-hosted servers are the least predictable.
A practical approach: build your normalization around the enhanced code first, then use regex on the message text as a fallback to catch edge cases. Log the raw original response so you can refine your mapping over time as you encounter new variations.
If you're using an ESP rather than your own infrastructure, most platforms already do this normalization for you and surface simplified categories in their dashboard. Check whether "hard bounce," "soft bounce," and "block" are as granular as you need, or whether you need to export raw bounce logs for deeper analysis.
Need help making sense of a specific bounce pattern? Ask us and we'll decode it with you.
Contributors
Who worked on this answer
Every name links to their profile. Every company links to their site. Real people, real accountability.