Deliverability

Reading a bounce: hard, soft, and the ones that are neither

A bounce is an SMTP status code, not a label. What 5xx and 4xx actually mean, where the hard/soft split breaks down, and what to suppress versus retry.

By Mateo Duarte ·

A 5xx bounce does not always mean the address is dead, and a 4xx does not always mean try again later. What actually comes back is an SMTP reply code and a diagnostic string, and “hard” and “soft” are a summary someone laid on top afterward. A reputation block is a 5xx. A greylist delay is a 4xx that succeeds on the second try. Suppressing every 5xx address throws away subscribers whose only problem was you, not them. Microsoft’s own bulk sender enforcement is a clean real-world example of a reputation block: since April 2025, an unauthenticated high-volume sender is refused at connection with a 5xx, not filtered into a folder, as Gmail, Yahoo and Microsoft’s bulk sender rules covers.

The three-digit code, and what governs it

Every SMTP reply starts with a three-digit code, and RFC 5321 only treats the first digit as a hard rule. A 2yz code means the command succeeded. A 4yz code is a Transient Negative Completion reply: rejected, but the condition is temporary and the client should retry. A 5yz code is a Permanent Negative Completion reply: rejected, and the client should not repeat the exact request. That is the entire hard/soft split as SMTP itself defines it, and it says nothing about why the receiver refused you.

The why usually rides along as an enhanced status code, a second string in the form X.Y.Z defined by RFC 3463 and put under an IANA registry process by RFC 5248, which set up how new codes get registered without replacing 3463’s definitions. X repeats the class (2 success, 4 persistent transient failure, 5 permanent failure), Y names a subject such as addressing, mailbox, network, or policy, and Z narrows it further. 550 5.1.1 is a permanent failure registered as “bad destination mailbox address”: the mailbox does not exist. 550 5.7.1 is also a permanent failure, but its registered meaning is “delivery not authorized, message refused”, the result of per-host or per-recipient filtering. Same first digit, same “permanent”, opposite next step.

Not every server sends the enhanced code, and the ones that do vary in wording for the same underlying cause. The three digits are close to universal. The diagnostic text after them, unstructured prose written by whoever configured that mail server, is where you actually learn what happened.

Code families: what they mean, what to do

Code familyWhat it usually meansWhat to do
5.1.0 / 5.1.1 (bad mailbox)The address does not exist, or never did.Suppress the address now.
5.2.x (mailbox unavailable)The account exists but is disabled or closed for good.Suppress the address now.
5.7.1 and the rest of 5.7.x (policy)The receiver refused you: an IP or domain reputation block, or a content filter. The address may be reachable from anywhere else.Fix your sending. Leave the address alone.
4.2.2 (mailbox full)The recipient’s inbox is temporarily over quota.Retry on the normal schedule.
4.4.1 / 4.4.4 (host unreachable, can’t route)The receiving server was busy, down, or briefly unresolvable.Retry on the normal schedule.
4.7.x (temporary policy)A deliberate delay, the same policy subject as 5.7.x but in its temporary form. Greylisting lives here.Retry. It is designed to succeed.
No enhanced code, opaque text onlyThe provider didn’t give you a machine-readable reason.Read the diagnostic string by hand before deciding anything.

The policy rows do the most damage when they get flattened into “hard” and “soft”. A reputation block looks identical to a dead mailbox in a dashboard that only shows the leading digit: both are 5xx. Suppressing the address fixes nothing about the block and costs you a subscriber who was reachable the whole time. Greylisting looks identical to a broken server in the same dashboard: both are 4xx. A sender that gives up after one 4xx instead of retrying never delivers to a server running greylisting at all, which is the point: greylisting exists to filter out senders that don’t retry.

SES’s own vocabulary, and where it diverges

Amazon SES doesn’t hand you the raw SMTP exchange. It classifies each bounce into a bounceType of Permanent, Transient, or Undetermined, with a bounceSubType underneath, published in its Amazon SNS bounce notifications. Permanent/General is SES’s name for a hard bounce, carries a warning that repeat offenses can get your sending paused, and is the subtype tied to suppression-list behavior. The Transient subtypes, General, MailboxFull, MessageTooLarge, ContentRejected, AttachmentRejected, are all framed as retryable, with no suppression language attached. Undetermined is SES’s way of saying “not enough information”: the provider sent a bounce, but SES couldn’t parse a reason out of it, and the raw bounce text is where the actual reason lives.

That’s a coarser picture than the raw SMTP one, and it has no bucket for a reputation block. SES’s list of Permanent subtypes covers a missing address, an unretrievable address, an address already on a suppression list, and an unsubscribed recipient. A 5.7.1 policy refusal from a receiver doesn’t match any of those, so it falls into Permanent/General by elimination, the same bucket as a dead mailbox, and AWS’s own worked example for that subtype is a diagnostic string as plain as smtp; 550 user unknown. SES tells you it’s permanent. Whether it’s the address or your reputation is still on you to read.

One place SES diverges on timing rather than meaning: it doesn’t necessarily notify you the instant a soft bounce happens. AWS’s own documentation says that when a message soft bounces, SES keeps retrying delivery for a period and only sends a bounce notification once it gives up, unlike a hard bounce, which is reported right away. A notification-driven bounce dashboard is already averaging over a retry window the underlying SMTP conversation didn’t have.

A bounce is not a complaint, and silence is neither

A bounce means the receiving server didn’t accept the message, and said so during the delivery attempt. A complaint means the opposite failure: the message was accepted and delivered, and the recipient (or their provider, via a feedback loop) reported it as spam afterward. SES keeps them as separate notification types for exactly that reason: notificationType is Bounce, Complaint, or Delivery, never combined into one notification, because a hard bounce and a complaint call for the same response, suppression, but they’re different evidence about a different failure. Publishing either one to Amazon SNS meters separately from the send itself, as covered in what Amazon SES actually costs.

A third outcome produces neither signal: the receiving server accepts and delivers the message straight into the spam folder, or into Promotions. Nothing rejected it, so there’s no bounce. Nobody clicked “report spam”, so there’s no complaint. The only record of it is what the recipient sees, which is why a rising unopened rate next to a flat bounce rate usually points at a folder problem, not a delivery failure. See why emails land in Promotions or spam for the spam case, and why your emails land in Promotions for the other one, which isn’t a deliverability failure at all.

What to actually do with one

Suppress on the first bounce only when the code says the mailbox itself is gone: 5.1.x, 5.2.x, or SES’s Permanent/General. EmailFig does this automatically, and globally across every account, the moment a hard bounce lands. Retry, and leave the contact alone, on a 4xx, a 5.7.x policy block, or anything reading as a filter rather than a dead address; EmailFig only suppresses a soft-bouncing contact once it keeps failing, within your own account, because one soft bounce is noise. Everything else, an Undetermined bounce or a code you don’t recognize, is worth reading in full before you decide either way: the diagnostic text usually says in plain language what the two-line summary can’t. See soft vs hard bounces for how EmailFig applies that split, and suppressions for what happens to an address once it lands there.

Bounce codes are one input into a wider reputation; see email deliverability for people who aren’t experts for how they fit alongside authentication, bulk sender rules, and complaint thresholds.

Keep reading

All posts →