All articlesReference

Every SMTP Error Code Explained: A Complete Reference for Developers

What each SMTP reply code and enhanced status code actually means, which are temporary, which are permanent, and exactly how to fix the ones you will really meet.

The SMTPTester Team November 14, 2025 17 min read

How to read an SMTP reply

Every SMTP response begins with a three-digit code, and each digit carries meaning. Learn the structure once and you can classify an unfamiliar error in seconds without looking anything up.

First digit — the outcome:

  • 2xx — success. The command worked.
  • 3xx — intermediate. The server wants more input from you.
  • 4xx — transient failure. Try again later; the same request may succeed.
  • 5xx — permanent failure. Retrying the identical request will fail identically.

Second digit — the category:

  • x0x — syntax.
  • x1x — informational.
  • x2x — connection.
  • x5x — mail system.

Third digit narrows the specific condition.

Many servers also return an enhanced status code — three dot-separated numbers such as 5.7.1 — defined in RFC 3463. These are far more precise than the basic code, and the class digit mirrors the reply: 2 is success, 4 is transient, 5 is permanent.

The most valuable operational rule in all of email: retry 4xx, never retry 5xx. Hammering a 5xx damages your sender reputation and will eventually get your IP throttled or blocked.

Success codes

CodeMeaning
211System status or help reply
214Help message
220Service ready — the greeting, and the reply to STARTTLS
221Service closing transmission channel, after QUIT
235Authentication successful
250Requested action completed — the workhorse reply
251User not local, will forward
252Cannot verify user, but will accept and attempt delivery

A 250 after the final dot of DATA is the moment responsibility transfers from your system to the provider's. Log the queue ID from that reply — it is the only handle you will have if you later need to trace the message.

Intermediate codes

CodeMeaning
334Server challenge during AUTH; the payload is Base64
354Start mail input; end with a lone dot on its own line

A 334 is not an error, though plenty of naive clients treat it as one. During AUTH LOGIN the server sends 334 VXNlcm5hbWU6 — Base64 for "Username:" — and waits.

Transient failures (4xx) — retry these

### 421 — Service not available, closing channel

The most common transient code in production. Causes include rate limiting, too many concurrent connections from one IP, a server going into maintenance, or a temporary reputation block. The socket closes immediately.

Fix: reduce concurrency, add jittered exponential backoff, and reuse connections instead of opening a new one per message. If 421 appears at a consistent volume threshold, you are hitting a documented provider limit.

### 450 4.2.0 — Mailbox unavailable, temporarily

The recipient mailbox exists but cannot accept mail right now — often greylisting, a full mailbox, or a locked account.

Fix: retry after a delay. Greylisting specifically expects you to retry after several minutes from the same IP; a compliant queue satisfies it automatically.

### 451 4.3.0 — Local error in processing

Something broke on the receiving server: a full disk, a content scanner timing out, a database hiccup. Occasionally it signals a content filter that could not make a decision.

Fix: retry with backoff. Persistent 451 for a single destination warrants contacting the postmaster.

### 452 4.2.2 — Insufficient system storage

Either the recipient mailbox is over quota or the server is out of disk. Some providers also return 452 when you exceed the maximum recipients per message.

Fix: retry, and split large recipient lists into batches of 50 or fewer.

### 454 4.7.0 — Temporary authentication failure

The authentication backend is unavailable, or the provider is rate-limiting authentication attempts.

Fix: back off aggressively. Repeated retries look like a credential-stuffing attack and can escalate to a block.

Permanent failures (5xx) — fix these

### 500 / 501 / 502 / 503 / 504 — protocol problems

  • 500 Syntax error, command unrecognised. Often a line-ending problem: SMTP requires CRLF, not bare LF.
  • 501 Syntax error in parameters. A malformed address or a broken Base64 payload.
  • 502 Command not implemented. You used something the server does not support.
  • 503 Bad sequence of commands. Classic examples: RCPT before MAIL, or DATA before RCPT.
  • 504 Command parameter not implemented — usually an unsupported AUTH mechanism.

These are always client bugs. No amount of retrying helps.

### 521 / 541 — connection refused or rejected

The host does not accept mail at all (521), or a filter rejected your connection outright (541). Check that you are connecting to the right hostname and that your IP is not listed on a blocklist.

### 530 5.7.0 — Authentication required

You tried to relay before authenticating, or you connected to port 25 where relaying is disallowed.

Fix: use port 587 or 465 and authenticate first. Remember to re-issue EHLO after STARTTLS, otherwise the client never learns that AUTH is available.

### 534 5.7.9 — Authentication mechanism too weak

You offered a mechanism the server considers insufficient for the channel — typically plain credentials without TLS, or password auth against a mailbox that requires OAuth.

Fix: enable TLS, or switch to XOAUTH2.

### 535 5.7.8 — Authentication credentials invalid

The single most reported SMTP error. Usual causes: using the account password instead of an app password, omitting the domain part of the username, whitespace pasted from a password manager, or SMTP AUTH disabled for the mailbox by an administrator.

Fix: generate a dedicated app password or API key, use the full email address as the username, and confirm the mailbox is permitted to use SMTP.

### 550 — the ambiguous one

550 covers several very different situations, and the enhanced code tells you which:

  • 550 5.1.1 — recipient address does not exist. Remove it from your list permanently.
  • 550 5.7.1 — relay denied, or the message was rejected by policy. Could be authentication, could be a blocklist, could be DMARC.
  • 550 5.7.26 — the message failed authentication (Gmail's phrasing when SPF/DKIM/DMARC do not align).
  • 550 5.4.1 — recipient address rejected: access denied (common on Microsoft 365 for a non-existent user).

Fix: read the text after the code. Providers almost always include a URL explaining their specific policy.

### 551 / 552 / 553 / 554

  • 551 User not local — the server will not forward.
  • 552 Message exceeds size limit. Compress or link to attachments instead.
  • 553 Mailbox name not allowed — a malformed address or a sender the server refuses.
  • 554 Transaction failed. The catch-all rejection, frequently used for spam and reputation blocks. The accompanying text is essential.

Enhanced status codes worth memorising

CodeMeaning
4.2.2 / 5.2.2Mailbox full
4.4.1No answer from host
4.4.2Bad connection, dropped mid-session
4.7.1Delivery not authorised, temporarily
5.1.1Bad destination mailbox address
5.1.2Bad destination system — domain does not exist
5.1.8Bad sender address syntax
5.2.3Message length exceeds limit
5.4.4Unable to route
5.7.1Delivery not authorised
5.7.13Sender account disabled
5.7.25Reverse DNS does not match sending IP
5.7.26Multiple authentication failures

5.7.25 deserves special attention for self-hosted senders: your sending IP needs a PTR record that resolves back to the hostname you present in EHLO, and that hostname must resolve forward to the same IP. Without matching forward and reverse DNS, several large providers reject mail regardless of SPF and DKIM.

Building retry logic that behaves

A correct sending queue implements roughly this policy:

on 2xx  -> mark delivered, store queue id
on 4xx  -> retry with jittered exponential backoff
           1m, 5m, 15m, 1h, 4h, 12h, then bounce at 24-48h
on 5xx  -> permanent bounce, add to suppression list, never retry
on 421  -> close connection, halve concurrency, retry later
on 550 5.1.1 -> suppress the address forever

Three details matter. Add jitter so parallel workers do not retry in lockstep. Cap total retry duration at 24–48 hours; beyond that the message is stale. And maintain a suppression list so a hard-bounced address is never contacted again — repeatedly mailing dead addresses is one of the fastest ways to destroy sender reputation.

Diagnosing an unfamiliar error

  1. Note whether it is 4xx or 5xx. That decides whether to retry.
  2. Read the enhanced code for precision.
  3. Read the human-readable text — providers put the real answer there, often with a documentation link.
  4. Determine which stage failed: connection, TLS, AUTH, MAIL FROM, RCPT TO, or DATA. Each stage points at a different subsystem.
  5. Reproduce against the raw server so you see the untranslated reply.

That last step is where most debugging time is saved. Application logs paraphrase; the wire does not. Run the connection through SMTPTester, read the full transcript, and the code that looked cryptic in your logs will usually explain itself.

Where the error occurred matters as much as the code

The same code means different things at different stages of the session. Track which command triggered the reply.

StageA failure here means
ConnectionNetwork, firewall, or IP-level block
EHLOYour hostname was rejected, or the server is refusing your IP
STARTTLSCertificate or protocol version mismatch
AUTHCredentials, mechanism, or permission
MAIL FROMSender not authorised, or sender domain rejected
RCPT TORecipient problem — the address, or a policy about who may receive
DATA / end-of-dataContent, size, spam filtering, or authentication alignment

A 550 at RCPT TO is a recipient problem. A 550 after the final dot of DATA is a content or reputation problem. Identical code, completely different investigation. Any logging you build should record the stage alongside the code.

Provider-specific phrasing

Large providers extend the standard codes with their own text, and that text is where the real answer lives.

Gmail typically appends a documentation URL, for example 550-5.7.26 ... https://support.google.com/mail/answer/81126. Follow it; the page names the exact policy you violated. Gmail's 421 4.7.0 Try again later almost always means rate limiting rather than a genuine outage.

Microsoft uses distinctive enhanced codes: 5.7.60 for send-as permission problems, 5.7.64 for connector mismatches, 4.7.500 for throttling. These are Microsoft-specific and will not appear in RFC tables.

Yahoo returns 554 delivery error with a temporary-failure explanation more often than most, and is unusually sensitive to complaint rates.

Amazon SES rejects at submission time with detailed messages about verified identities and sandbox restrictions — a new account can only send to verified addresses until you request production access.

Logging errors usefully

Most teams log too little to diagnose and too much to search. A good SMTP log line contains:

  • Timestamp and correlation ID linking to the originating application event.
  • Destination host, port, and the stage that failed.
  • The numeric code, the enhanced code, and the complete reply text.
  • The recipient domain (not the full address, for privacy).
  • Attempt number and the retry decision taken.

Deliberately exclude credentials, full message bodies, and complete recipient addresses. Then build one dashboard: error counts grouped by code and by recipient domain, over time. Nearly every email incident is visible as a spike on that single chart, and grouping by domain instantly tells you whether the problem is yours or one provider's.

Turning codes into alerts

Not every error deserves a page. A sensible policy:

  • Page immediately: any sustained 5xx at AUTH, because it means nothing is sending.
  • Page immediately: total send failures above 10 percent for five minutes.
  • Warn: 421 rate above baseline, indicating throttling.
  • Warn: a rise in 550 5.7.x, indicating a reputation or authentication problem.
  • Ignore individually: isolated 550 5.1.1, which is normal list attrition — but alert if the *rate* rises sharply, because that means a bad import.

The distinction is between errors that mean your system is broken and errors that mean the world is normal. Getting that boundary right is what makes on-call sustainable.

Test your SMTP server now

Apply what you just learned. Free, no signup, results in seconds.

Open the tool →

Continue reading