The short answer#
Every time one mail server talks to another, it answers each command with a
three-digit code. The first digit tells you the category — 2xx success,
4xx temporary failure, 5xx permanent failure — and that first digit is
almost the entire story for deliverability. An email verifier reads these same
codes during its probe, without ever sending a message, to decide whether a
mailbox is deliverable, undeliverable, or unknowable. This is the field guide
to the codes you'll actually meet, and the verdict each one produces.
How to read a response code#
SMTP codes have a consistent grammar. The first digit is the outcome class:
2xx— success. The command worked.250("requested action completed") is the one you want to see.4xx— transient failure. Something went wrong, but it might work if you try again later. This is a deferral, not a rejection.5xx— permanent failure. The server is refusing, and retrying won't help.
Many servers also send an enhanced status code — a second, dotted number
like 5.1.1 — defined by RFC 3463. Its middle digit narrows the reason:
x.1.x is about the address, x.2.x about the mailbox, x.7.x about
security or policy. That x.7.x class is how a verifier can tell a
reputation block ("we're refusing you") from a plain missing mailbox, even
when the human-readable text is vague.
For verification, the mapping is refreshingly clean:
| Response to RCPT TO | Meaning | Qualisend verdict |
|---|---|---|
250 / 251 | Recipient accepted | deliverable / accepted_email |
4xx | Temporary deferral (greylisting, rate limit) | retry, then unknown / timeout |
452 / 552 | Mailbox over quota | risky / low_deliverability |
550-class | Permanent rejection, no such user | undeliverable / rejected_email |
| Timeout / no reply | Server never answered conclusively | unknown / unavailable_smtp |
The codes you'll actually see#
250 — OK#
The recipient was accepted. In a verification probe this is the strongest
positive signal — but read it in context: on a
catch-all domain the server returns 250
for every address, real or not, so a 250 there is meaningful only when a
parallel probe of a nonsense address gets rejected.
421 — Service not available#
The server is closing the connection, often because it's overloaded or
throttling you. Transient by class — a verifier treats it as a deferral and
retries, then reports unknown if it persists.
450 / 451 — Mailbox unavailable / local error, try again#
The classic greylisting responses. The server is
temporarily refusing an unfamiliar sender and inviting a retry. A real mail
server retries automatically; a verifier retries within its time budget and
falls back to unknown if the deferral outlasts it. 451 frequently carries
"greylisted, please try again later" in its text.
452 — Insufficient system storage / too many recipients#
Often means the mailbox is full. The mailbox exists — which is why Qualisend
treats a full-mailbox signal as risky (low_deliverability) rather than
undeliverable: mail may bounce now but the address isn't dead, and full
mailboxes frequently recover.
550 — Mailbox unavailable / user unknown#
The workhorse rejection. The address does not exist, or the server is refusing
delivery permanently. Verdict: undeliverable / rejected_email. If the
enhanced code is 5.1.1, it is specifically "bad destination mailbox" — a
clean, unambiguous "no such user".
551 / 553 — User not local / mailbox name not allowed#
Less common permanent rejections — the server won't relay for that recipient,
or the address form is unacceptable. Both are undeliverable.
554 — Transaction failed#
A catch-all permanent failure, frequently used for policy blocks: "transaction
failed", "message refused", or an anti-spam rejection. When paired with a
5.7.x enhanced code or blocklist keywords, it signals the server is refusing
your sender, not judging the mailbox — a distinction a good verifier records
separately so a reputation problem doesn't get misread as a dead address.
The rest of the conversation#
The RCPT TO reply carries the verdict, but a verification probe reads
several other codes on the way there, and recognizing them helps when you're
staring at a raw SMTP log or a bounce message:
220— service ready. The greeting the server sends when you connect. No220means you never got in the door — often a connection-level block, which a verifier records asunavailable_smtp.250afterHELO/EHLOandMAIL FROM. Each step of the handshake gets its own250. A rejection beforeRCPT TO— atMAIL FROM, say — is usually the server refusing your sender, not judging the recipient.354— start mail input. The server inviting you to send the message body. A verifier never gets here on purpose: it stops atRCPTand disconnects, so the message is never transmitted.221— closing connection. The polite goodbye afterQUIT.501/502/503— syntax or sequence errors. The commands came in malformed or out of order. These are about the conversation, not the address, and a robust verifier handles them without misreading them as a mailbox verdict.
The practical point: not every non-250 is a dead mailbox. A rejection at the
wrong step of the conversation is usually about your sender or the
connection, and reading which step failed is how a verifier avoids blaming the
recipient for the server's mood.
Permanent, transient, and the honest unknown#
The single most consequential decision a verifier makes is how it treats
4xx. A permanent 5xx is easy: the address is bad, suppress it. A 250 is
easy: it's deliverable (catch-all caveats aside). But a 4xx is the server
explicitly declining to answer yet — and the honest response is to retry,
then report unknown if the deferral persists, never to guess.
This is also why the same address can return different verdicts on different
runs without any tool lying: the mailbox is deterministic, but the code it
produces depends on the server's mood — greylisting on the first attempt,
250 on the retry. The codes are a live conversation, not a database lookup.
Where verification reads these codes#
In the verification pipeline, response
codes are the raw material of stage 6, the SMTP mailbox probe. The verifier
runs the delivery conversation — HELO, MAIL FROM, RCPT TO — reads the
RCPT code, and disconnects before DATA, so the mailbox owner never
receives anything. Everything above is how that single RCPT code becomes a
status you can act on.
Frequently asked questions#
What's the difference between a 4xx and a 5xx bounce?#
4xx is temporary — the server is deferring and a retry may succeed, so
sending infrastructure keeps trying for a while (a "soft bounce"). 5xx is
permanent — the server is refusing outright, so the message is a "hard
bounce" and further attempts will fail the same way. For list hygiene, 5xx
addresses should be suppressed; 4xx addresses should be retried or marked
unknown — building a bounce classifier
turns exactly this rule into code.
Does a 550 always mean the address is invalid?#
Almost always it means "no such user", but 550 is also used for policy
rejections — the server blocking your sender rather than judging the mailbox.
The enhanced status code disambiguates: 5.1.1 is a genuinely bad mailbox,
while 5.7.x signals a security or reputation block. A verifier that reads
the enhanced code won't misfile a reputation problem as a dead address.
What is an enhanced status code?#
The optional second number in a reply, like 5.1.1 or 4.7.1, defined by
RFC 3463. The three fields are class (2/4/5, matching the basic code), subject
(what the code is about — address, mailbox, network, policy), and detail. They
give machine-readable precision that the free-text message often lacks.
Can I trust a 250 completely?#
Only if the domain isn't catch-all. A 250 from a normal server that rejects
unknown recipients is a strong positive; a 250 from a
catch-all domain is meaningless, because
that server returns 250 for every possible address. This is exactly why
verification probes a nonsense address in parallel.