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.
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.
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:
Second digit — the category:
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.
| Code | Meaning |
|---|---|
| 211 | System status or help reply |
| 214 | Help message |
| 220 | Service ready — the greeting, and the reply to STARTTLS |
| 221 | Service closing transmission channel, after QUIT |
| 235 | Authentication successful |
| 250 | Requested action completed — the workhorse reply |
| 251 | User not local, will forward |
| 252 | Cannot 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.
| Code | Meaning |
|---|---|
| 334 | Server challenge during AUTH; the payload is Base64 |
| 354 | Start 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.
### 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.
### 500 / 501 / 502 / 503 / 504 — protocol problems
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:
Fix: read the text after the code. Providers almost always include a URL explaining their specific policy.
### 551 / 552 / 553 / 554
| Code | Meaning |
|---|---|
| 4.2.2 / 5.2.2 | Mailbox full |
| 4.4.1 | No answer from host |
| 4.4.2 | Bad connection, dropped mid-session |
| 4.7.1 | Delivery not authorised, temporarily |
| 5.1.1 | Bad destination mailbox address |
| 5.1.2 | Bad destination system — domain does not exist |
| 5.1.8 | Bad sender address syntax |
| 5.2.3 | Message length exceeds limit |
| 5.4.4 | Unable to route |
| 5.7.1 | Delivery not authorised |
| 5.7.13 | Sender account disabled |
| 5.7.25 | Reverse DNS does not match sending IP |
| 5.7.26 | Multiple 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.
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 foreverThree 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.
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.
The same code means different things at different stages of the session. Track which command triggered the reply.
| Stage | A failure here means |
|---|---|
| Connection | Network, firewall, or IP-level block |
| EHLO | Your hostname was rejected, or the server is refusing your IP |
| STARTTLS | Certificate or protocol version mismatch |
| AUTH | Credentials, mechanism, or permission |
| MAIL FROM | Sender not authorised, or sender domain rejected |
| RCPT TO | Recipient problem — the address, or a policy about who may receive |
| DATA / end-of-data | Content, 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.
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.
Most teams log too little to diagnose and too much to search. A good SMTP log line contains:
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.
Not every error deserves a page. A sensible policy:
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.
Apply what you just learned. Free, no signup, results in seconds.
Open the tool →A complete guide to testing SMTP servers — online testing, telnet and openssl commands, TLS verification, authentication checks and a repeatable diagnostic workflow.
DeliverabilityHow bounces work, the difference between hard and soft bounces, how to parse DSN messages, build a suppression list, and keep bounce rates under control.