Decay University · Part 6: Diagnosis and repair

Lesson 50 of 64

Reading bounce messages: email bounce codes decoded

The anatomy of a DSN, 4xx vs 5xx reply codes, enhanced status codes, greylisting, throttling, and the provider strings that name the exact problem.

Last updated 19 July 2026

When a receiving server refuses a message, it says why: a numbered code, usually a sentence of text, and the whole explanation gets mailed back to the sender. That return note is the bounce message, the receiver talking to you directly, no dashboard in between. After this lesson you can take any bounce, find the reply code inside it, decide from one digit whether the failure is temporary or permanent, and read what the receiver actually named. An earlier lesson covered what to do about bounces. This one is about reading a single one, because in diagnosis the bounce text is often the only artifact anyone can hand you.

The anatomy of a bounce

A bounce arrives as an email, typically from an address like mailer-daemon@ somewhere, and under the hood most of them follow one standard format: the delivery status notification, or DSN (RFC 3464). Three parts, stacked.

First, a human-readable block: "Your message could not be delivered to one or more recipients", plus whatever prose the sending server adds. This part is written for comfort, not diagnosis. Skim it.

Second, the machine-readable part, and this is where you read. A short block of labeled fields: Final-Recipient (who it was for), Action (usually failed or delayed), Status (a dotted code we will decode in a moment), and the field I go to first, Diagnostic-Code, which contains the receiving server's actual SMTP reply, verbatim. Whatever the receiver said in the live delivery conversation gets embalmed here, word for word.

Third, the original message or at least its headers, so you can confirm which send this even was. Everything from the headers lesson applies to that section unchanged.

Not every failure produces a DSN. When the receiver refuses during the live SMTP conversation, the sending server sees the reply directly and writes it to a log; the bounce email exists when someone downstream has to report back. Either way, the same reply text is the evidence.

The grammar of the codes

The reply inside Diagnostic-Code starts with a three-digit number, and the first digit does most of the work. A 4xx reply is a deferral: temporary, try again later, and real mail servers do retry, on a schedule, for days. A 5xx reply is a rejection: permanent, stop. You met this split before; here it becomes the first read you perform on any bounce, because it answers the client's real question ("is this dead?") before you have understood anything else.

The dotted code after it, the enhanced status code (RFC 3463), is where precision lives. Read it as class, subject, detail. The first number mirrors the family: 4 temporary, 5 permanent. The second number names the subject area, and this is the digit worth memorizing: .1. is addressing (wrong or dead address), .2. is the mailbox itself (full, disabled), .4. is network and routing, and .7. is security or policy, which in practice means authentication, reputation and spam filtering. The third number is the fine detail.

So 5.1.1 and 5.7.1 both arrive as a 550, and they are different diagnoses entirely. 5.1.1 means the mailbox does not exist: a list problem. 5.7.1 means the receiver refused you on policy: a sender problem, and the interesting kind. One digit separates "delete the address" from "start a deliverability investigation".

Here is a synthetic but faithful hard bounce, the machine part of the DSN (domains are the reserved documentation ones):

Reporting-MTA: dns; mail-out.example.net
Final-Recipient: rfc822; jordan@example.com
Action: failed
Status: 5.1.1
Diagnostic-Code: smtp; 550 5.1.1 <jordan@example.com>:
    Recipient address rejected: User unknown

Decoded: Action: failed says this is final, no more retries. Status: 5.1.1 reads as permanent, addressing, no such mailbox. The Diagnostic-Code confirms it in the receiver's own words: 550 (permanent), 5.1.1 again, "User unknown". Nothing about reputation, nothing about content. The address is dead; suppress it and move on. Total reading time, thirty seconds.

Greylisting and throttling: the deliberate deferrals

Two 4xx patterns deserve their own read, because both are the receiver acting on purpose.

Greylisting is a deferral aimed at first contact: a receiver that has never seen your server before answers with a temporary refusal, on the theory that crude spam software never retries and real servers always do. The retry succeeds, usually within minutes, and the receiver remembers you. In a bounce log it is a brief 450-class blip against a new destination that clears on its own. "The first email to a new contact always arrives late" is greylisting, and it is fine.

Throttling is the receiver slowing down a sender it finds suspect. The tell is 421 or 450-class deferrals that correlate with volume: the first chunk of a campaign delivers, then deferrals pile up as the receiver decides it has taken enough from you for now. Retries do eventually deliver some of it, which is why throttling hides so well inside "soft bounce" statistics. But the message underneath is about reputation, not capacity. A receiver throttles senders it does not yet trust at the volume they are attempting.

Here is what a throttling deferral from Gmail looks like inside a DSN, using one of Google's published error strings (IP from the documentation range):

Action: delayed
Status: 4.7.28
Diagnostic-Code: smtp; 421 4.7.28 Gmail has detected an unusual
    rate of unsolicited email originating from your IP address
    203.0.113.45. To protect our users from spam, email has been
    temporarily rate limited.

Decoded: 421 is temporary, so retries continue and Action: delayed says the sending server has not given up. The enhanced code 4.7.28 reads as temporary, policy, and the detail Google assigns to unsolicited-rate problems. Then the text does something generous: it names the measured thing. Gmail publishes variants of this string that say whether the unusual rate was observed from your IP address or from your DKIM domain, in the bounce itself. That distinction can take a day to establish with dashboards. Here it is free.

The strings are the gift

That example is the general pattern: major providers write rejection text meant to be read. Google maintains a public catalog of its SMTP error strings, and its policy rejections point you at its sender guidelines. Microsoft's rejections for blocked IPs carry reference codes and point toward its sender-support process, the same mitigation path the postmaster dashboards lesson introduced alongside SNDS. Paste the string into a search engine and you usually land on the provider's own page for that condition.

Which is why my first question in any triage conversation where the word "bounced" appears is: forward me the bounce. The whole email, not a screenshot of the subject line. Clients apologize for these messages as if they were embarrassing; to the person diagnosing, a bounce is the one artifact where the receiver states its reason in writing. Everything else we work with is inference.

The decay signal in the bounce log

A shift in bounce pattern is often the earliest visible symptom of reputation decay: a 4.7.x deferral class appearing at one provider where there was none, weeks before open rates move. The frustrating part, and I see this constantly in triage, is that most ESP dashboards swallow the evidence. The interface reports "soft bounces: 12" and the diagnostic text that would have named the problem sits in a log the sender has never opened, if the ESP exposes it at all. Learn where your ESP shows raw bounce reasons; if it doesn't show them anywhere, that is worth knowing before an incident, not during one.

The lab

Find a real bounce in your own mail history. Nearly everyone has one: search your mailbox for "mail delivery failed", "undeliverable", or "delivery status notification". Open it and decode it against this lesson: locate the Diagnostic-Code (or the reply line in the human-readable part), read the three-digit code for temporary versus permanent, read the enhanced code's middle digit for the subject, and say in one sentence what the receiver named. If your mail history is genuinely bounce-free, work the two examples above the same way; the drill is the same.

The next lesson takes this artifact and the header-reading skill and builds the triage runbook that turns evidence into a diagnosis.

Terms from this lesson

  • DSN (delivery status notification) - the standard format of a bounce email: a human-readable summary, a machine-readable status block, and the original message or its headers.
  • Diagnostic-Code - the DSN field carrying the receiving server's SMTP reply verbatim. The single most informative line in any bounce.
  • Action - the DSN field saying whether the failure is final (failed) or the sender is still retrying (delayed).
  • throttling - a receiver deliberately deferring a portion of a suspect sender's volume with 421/450-class replies. Temporary in form, reputational in meaning.

Check yourself

1. A bounce contains: Status: 5.1.1 and Diagnostic-Code: smtp; 550 5.1.1 Recipient address rejected: User unknown. What is the read?

2. Mid-campaign, deferrals appear reading: 421 4.7.28 Gmail has detected an unusual rate of unsolicited email originating from your IP address 203.0.113.45. What is happening?

3. In an enhanced status code like 5.7.1, what does the middle number tell you?

Scenario

A client emails you: "Our invoice to a big customer bounced. Our ESP dashboard just shows one soft bounce for the campaign. The customer says they got nothing."

What do you ask for first?