Your monitoring fires at 3 AM: "SMTP delivery failures spiking." You check the logs and see 550 5.1.1 User unknown, 421 Try again later, and 535 Authentication failed. Which ones do you retry? Which ones mean your config is broken? Which ones are permanent?
The Mental Model
SMTP response codes follow a simple pattern defined in RFC 5321:
- 2xx — Success. The message was accepted.
- 4xx — Temporary failure. Try again later — the problem might resolve itself.
- 5xx — Permanent failure. Don't retry — the message will never be accepted.
That's the spec. In practice, real-world mail servers bend these rules constantly. Some servers return 4xx for permanent problems (to avoid giving spammers useful information). Some return 5xx for temporary issues (misconfigured servers). Treat the codes as guidelines, not gospel.
4xx Codes — Temporary Failures (Soft Bounces)
421 — Service Not Available
The server is temporarily unable to handle your connection. Common causes: server restarting, too many concurrent connections, rate limiting kicking in. Action: Retry with exponential backoff.
450 — Mailbox Unavailable
The recipient's mailbox exists but is temporarily unavailable — usually because it's locked by another process or the server is applying policy checks. Action: Retry after 5-15 minutes.
451 — Local Error in Processing
The receiver's server hit an internal error while processing your message. This is the server's problem, not yours. Action: Retry with backoff. If persistent, the recipient's server admin needs to fix it.
452 — Insufficient Storage
The recipient's mailbox is full, or the server is out of disk space. Action: Retry periodically (hours, not minutes). Consider alerting if this persists for the same recipient — their mailbox may be permanently full (abandoned account).
5xx Codes — Permanent Failures (Hard Bounces)
550 — Mailbox Not Found
The most common permanent error. The email address doesn't exist on that server. 550 5.1.1 The email account does not exist is Gmail's version. Action: Add to suppression list immediately. Do not retry. Continuing to send to non-existent addresses damages your sender reputation.
551 — User Not Local
The recipient's server knows the address but says the user has moved. Sometimes includes a forwarding address. Action: Update the recipient address if a forward is provided. Otherwise, suppress.
552 — Message Too Large
Your message exceeds the recipient server's size limit. Action: Reduce attachment sizes or host them externally. Don't retry without reducing the message size.
553 — Mailbox Name Invalid
The email address format is rejected — the local part contains characters the server doesn't accept. Action: Validate email addresses at signup. Suppress this address.
554 — Transaction Failed
A catch-all permanent error. Often used for policy rejections: "Your IP is blacklisted," "Message rejected due to content," "SPF check failed." Action: Read the full error text. It usually contains the specific reason.
Authentication Errors
535 — Authentication Failed
Your SMTP username or password is wrong, or the auth mechanism isn't supported. Action: Check your credentials immediately. This is a configuration error, not a recipient problem. Don't retry — every failed auth attempt may trigger account lockout.
530 — Authentication Required
The server requires authentication but you're trying to send without it. Action: Update your SMTP config to include credentials. This isn't a transient error.
Retry Strategy
| Code Class | Strategy | Max Retries | Backoff |
|---|---|---|---|
| 421 | Retry | 5 | 1min, 5min, 15min, 1hr, 4hr |
| 450, 451 | Retry | 3 | 5min, 30min, 2hr |
| 452 | Retry (slow) | 3 | 1hr, 6hr, 24hr |
| 550 (5.1.1) | Suppress | 0 | — |
| 552 | Fix message | 0 | — |
| 535, 530 | Fix config | 0 | — |
| 554 | Investigate | 0 | — |
Debugging the SMTP Conversation
When error codes aren't enough, you need to see the full SMTP conversation — the sequence of commands and responses between your app and the receiving server.
Send your email through MailHog.site and inspect the full headers and SMTP session data. You'll see every EHLO, MAIL FROM, RCPT TO, and DATA exchange, making it clear exactly where the conversation fails.
FAQ
Should I retry on all 4xx errors?
Yes, with exponential backoff. But set a maximum retry count (3-5 attempts) and a maximum retry window (24-48 hours). If a 4xx persists beyond that, treat it as a permanent failure for operational purposes.
What does "5.7.1 Message rejected due to content" mean?
The receiving server's content filter flagged your message as spam or policy-violating. Check your email's spam score and review the content for triggers. Common causes: URL shorteners, ALL CAPS subjects, or sending from a domain without proper DKIM/SPF/DMARC authentication.
How do I build a suppression list?
Add any email address that returns a 550 (5.1.1) to a suppression list in your database. Before sending any email, check the suppression list first. Most email APIs (SendGrid, Postmark, SES) maintain their own suppression lists, but you should maintain your own too for the addresses you've collected directly.