How to read an SMTP bounce, not the tea leaves
A bounce says exactly what happened, if you read the number instead of the sentence. The 4.x.x and 5.7.x codes per provider, what each one really means, when to retry.
A bounce comes back. Someone forwards it to you with "any idea?" in the body. You skim the English sentence at the end, decide it sounds like SPF, and spend the afternoon editing a TXT record that was never the problem.
The bounce told you what happened. It said so in three digits, near the start, before any of the prose. The prose is the part you can't lean on.
Every provider writes its rejection text differently, and some of them write it badly. The numeric codes are standardised, which makes them the sturdier half of the message. Not identical everywhere: Google, Microsoft and Yahoo all mint codes of their own, and a couple of Google's collide head-on with the registered meaning. But the standard part gets you most of the way in about ten seconds.
Short answer: the first digit tells you whether the bounce is temporary or permanent, the middle digit tells you which part of the mail system made the decision, and the sentence at the end is the least reliable part of the whole message.
Is it a 4 or a 5? Start there.
The first digit tells you whether to do anything at all. This is the split that the words soft bounce and hard bounce are pointing at.
4xx / 4.x.x temporary: your server will retry on its own
5xx / 5.x.x permanent: retrying this message unchanged achieves nothing
A 4 is a soft bounce, or a deferral. The receiving server is saying "not now", and your mail server will keep trying on a schedule without being asked. Postfix keeps a deferred message queued for five days by default before it gives up. Hosted sending platforms are usually far less patient than that, so a deferral on a hosted service can turn into a returned message the same day.
A 5 is a hard bounce. RFC 3463 defines it as a failure "not likely to be resolved by resending the message in the current form", so something about the message or the destination has to change first. In practice the message has already been returned to the sender, and waiting is not the thing that changes.
Our take: a single 4.x.x in a log is not an incident. It is the protocol working. What deserves attention is the same 4.x.x for the same destination that never clears. A deferral still repeating hours later is a block. The receiver has decided against you and is declining to say so out loud, and waiting will not change the answer.
What do the three numbers actually mean?
An SMTP enhanced status code is a class, a subject and a detail, in that order, defined in RFC 3463. Read left to right and each digit narrows the answer.
The middle digit is the one nobody uses, and it is the most useful. RFC 3463 gives each subject a stated owner, and that part is where the popular shorthand goes wrong:
X.1.x addressing: the address itself; the sender can usually correct it
X.2.x mailbox: the box exists but can't take this message; the recipient's
X.3.x mail system: the receiving system, not this mailbox
X.4.x network / routing: connections, DNS, loops, expiry
X.7.x security / policy: auth, reputation, filtering; either side, or both
So 5.1.1 is permanent + addressing + "no such mailbox". 4.2.2 is temporary + mailbox + "the box is full right now". 5.7.26 is permanent + policy + "more than one authentication check failed". Once the middle digit is in your head you can place a code you have never seen before, which matters because providers invent detail digits freely.
Our take: the middle digit is a category, not a blame allocator, and the widespread reading that X.7.x means "your fault" is not what the RFC says. Security and policy issues are "under the control of either or both the sender and recipient", so a 5.7.x is as often the receiver's filter as your DNS. The digit that does point at the sender is X.1.x, addressing, where the RFC says the errors "can generally be corrected by the sender". Usually by fixing the address you typed.
Which codes can you actually act on?
Forget fault. The useful question is what you can change. Some codes describe the address you sent to, some name something on your side of the wire, and some record a decision the receiver made about you without saying why.
Codes that describe the address, not you
5.1.1 mailbox does not exist (typo, or the person left)
5.1.2 bad destination system: the domain can't take mail at all
5.2.1 mailbox disabled, not accepting messages
5.2.2 mailbox over quota
Every one of those is a fact about the address or the box behind it. The fix is a corrected address, or a phone call. Editing your DNS will not help, and a 5.1.1 that keeps bouncing on a mailing list is a list-hygiene job.
5.1.2 is wider than the "no MX record" gloss it usually gets. The registered wording is that the system to the right of the @ "does not exist or is incapable of accepting mail", which covers a domain that was never registered, one with no MX, and one publishing a null MX to say it never accepts mail at all.
Codes that are yours: DNS, IP or sending behaviour
5.7.23 SPF validation failed (your sending IP isn't authorised)
5.7.24 SPF validation error (evaluation errored: syntax, or the lookup limit)
5.7.25 reverse DNS (PTR) validation failed
5.7.26 more than one authentication check failed
5.7.515 Outlook.com rejecting an unauthenticated high-volume sender
The four 5.7.2x codes are standardised in RFC 7372, so they carry the same registered meaning wherever you see them. 5.7.23 means add the IP or the include. 5.7.24 means SPF evaluation errored instead of returning a verdict, and at 5. that is a PermError: a syntax mistake or more than ten DNS lookups, failing for everyone, everywhere. 5.7.25 means the IP you send from has no valid PTR record, or the forward lookup doesn't come back to it.
5.7.26 gets over-read constantly. Its registered meaning is only that more than one check failed, and the RFC says outright that which mechanisms failed "are not specified", so it is not a synonym for DMARC. Gmail issues it for three separate situations: no authentication at all, an SPF -all that failed, and a DMARC policy rejecting unauthenticated mail. Its own sentence tells you which. 5.7.515 is Microsoft's own invention and is not in the registry at all.
Codes that record a decision without giving a reason
5.4.1 "access denied" (Microsoft; the sentence rarely says why)
5.7.0 rejected on policy (a filter said no, without saying which)
5.7.1 rejected, not authorised (relay refused, or a content/policy block)
4.7.28 Gmail rate-limiting an unusual volume of mail from you
4.7.29 Gmail rate-limiting you for connecting without TLS
These are the ones that send people down the wrong hole for a day. Not one of them names its own fix. Read the next section before you touch anything in this group.
Why does the rejection text contradict the code?
Because the sentence is written by whoever implemented that check, the number is standardised, and neither one is obliged to be specific.
The clearest example is 550 5.4.1 Recipient address rejected: Access denied from Microsoft, where three signals point in three directions. The wording blames the address. The middle digit says network and routing. And Microsoft's own page for the code says something else again: the NDR is generated when directory-based edge blocking rejects an incoming message because the recipient's address is invalid. Every fix on that page is recipient-side: check the spelling, resync the accepted domain, reset the proxy address.
Operators report the same code on freshly rented IPs with every authentication check green, where no spelling fix helps. Microsoft publishes nothing that confirms a reputation path for 5.4.1, so that reading stays a hypothesis. One test settles it in a minute: send to a second, definitely-valid address at the same tenant. Every recipient bouncing points at your sending IP or domain. One address bouncing points at the address. We took the rest of the Microsoft non-delivery report zoo apart in why Microsoft 365 and Outlook are blocking your mail.

The same trap runs the other way. Google's 5.7.26 bounce hands you the answer in its own text: "This message does not pass authentication checks (SPF and DKIM both do not pass)." The registered meaning of 5.7.26 would not have told you which checks failed. The sentence did. Some providers write a genuinely useful one, and you cannot tell which kind you are holding until you have read both.
What to do: read the number to place the failure, read the sentence for the specifics, and read the rejecting host to know whose rules you fell foul of. The number is the sturdier half, but it is a category, not a diagnosis. When the two disagree, go and get a third fact before you change anything.
Which codes matter per provider?
The standard codes are shared. The wrappers around them are not, and knowing the wrapper tells you who rejected you.
Google / Gmail. NDRs arrive from [email protected] and end with a bracketed identifier. Google documents both: gsmtp is appended to every error it issues, and gcdp is appended when the rejection came from a custom rule a Google Workspace administrator wrote. [gcdp] is the one that tells you something: a person at the receiving organisation configured this, and no amount of repairing your authentication will clear it.
Two Google codes collide with their registered meanings, so memorise them. 421 4.7.28 is rate limiting after Gmail sees an unusual volume of mail tied to your IP, your netblock, your SPF or DKIM domain, or a URL in your message body. Complaints are one trigger among several, not the definition. 421 4.7.29 means one thing only: you connected without TLS. Since February 2024 Google has required SPF or DKIM, valid forward and reverse DNS, TLS, and a Postmaster Tools spam rate under 0.3% from every sender. Over 5,000 messages a day to Gmail it wants SPF and DKIM both, a DMARC record, alignment and one-click unsubscribe. The DMARC policy may be p=none; it just has to exist.
Microsoft. Exchange Online prefixes the failure with an internal component name. RESOLVER is routing and addressing, STOREDRV is the mailbox store, QUEUE is transport. Read the component, then the code, and ignore the [BeginDiagnosticData] block entirely. 550 5.7.515 is Outlook.com's high-volume authentication rule. Microsoft's announcement scopes it to the consumer service (hotmail.com, live.com and outlook.com addresses), and its 29 April update says non-compliant mail from high-volume domains goes to Junk from 5 May 2025, with outright rejection on that code coming later, on a date Microsoft has not named. If you are being blocked delivering to a business tenant, this is not your code.
5.7.13 is a trap worth knowing about, because three sources define it three ways. The registry has it as a sender's account being disabled after it authenticated. Microsoft's own page for the code describes a public folder configured to refuse external senders. And the bounce almost everyone actually meets, STOREDRV.Deliver.Exception:AccountDisabledException, means the recipient's mailbox is switched off. Read the component and the exception name. The digits alone will mislead you here.
Yahoo and AOL. Rejections carry a bracketed identifier: [TSS02], [TSS04], [TSS05], [TS06]. Yahoo publishes no index of what they mean, and nothing below this line comes from Yahoo. Its error-codes page lists causes rather than identifiers, and frames temporary rejections as 421 or 451 and permanent ones as 553 or 554. Where the brackets do surface in real bounces, the sentence beside them is the same generic one either way: "temporarily deferred due to unexpected volume or user complaints" appears with TSS04 and TSS05 alike.
Our take: treat the bracket as a reference number for a conversation with Yahoo, not as a diagnosis. Anyone handing you a precise per-code meaning, us included until Yahoo publishes one, is reporting folklore. The payload is the sentence and the fact that you are being deferred.
Gateways in front of the mailbox. If the rejecting host is *.pphosted.com you are talking to Proofpoint, and *.mimecast.com is Mimecast. Both sit ahead of the real mail system, so a block there says nothing about the recipient's mailbox, and neither one appears in the recipient's own admin console. Getting unblocked means the gateway's process, not the mail provider's.
Our take: the reporting host in the bounce is worth as much as the code. It tells you whose rules you fell foul of, and therefore whose delist or unblock process you need. People routinely open a support ticket with the wrong company.
When should I just retry?
Retry, meaning leave it alone and let your mail server handle it, when the code is a 4, the cause is on their side, and this is the first time you have seen it.
Genuinely fine to leave alone:
4.2.1 rate limited, try again later
4.2.2 recipient mailbox full (temporarily)
4.4.1 no answer from host
4.4.2 bad connection, dropped mid-conversation
4.3.2 receiving system not accepting mail right now
Your mail server handles all of those. Do nothing. If it clears within the hour, there was never a problem to solve.
Worth investigating despite being a 4:
4.7.28and4.7.29from Gmail. Temporary in name only, and not the same problem.4.7.28is volume and reputation, and it will not resolve by waiting.4.7.29is a missing TLS connection, which is a configuration fix on your side and clears the moment you make it.- Any
4.x.xthat persists past a few hours for one destination. Greylisting is designed to clear on your server's next retry, though the receiver sets that window and some set it long. A deferral that survives the afternoon is a block. 4.4.7in bulk. Delivery time expired: your queue gave up before the far side ever accepted, which is a connection-level problem rather than a per-message decision. Don't read4.7.0the same way despite the neighbouring digits. It is "other or undefined security status", and Gmail alone uses it for a closed connection, an IP missing from an allowlist, and a plain try-again.
The failure mode here is a mail server quietly retrying a soft block for five days while everyone assumes the mail went out. Check the queue, not the sent folder.
How do I read one without guessing?
Find four things in the bounce and ignore the rest of it.
- The
Diagnostic-Code:line. This is the receiving server's verbatim response, and the closest thing in the bounce to a primary source. Everything above it is your own mail server's prose summary. Read it alongside theStatus:,Action:andRemote-MTA:fields, which are the machine-readable record of what your server did with that answer. - The enhanced code inside it. The
X.Y.Ztriplet. Class, subject, detail, in that order. - The
Remote-MTA:or reporting host. Who actually said no. This is how you tell a Proofpoint gateway from the mailbox behind it. - The provider tag.
[gsmtp],[gcdp],[TSS02], aRESOLVER/STOREDRVcomponent. Confirms whose rulebook applies, and in Google's case whether an administrator wrote the rule.
A real Gmail rejection reduced to those parts:
Diagnostic-Code: smtp; 550 5.7.26 This message does not pass
authentication checks (SPF and DKIM both do not pass). To fix this
issue, review your SPF and DKIM configuration for example.com. [gsmtp]
Permanent, policy, more than one authentication check failed, from Google, with the two that failed named and the fix spelled out. No guessing required, and no reason to look at the wall of headers above it.
If you would rather not parse it by hand, our bounce decoder takes the whole NDR and maps the code, the component and the fix in one pass. The full SMTP error code directory is the reference version, with a page per code and the per-provider wording for each.
Bounces feel opaque because the useful part is three digits long and buried in the middle of two hundred lines of machine output. Find the
Diagnostic-Codeline, read the number, and the rest of it is noise.
So what do I actually do?
- First digit. A
4needs patience, a5needs a decision. Everything else follows from this. - Middle digit. It names the category, not the culprit.
X.1.xis the address and usually yours to correct,X.2.xis the recipient's box,X.7.xcan be either side. - Read the number before the sentence. The number places the failure, the sentence supplies the specifics. When they disagree, go and find a third fact.
- Note who rejected you. The reporting host decides which delist or unblock process you need, and a gateway is not the mail provider.
- If it's
5.7.23or5.7.24, fix SPF: authorise the IP, or repair the record that errored out. - If it's
5.7.26, read the sentence for which checks failed before assuming alignment. - If it's
5.7.25, your sending IP has no valid PTR, or the forward lookup doesn't return it. Fix reverse DNS before anything else. - If it's
5.4.1, find out whether every recipient at that tenant bounces or only one, before you touch either your IP reputation or your address book. - If it's
5.7.0,5.7.1or4.7.28, it is reputation. Check the IP and domain against the blocklists that actually matter, fix the underlying behaviour, then use the provider's own delist route. - Stop the retry loop. A soft block retried for days looks like success from the sender's side. Watch the queue.
Bounces are the only part of email deliverability where the receiver tells you plainly what it decided. Spam foldering, silent filtering and reputation scoring all happen without a word back to you. Reading the ones you get costs nothing and saves the afternoon you were about to spend on the wrong record.
Two follow-ons if the code points somewhere specific. A Microsoft NDR that reads like a stack trace is worth taking apart component by component, which the Microsoft piece above does. And if the answer turns out to be reputation, work the handful of lists that gate real delivery rather than filling in every delist form you can find.