Glossary term
SMTP reply codes: reading what the receiving server said
What SMTP reply codes are
SMTP reply codes are the three-digit responses a receiving mail server
returns at every step of an SMTP transaction — after
the connection opens, after MAIL FROM, after each RCPT TO, and after
the message content is transmitted. Defined in RFC 5321, they are the
protocol's entire vocabulary of verdicts: accepted, refused forever, or
refused for now.
The first digit carries the decision:
- 2xx — success.
250is the workhorse ("requested action okay"), and250after the message data is the acceptance that platforms count as "delivered." - 3xx — intermediate.
354means "send the message content now"; part of the choreography, not an outcome. - 4xx — transient failure. Try again later; the basis of every deferral and, eventually, most soft bounces.
- 5xx — permanent failure. Do not retry; the anatomy of a hard bounce.
The second digit categorizes (syntax, information, connection, mail system), the third finishes the enumeration, and RFC 5321 permits (and practice universally includes) human-readable text after the digits. That text is where receivers explain themselves, from "mailbox full" to a policy URL telling you which requirement you failed.
Alongside the basic codes runs a second, richer system: enhanced
status codes per RFC 3463, in class.subject.detail form
(5.1.1, 4.7.0), delivered when both servers support the
ENHANCEDSTATUSCODES extension of RFC 2034. Between the two systems and
the free text, a refused delivery almost always tells you why — if
anyone reads it.
How 4xx differs from 5xx
One digit separates a delay from a verdict, and treating them alike is one of the costlier confusions in email operations.
A 4xx reply obliges the sender to queue and retry. Nothing about the recipient or message has been finally judged; the receiver may be overloaded, greylisting an unknown source, enforcing a rate limit against your IP reputation, or reporting a temporarily full mailbox. Correct handling is patience on a backoff schedule — the deferral entry covers the operational side.
A 5xx reply forbids retry. 550 with "user unknown" (enhanced code
5.1.1) means the address does not exist; retrying it is not
persistence but list-quality damage in progress, because receivers score
senders on how they respond to permanent failures. Correct handling is
immediate suppression and, in aggregate,
list hygiene.
The trap is that the mapping from code to meaning is receiver-defined at the edges. Some providers issue 4xx for what is functionally a policy rejection, letting retries exhaust quietly; others use 5xx for conditions that a sender could remedy tomorrow, like a reputation-based block with a remediation URL. The digits set the retry contract; the enhanced code and text carry the actual diagnosis. Read all three.
How SMTP reply codes work
In the transaction. Each command earns a reply before the next step
proceeds. A rejection at RCPT TO is per-recipient (one bad address in a batch fails alone), while a rejection after DATA judges the whole
message: content, authentication results, reputation. Where in the
transaction a code arrives is itself diagnostic: connection-stage 421s
speak to IP-level standing, post-DATA 550s to message-level filtering.
Enhanced status codes. RFC 3463's class.subject.detail grammar
gives the precision the basic grid lacks. The class repeats the
transient/permanent split (4.x.x / 5.x.x); the subject names the
domain of the problem — addressing (x.1.x), mailbox (x.2.x), mail
system (x.3.x), network (x.4.x), protocol (x.5.x), content
(x.6.x), security and policy (x.7.x). The ones worth memorizing:
5.1.1— no such user; the canonical hard bounce4.2.2— mailbox full; the canonical soft-bounce cause5.2.1— mailbox disabled4.7.0/5.7.1— policy or security refusal; the family where reputation blocks, DMARC enforcement and blocklist hits announce themselves5.7.26and neighbors — authentication-specific refusals some receivers use for missing SPF/DKIM
In the bounce message. When a failure happens after acceptance (a relay downstream refuses), the code reaches you inside a delivery status notification to the return-path address, in machine-readable DSN format (RFC 3464). Your platform parses these into its bounce categories; the raw codes remain the ground truth when categories look wrong.
In provider policy. Large receivers document their code usage — Gmail's error texts often include a support URL naming the violated policy from its sender requirements. When a 5xx text hands you a URL, the debugging session is half done.
SMTP reply codes and your deliverability
Reply codes are where deliverability stops being inference and becomes testimony: the receiver, on the record, at the moment of decision.
Bounce handling runs on them. The 4xx/5xx split drives suppression
logic, and suppression discipline is scored. A sender that keeps
retrying 5.1.1 addresses tells every receiver its list quality and
its hygiene are both poor — a direct
sender reputation input, and a spam-trap
risk multiplier since traps live at exactly the
addresses good hygiene would have dropped.
Reputation problems announce themselves here first. Blocklist hits
and throttles arrive as 5.7.x texts naming the list, or 421s citing
rates, before any placement data could show you the damage. The
blacklist checker confirms what the reply
text alleges; Postmaster Tools shows the
receiver-side view.
Placement testing depends on reading them. In an inbox placement test, mail refused at the gateway is a bounced state, not a filtering result — conflating "the receiver said 550" with "the receiver junked it" corrupts the rates. Send-side codes and mailbox-side placement are different stages with different fixes.
Aggregate patterns are a diagnostic instrument. Per-provider code
distributions over time surface stories single bounces cannot: a
creeping 4.2.2 share says list decay, a step-change in 5.7.x says a
policy or authentication event, one provider's divergence says the
problem is a relationship rather than the mail.
Limitations and failure modes
Reading the digits and skipping the text. "550" alone is nearly information-free — the same code carries "user unknown," "blocked for policy," and "message rejected due to content." The enhanced code and free text are the diagnosis; the three digits are only the retry contract.
Assuming uniform semantics. RFC 5321 defines the grammar; receivers improvise within it. The same condition can earn different codes at different providers, and some responses are deliberately vague to avoid educating spammers. Treat provider documentation, not the RFC alone, as the decoder for a specific receiver's habits.
Retrying permanent failures. Whether from parsing gaps or wishfulness, re-mailing 5xx-rejected addresses is self-harm with a timestamp. The receiver logged its verdict and is watching what you do with it.
Suppressing on transient failures. The opposite error: treating every 4xx as fatal and purging addresses that merely had a full mailbox during a long weekend. The digits differ precisely so your handling can.
Accept-then-discard blindness. A 250 is acceptance, not
placement — filters that accept and junk (or accept and drop) leave no
code trail at all. Reply codes bound what the transaction can tell you;
past the boundary you need
placement testing and provider
dashboards.
Homegrown senders mishandling the choreography. Scripts that ignore
per-recipient RCPT TO failures, misread 354, or drop the connection
on a slow reply create failure patterns that look, from the receiver's
chair, like bot traffic. If you must speak SMTP directly, speak it
correctly or use infrastructure that does.
Related terms
SMTP, deferral, hard bounce, soft bounce, greylisting, suppression list, list hygiene, return-path, sender reputation.
Frequently asked questions
What do the three digits in an SMTP code mean? First digit: outcome class — 2 success, 3 intermediate, 4 transient failure, 5 permanent failure. Second digit: category (syntax, information, connection, mail system). Third: specific case. The appended text and any enhanced status code carry the actual explanation.
What is the difference between 550 and 421?
550 is a permanent refusal (commonly unknown user or policy rejection) that should never be retried. 421 is a transient
"service not available, try later," the standard vehicle for
throttling and load-shedding, answered by queued retries.
What are enhanced status codes like 5.1.1?
The RFC 3463 system: class.subject.detail. 5.1.1 is "bad destination
mailbox address" — no such user. They ride alongside the basic code
when servers negotiate the RFC 2034 extension, and they are usually the
most precise machine-readable part of a rejection.
Why did the same address bounce at one provider and deliver at another? Different receivers, different verdicts: one may have the mailbox local and know it is gone, another may relay onward, and policy codes are by nature receiver-specific. Per-address decisions belong to whoever answers the transaction.
Which codes mean I have a reputation problem?
The x.7.x family and 421s citing rates or blocks. Texts naming a
blocklist, a policy page or "unusual traffic" are the receiver telling
you where to look — follow the URL if one is given, and verify against
independent checks.
Does a 250 mean my email reached the inbox? No. It means the receiving server accepted responsibility for the message. Folder placement is decided afterward, invisibly to the transaction — the gap that separates delivery rate from inbox placement.
Next bounce you investigate, skip the platform's category label and pull the raw DSN: basic code, enhanced code, full text, and which transaction stage produced it. Five minutes with the primary evidence beats an hour of dashboard archaeology — and if the text names a policy, the deliverability troubleshooter maps it to a fix path.