Hard Bounces, Soft Bounces, And What To Do With Each
The Mythic Intel Team · Jul 15, 2025 · 6 min read
A hard bounce is a permanent delivery failure that you must never retry and must suppress immediately; a soft bounce is a transient failure that you should retry with backoff for a bounded window. The single digit that decides which one you are looking at is the leading number of the SMTP reply: 5xx is permanent, 4xx is transient. The enhanced status code that rides alongside it, defined in RFC 3463, tells you precisely why. Getting this distinction right is the difference between protecting your sending reputation and quietly destroying it by pounding dead addresses.
Bounce discipline is not bookkeeping. Mailbox providers watch how a sender reacts to failures. Continuing to send to addresses that returned 5.1.1 user unknown is one of the clearest signals that a sender is working from a stale or purchased list, and it drags down the reputation that governs whether your good mail reaches the inbox.
Reading the codes: basic and enhanced
Every SMTP failure carries two numbers. The basic reply code (three digits) and the enhanced status code (class.subject.detail) from RFC 3463. Read the enhanced code left to right:
- The first digit is the class.
2is success,4is a persistent transient failure (valid message, temporary condition, retrying later may work), and5is a permanent failure (not resolvable by resending in the current form). - The second digit is the subject: what the failure is about.
.1.is addressing,.2.is mailbox status,.4.is network or routing,.7.is security or policy. - The third digit is the specific detail.
A real rejection at the SMTP layer:
RCPT TO:<[email protected]>
550 5.1.1 The email account that you tried to reach does not exist.
550 plus 5.1.1 is unambiguous: class 5 permanent, subject 1 addressing, detail 1 bad destination mailbox. The address does not exist and never will at this server. That is a hard bounce. Compare a transient one:
RCPT TO:<[email protected]>
452 4.2.2 The recipient's inbox is over its storage limit.
452 plus 4.2.2 is class 4 transient, subject 2 mailbox, detail 2 mailbox full. The address is fine; the mailbox is temporarily over quota. That is a soft bounce. Retry it later.
The codes that matter most in practice:
5.1.1bad destination mailbox (user unknown): hard. Suppress.5.1.10recipient address is a non-existent domain or null MX: hard. Suppress.5.2.1mailbox disabled, not accepting messages: usually hard, occasionally transient if the box is only temporarily disabled.5.7.1delivery not authorized, message refused: hard, often a policy or block decision. Suppress and investigate the block.4.2.2mailbox full: soft. Retry.4.4.1connection or no answer from host: soft. Retry.4.7.xsecurity or reputation defer (the family Gmail's reputation throttling lives in): soft. Retry with backoff and fix reputation.
When the message itself, not the recipient, generates the failure (a delivery report mailed back to your bounce address), it arrives as a DSN formatted per RFC 3464, with the enhanced code in a Status: field you parse programmatically:
Final-Recipient: rfc822; [email protected]
Action: failed
Status: 5.1.1
Diagnostic-Code: smtp; 550 5.1.1 No such user
What to do with each
The rule is simple and the discipline is in applying it without exception.
Hard bounce, any 5.x.x: stop sending to that address now, and add it to a suppression list so no future campaign or transactional send can target it. A suppression list is the permanent record of addresses you have proven are undeliverable; every send checks it before queuing. The one nuance is to distinguish recipient-permanent codes (5.1.1, 5.1.10) from sender-side block codes (5.7.1), because the second kind means a provider has blocked you and the fix is your reputation, not the address.
Soft bounce, any 4.x.x: keep the message queued and retry on a widening schedule, then give up and treat it as failed after a bounded window:
attempt 1 t+0
attempt 2 t+15m
attempt 3 t+1h
attempt 4 t+4h
attempt 5 t+12h
attempt 6 t+24h
expire t+48h to 72h -> generate failure DSN, count as a bounce
The 48 to 72 hour ceiling is the long-standing convention for how long an MTA holds a deferred message. After it expires, the soft bounce becomes a delivery failure. A useful operational rule is to convert an address to suppressed after it soft-bounces on several consecutive distinct sends, because a mailbox that is "full" every time you send for two weeks is effectively dead.
Why this protects reputation
Mailbox providers infer list hygiene from bounce behavior. A clean sender's hard-bounce rate sits low because dead addresses get suppressed after their first 5.x.x. A sender that keeps mailing addresses that already returned 5.1.1 shows a high and persistent invalid-recipient rate, which is a textbook signature of a bad list and pushes mail toward spam folders or outright blocks. The complaint and bounce signals feed the same reputation system that governs inbox placement, and the 2024 bulk-sender requirements from Google and Yahoo make the stakes explicit: keep the spam complaint rate under 0.3 percent and authenticate everything, or lose inbox access. Disciplined bounce handling, suppress hard bounces immediately and retry soft bounces only within a bounded window, is what keeps the invalid-recipient signal low enough that the rest of your authentication and content work actually pays off.
Process the bounces in real time, not weekly. Parse the enhanced status code rather than regex-matching the human-readable text, because the prose varies by provider while the class.subject.detail triple is standardized. And separate your transactional and bulk streams so a reputation hit from one does not contaminate the other.
Saying it out loud
In an interview: "The leading digit decides the action: 5xx is a hard bounce, suppress it permanently; 4xx is a soft bounce, retry with backoff and expire it after about 48 to 72 hours. I parse the RFC 3463 enhanced code, class.subject.detail, not the free text, so 5.1.1 is a dead mailbox to suppress while 4.2.2 is a full mailbox to retry, and I distinguish recipient-permanent codes from sender-block codes like 5.7.1. The whole point is reputation: providers read your hard-bounce rate as a proxy for list quality, so suppressing dead addresses on the first permanent failure is what keeps the rest of the deliverability stack working." That answer shows you treat bounce handling as a reputation control, not an afterthought.