SMTP Reply Codes Explained

Every line a mail server sends back begins with a three-digit code, and most add a second code in x.y.z form. Together they tell you whether the message is on its way, whether to retry, or whether something is broken and will stay broken.


SMTP is a conversation in which the server answers every command with a numbered reply. A three-digit reply code carries the machine-readable verdict, an optional enhanced status code in x.y.z form narrows down the reason, and the human text at the end is free-form. Reading those numbers is the difference between "email is broken" and "the server rejected the password at AUTH with 535, so fix the credential."

Anatomy of an SMTP Reply

Every reply follows the same shape. The first token is always the three-digit code defined in RFC 5321; anything after it is optional detail for humans:

text
250 2.1.5 Recipient OK │ │ │ │ │ └─ Free-form text — varies by server, never parse it for logic │ └─────── Enhanced status code (RFC 3463), optional └─────────── Reply code (RFC 5321), always present, always three digits

A reply can also span several lines. The server marks continuation with a hyphen after the code and the final line with a space. This is how the EHLO capability list arrives, and it is the single most misread piece of an SMTP transcript:

text
250-mail.example.com Hello client.example.net ← hyphen: more lines follow 250-SIZE 35882577 250-STARTTLS 250-AUTH LOGIN PLAIN 250 8BITMIME ← space: this is the last line
The hyphen is not part of the code250-STARTTLS and 250 STARTTLS are the same reply code. If a client library appears to hang after EHLO, it is often failing to consume continuation lines until it sees the space-delimited final one.

The Five Reply Classes

The first digit tells you the outcome, and it is the only digit you need for the decision that matters most — retry or give up:

ClassMeaningWhat the sender does
2xxSuccess — the command was acceptedContinues to the next command
3xxIntermediate — more input neededSends the data the server is waiting for
4xxTransient failure — try again laterQueues the message and retries for hours or days
5xxPermanent failure — do not retryGives up immediately and bounces to the sender

A 1xx class exists in the underlying reply-code framework but SMTP does not use it, so in practice you will only ever see the four above.

Why 4xx versus 5xx is the important distinction

A 4xx reply means the server is refusing right now — it is out of disk, rate limiting you, greylisting you, or temporarily unable to verify the recipient. The sending server keeps the message in its queue and retries on a backoff schedule, typically for 24 to 72 hours before giving up. The sender usually receives a "delayed" notice, not a bounce.

A 5xx reply means the server has made a final decision. The message is dead, and the sending server generates a bounce (an NDR) straight away. Retrying an identical message against a 5xx will fail identically every time.

Some servers lie about permanenceA handful of systems return 5xx for conditions that are genuinely temporary, and a few return 4xx forever. If a "permanent" failure clears on its own, or a "temporary" one has repeated for a week, trust the observed behaviour over the digit.

What the second and third digits add

The second digit categorises the reply: 0 syntax, 1 information, 2 connections, 5 mail system. The third digit is a further refinement with no fixed meaning across servers. In practice nobody parses digits two and three — the enhanced status code below is far more precise.

Enhanced Status Codes (RFC 3463)

The x.y.z code that often follows is a separate, richer scheme. It was added because three digits could not express the range of reasons mail fails:

text
5.7.1 │ │ │ │ │ └─ Detail — the specific condition within that subject │ └─── Subject — what part of the system is unhappy └───── Class — 2 success, 4 persistent transient, 5 permanent

The subject digit is the useful one:

SubjectAreaTypical example
x.0.zOther or undefined5.0.0 generic permanent failure
x.1.zAddressing — sender or recipient5.1.1 mailbox does not exist
x.2.zMailbox state5.2.2 mailbox full
x.3.zMail system — capacity and resources4.3.1 out of storage
x.4.zNetwork and routing4.4.1 no answer from host
x.5.zMail delivery protocol5.5.1 invalid command
x.6.zMessage content and media5.6.1 media not supported
x.7.zSecurity and policy5.7.1 delivery not authorized
x.7.z means "we decided not to"Almost every authentication, relaying, SPF, DKIM, DMARC and reputation rejection lands in the x.7.z security-and-policy subject. If the enhanced code starts with 5.7, the server is not confused — it is refusing on purpose, and the fix is a policy or credential change rather than a retry.

Codes You Will Actually See

A working session touches only a handful of codes. These are the ones worth recognising on sight:

CodeWhere it appearsMeaning
220On connect, and after STARTTLSService ready — the greeting
221After QUITClosing the connection
235After AUTHAuthentication succeeded
250EHLO, MAIL FROM, RCPT TO, end of DATACommand accepted
334During AUTHServer prompt — send the next base64 token
354After DATAStart sending the message; end with a lone dot
421Any timeService unavailable, connection closing — often rate limiting
450 / 451RCPT TO, DATATemporarily rejected — greylisting lives here
452RCPT TO, DATAInsufficient storage, or too many recipients
454STARTTLS, AUTHTLS not available, or temporary auth failure
500 / 501Any commandSyntax error — usually a broken client
502Any commandCommand not implemented
503Any commandBad sequence — e.g. RCPT TO before MAIL FROM
530MAIL FROMAuthentication required — you skipped AUTH
535AUTHCredentials rejected
550RCPT TO, DATAMailbox unavailable, relaying denied, policy rejection
552DATAMessage too large
554Connect, DATATransaction failed — frequently a reputation block

Greylisting: the 4xx you should not fight

A first-time sender is often met with 451 4.7.1 Greylisted, try again later. The receiver is deliberately deferring an unknown sender on the assumption that spam software will not retry. Legitimate mail servers retry a few minutes later and are then accepted, usually with the sender whitelisted for a period afterwards. Nothing needs fixing — but it does mean a single test send can appear to fail when delivery is working correctly.

Reading a Complete Session

Put together, an entire successful submission reads like this. The codes on the left tell the whole story without any of the text:

text
220 smtp.example.com ESMTP ready ← server is up EHLO client.example.net 250-smtp.example.com Hello ← capabilities follow 250-STARTTLS 250 AUTH LOGIN PLAIN STARTTLS 220 2.0.0 Ready to start TLS ← upgrade accepted EHLO client.example.net 250-smtp.example.com Hello 250 AUTH LOGIN PLAIN ← re-issued after the upgrade AUTH LOGIN 334 VXNlcm5hbWU6 ← prompt for username 334 UGFzc3dvcmQ6 ← prompt for password 235 2.7.0 Authentication successful ← credentials accepted MAIL FROM:<alerts@example.com> 250 2.1.0 Sender OK RCPT TO:<you@example.org> 250 2.1.5 Recipient OK ← server will take the message DATA 354 Start mail input; end with <CRLF>.<CRLF> 250 2.0.0 OK: queued as 4F2A81C0B7 ← accepted for delivery QUIT 221 2.0.0 Bye
250 at the end of DATA is not proof of delivery250 OK: queued means the receiving server has taken responsibility for the message. It can still bounce it afterwards, file it as spam, or discard it on content grounds. Acceptance and delivery are different events.
See these codes on your own serverThe SMTP Test runs a real session and shows the reply at every step — connect, STARTTLS, AUTH and RCPT TO — with timings.
Run an SMTP test

Where You Encounter Reply Codes

In a bounce message

A non-delivery report quotes the receiving server's final reply verbatim. This is the most common place to meet a code, and the quoted line is the authoritative one — the surrounding prose written by your own provider is a paraphrase:

text
Your message wasn't delivered to you@example.org because the address couldn't be found. The response from the remote server was: 550 5.1.1 <you@example.org>: Recipient address rejected: User unknown

In mail server logs

Postfix, Exim and friends log the remote reply against each delivery attempt, which is where you look when mail is queued rather than bounced:

bash
# Postfix — find the reply the remote server gave grep "status=" /var/log/mail.log | tail -20 # A deferral (4xx) — still queued, will retry status=deferred (host mx.example.org said: 451 4.7.1 Greylisted) # A bounce (5xx) — gone status=bounced (host mx.example.org said: 550 5.7.1 Message rejected)

In provider-specific extended codes

Large providers append their own detail digits to the enhanced code. They are not standard, but they are precise and worth searching for verbatim: Google uses 5.7.26 for unauthenticated bulk mail, and Microsoft 365 uses 5.7.139 when SMTP authentication is disabled for the mailbox. When a provider gives you a long code, use it — it usually maps to one specific documented cause.

Turning a Code Into a Fix

Work from the code to the failing step, then to the change that is actually needed:

  • 4xx anywhere — usually nothing to fix on your side. Confirm the queue is retrying, and only investigate if it persists past a day.
  • 530 5.7.0 — the client sent MAIL FROM without authenticating. Enable SMTP auth in the client, or connect on the submission port.
  • 535 5.7.8 — the credential itself is wrong or not the kind the provider expects. See fixing 535 5.7.8.
  • 550 5.1.1 — the mailbox does not exist. See user unknown.
  • 550 5.7.1 — the server will not carry this message for you. See relaying denied.
  • 552 — the message exceeds the server's size limit, which the SIZE capability in the EHLO reply tells you in advance.
  • 554 at connect — your sending IP is blocked outright. Check a blacklist lookup before anything else.

Frequently Asked Questions

Is a 4xx code something I need to fix?

Usually not. The sending server queues the message and retries automatically, and most 4xx conditions — greylisting, rate limiting, a momentarily busy server — clear on their own. It becomes your problem only if the same 4xx repeats for more than about a day, at which point the message will eventually bounce as undeliverable.

What is the difference between the reply code and the enhanced status code?

The three-digit reply code is required by RFC 5321 and tells you the class of outcome. The x.y.z enhanced code from RFC 3463 is optional and tells you the reason with far more precision. When both are present, read the enhanced code — 550 5.1.1 and 550 5.7.1 share a reply code but are completely different problems.

Why did I get a 250 but the email never arrived?

250 at the end of DATA means the receiving server accepted responsibility for the message, not that it reached an inbox. After acceptance it can be filed as spam, quarantined by a content or DMARC policy, or bounced asynchronously to your return path. Check the recipient's spam folder and your bounce address next.

Can I trust the text after the code?

Read it, but never build logic on it. The text is free-form and varies between servers and versions — only the numeric codes are standardised. Log the full line for humans, and branch on the code.

Which codes mean my IP is blocked?

Reputation blocks typically arrive as 554 at connection time or 550 5.7.x at RCPT TO, and the text usually names the blocklist. A 421 can also indicate a rate-based block rather than a listing. Confirm with a blacklist check before requesting delisting.

Related