Reading a bounce: is the receiver blaming your IP, your domain, or your message?
A rejection arrives, and before changing anything you need to know which of three things the receiver is objecting to: the address you connected from, the domain you claimed, or the message you sent. The codes narrow it down less than people expect and the free text carries more than the standards admit. Here is what each part of a rejection is allowed to mean, where the three branches lead, and the one line in the standards that explains why a bounce may not be the whole story.
The three parts of a rejection
A full rejection has three parts and they answer different questions. The three digit reply code says what to do next. The enhanced status code, when present, names a topic. The text after them is free form: RFC 5321 says the number is for automata and the text is for the human user, and that an SMTP client must determine its actions only by the reply code and not by the text, carving out only the 251 and 551 change of address replies and, if necessary, 220, 221 and 421. That instruction binds the sending software, not the postmaster reading a bounce afterwards, which is worth saying plainly because every receiver in this piece puts the actionable detail in exactly the part the standard tells machines to ignore. One more line, from RFC 7372, is the honest frame for everything below: only one enhanced status code can be returned for an exchange, and the failure it reflects "might not reflect the only reason, or the most important reason" for the message not being accepted. A bounce names one reason the receiver chose to surface, not the reason.
The first digit: retry or stop
Start with the disposition, because it is the only part the standard defines precisely. A 4yz reply is transient in a specific sense: it could succeed on an identical retry with no change to the command or the properties of sender and receiver. A 5yz reply means the client should not repeat the exact request. Neither maps onto the folk meanings. Permanent does not mean forever, and RFC 5321 says so in as many words, noting that even some permanent error conditions can be corrected; a 550 for a missing authentication record can stop recurring once the record exists, though the standard promises only that the condition is correctable and not that the next attempt is accepted. And a 4xx is not automatically a technical problem: RFC 6647 defines greylisting as a degradation of service applied to a source without a known reputation, and describes a variant applied only to sources that already carry a negative one, so a deferral can be a reputation judgement wearing a transient code. The same RFC notes there is no recommendation about what text to include, if any, so a bare 450 with no explanation is conformant and tells you nothing about the cause. Two smaller traps: the second digit is a coarse category only, so 550 and 554 both sit in the mail system class and the choice between them is receiver convention; and a code you have never seen is expected, since the standard tells senders to handle unknown codes by reading the first digit alone and says its own list must not be treated as permanent.
The enhanced code: a topic, not a verdict
Enhanced status codes read class.subject.detail, and reading them left to right is the intended behaviour: recognise the class even when the subject is unfamiliar, the subject even when the detail is. Their absence from a 2xx, 4xx or 5xx reply means only that the receiver does not advertise the extension, since RFC 2034 makes it a server property with no client negotiation and exempts only the greeting, the response to HELO or EHLO and 3xx replies, so a bare 421 given as a banner proves nothing either way; beyond that, read nothing into an absent code. What they will not do is settle your question. The registered sample text for X.7.1 is "Delivery not authorized, message refused", and the registry describes it as covering per-host or per-recipient filtering, which is precisely the distinction a sender wants and does not get. X.7.0 is registered as "Other or undefined security status" and may be used when the condition cannot be described because of security policies in force, so a deliberately uninformative rejection is conformant rather than broken. Two codes are usefully specific: X.7.25 is reverse DNS validation failed, and X.7.26 is multiple authentication checks failed, which RFC 7372 says deliberately does not name which ones. And the registry is not the last word on what a receiver means. On Google's error reference last updated 14 August 2026 and Microsoft's Exchange Online reference updated 11 August 2026, both read on 19 August 2026, Gmail's documented 5.7.27, 5.7.29 and 5.7.30 carry meanings unrelated to the registrations for those detail codes, and its 5.7.40 has no registration at all, while Microsoft documents a 4.7.26 where the registry associates that detail with a 550. Look the code up in the registry to learn what it was reserved for, then look it up in the receiver's own reference to learn what the receiver meant.
The free text: where receivers say what they mean
This is where the three-way split actually lives, and the two receivers that publish full references do it in opposite ways. As of their pages read on 19 August 2026, Google separates the branches in prose under one code: at 421 4.7.0 it publishes distinct strings for a message suspicious "due to the very low reputation of the sending IP address", "of the sending domain", and "due to the nature of the content or the links within", with the address string adding that sending has been temporarily rate limited while the other two say the message was blocked. Microsoft separates them by code instead, documenting a banned sending IP in the 5.7.606 to 5.7.649 range as "Access denied, banned sending IP", which carries a self service delisting portal, and a banned account at 5.7.501 as "Access denied, spam abuse detected". The split is not always visible in the text, though: "Access denied, banned sender" is the published string for a banned account at 5.7.502 and 5.7.503, a banned sending IP at 5.7.511 and a banned sender domain at 5.7.800, so on those four only the number tells them apart. Yahoo publishes far less: its help article, read on 19 August 2026 and carrying no date of its own, documents "554 5.7.9 Message not accepted for policy reasons" and says the error may be due to forwarded mail where the original author domain, the one in the From header, publishes a DMARC policy of reject, while its sender pages group causes by category rather than publishing a code table, so any Yahoo string from an aggregator is second hand. Three cautions on the text. It can be absent by design. It can read like a mailbox problem when it is not: RFC 5321 defines 550 as mailbox unavailable, with mailbox not found, no access or command rejected for policy reasons all inside the same code, and tells a server that declines to relay for policy reasons to answer 550, so a mailbox-flavoured code can carry a policy verdict, and it separately warns that a "550 mailbox not found" returned after the data are accepted leaves the client unable to tell which recipients failed. And the bounce you are holding may not be what the remote server said at all: in a delivery status notification the machine readable status is mandatory but the diagnostic code and the returned message are both optional, so a bounce reformatted along the way can conformantly drop the original. Check whether a Remote-MTA field is present: if it is, the diagnostic was issued by the far side; if it is not, it most likely came from your own, though the field is optional and a reformatted report can lose it.
Sorting your bounce into a branch
With those in hand the triage is short. If the text or code names your connecting address, a reputation of the sending IP, a banned IP, or reverse DNS, it is the address branch, and that is the only branch that is a question about a network, though the first question is whether that address is yours alone. On a shared hosting box, a shared ESP pool or an office NAT egress the receiver is judging the aggregate of everyone behind the address, most of the record you are about to read belongs to tenants you have never met, and the delisting request is your provider's to file rather than yours. Establish which of those you are on before you spend an afternoon on it: read what the space is and has been, find and stop whatever is still sending, and only then follow the receiver's published delisting path and, if a list is named, the list's own process. If it names your domain, an authentication mechanism or a policy, it is the domain branch, which usually means your DNS records but can also mean how your MTA signs and transmits, since a DKIM failure can be an unsigned message or one modified in transit and a TLS or format requirement is fixed on the server, where authentication establishes an identifier, not a reputation. If it names content or links and no sending identifier, it is the message branch; if the same complaint is scoped to an IP, netblock or domain, take that branch instead, since Gmail publishes unsolicited-mail strings scoped to an IP netblock and to SPF and DKIM domains and changing the network is unlikely to move it on its own. When the code is bare, use what you can: a mailbox-class code usually points at the recipient, although Microsoft documents 5.2.2 as a sender-side submission quota rather than a full mailbox; a network-class code is a report about the delivery system rather than a verdict on you, and the one senders misread most, delivery time expired, is commonly generated by a sending queue that gave up, though Microsoft's reference says a 4.4.7 usually indicates an issue on the receiving server; and a 4xx with no text could be congestion, greylisting or a reputation hold, which is exactly the case where the address's public record is worth reading before you touch anything. And resist re-engineering anything on a single bounce: RFC 3464 recommends that a list not remove a subscriber on one failure notice regardless of its code, but only on failure persisting over time. Read that as a rule about your setup, not as a reason to keep trying a recipient the far side has refused by name.
When a rejection points at your connecting address, look the address up on the front page and read the block around it: who holds the space and what the registry says today, which networks have announced that block and since when, which public blocklists the feeds still carry it on, and the confirmed tags that say whether the range reads as hosting, eyeball ISP or proxy space. A clean public record does not clear the address branch: the large receivers score sending addresses inside their own systems, and that score is published nowhere, so a lookup that comes back with nothing tells you the address carries no public listing today, not that the receiver thinks well of it. If you moved onto the range recently, what the previous announcers did with the space is worth ruling in or out before you change anything on your own side. It is rarely the whole story by itself: your sending is being scored from the day you arrive, so read the inherited history as one input rather than as an alibi.