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's you vs them, 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 that lies.
Every provider writes its rejection text differently, and some of them write it badly. The numeric codes are standardised and they are the same across Gmail, Microsoft, Yahoo and every gateway in front of them. Learn to read those and most bounces resolve in about ten seconds.
Short answer: the first digit tells you whether the bounce is temporary or permanent, the middle digit tells you whether it is your problem or the recipient's, 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: the sender will retry on its own
5xx / 5.x.x permanent: nobody is retrying, the mail is dead
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 and it is final. The message has already been returned to the sender and no amount of waiting changes that.
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:
X.1.x addressing: the recipient or sender address itself
X.2.x mailbox: the box exists but can't take this message
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
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 + a DMARC failure. 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.
Anything in X.7.x is about you. Anything in X.1.x or X.2.x is almost always about them.
Which codes are you, and which are them?
Bounce codes fall into two camps: the ones you can fix, and the ones where the only useful move is to reply to the sender and move on.
Codes that are the recipient's problem
5.1.1 mailbox does not exist (typo, or the person left)
5.1.2 bad destination domain (the domain has no MX at all)
5.2.1 mailbox disabled or suspended
5.2.2 mailbox over quota
5.7.13 recipient's account is disabled
Every one of those is a fact about the recipient. 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.
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 PermError (your record is syntactically broken)
5.7.25 reverse DNS (PTR) validation failed
5.7.26 DMARC failure (auth didn't pass, or didn't align)
5.7.515 Outlook.com rejecting an unauthenticated high-volume sender
These are the codes worth acting on immediately, and each names its own fix. 5.7.23 means add the IP or the include. 5.7.24 means your SPF record has a syntax error or blew the lookup limit, so it is failing for everyone, everywhere. 5.7.25 means the IP you send from has no valid PTR record, which is the standard self-hosting oversight. 5.7.26 is nearly always alignment rather than a missing record.
Codes where reputation is wearing someone else's label
5.4.1 "access denied" (usually Microsoft blocking your IP on reputation)
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 blocked: high complaint rate (too many spam reports)
4.7.29 blocked: local policy, new sender (unwarmed IP)
These are the ones that send people down the wrong hole for a day. 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, and the number is standardised.
The clearest example is 550 5.4.1 Recipient address rejected: Access denied from Microsoft. It reads like a bad address. It usually means Exchange Online blocked your sending IP or domain on reputation before it looked at anything else, with SPF, DKIM and DMARC all green. We covered that pattern and the rest of the Microsoft non-delivery report zoo 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)." Some providers write a genuinely useful sentence. You cannot tell which kind you are holding until you have read the number first.
What to do: read the number, decide what class of problem it is, and only then read the sentence to fill in the detail. Not the other way round. If number and sentence disagree, the number wins.
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 [gsmtp] tag for consumer Gmail or [gcdp] for Google Workspace. That tag is not an error code, it is a signature, and it proves the rejection came from Google itself rather than from a filter parked in front of it. The two Google-specific codes to know are 4.7.28 (your complaint rate has tripped the filters, check Postmaster Tools) and 4.7.29 (new sender hold, you are being asked to warm the IP up). Since February 2024 Google has required SPF, DKIM, DMARC at p=none and a complaint rate under 0.3% from anyone sending more than 5,000 messages a day to Gmail.
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 the Outlook.com consumer high-volume rule that landed in May 2025, and it does not apply to business tenants.
Yahoo and AOL. Rejections carry a bracketed identifier rather than a useful sentence. Yahoo does not publish a stable public index of them, but the ones you see most often are [TSS02] for too many simultaneous connections from your IP, [TSS04] for a rate limit, [TSS07] for a permanent spam or policy block, and [TS06] for a bad-reputation block. The TSS codes come back as 421 4.7.0 or 550 5.7.0, so the standard code alone tells you very little. The bracket is the payload.
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.29. Temporary in name only. These are reputation decisions and they will not resolve by waiting. The receiver is asking you to change your behaviour and re-earn the delivery.- Any
4.x.xthat persists past a few hours for one destination. Greylisting clears in minutes. A deferral that survives the afternoon is a block. 4.4.7or4.7.0in bulk. Messages expiring in the queue means the far side has stopped talking to you, which is a connection-level block rather than a per-message decision.
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 only part that is authoritative. Everything above it is your own mail server's summary. - 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.
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, DMARC, from Google, with the fix named. 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.
X.1.xorX.2.xis the recipient's problem.X.7.xis yours. - Read the number before the sentence. When they disagree, the number is right.
5.4.1from Microsoft is reputation, not a bad address. - 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.23,5.7.24or5.7.26, fix auth: authorise the IP, repair the SPF syntax, or sort out alignment. - If it's
5.7.25, your sending IP has no valid PTR. Fix reverse DNS before anything else. - If it's
5.4.1,5.7.0,5.7.1,4.7.28or4.7.29, 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.