DEV Community

Dhiraj Chatpar
Dhiraj Chatpar

Posted on • Originally published at postmta.com

SMTP Error Codes Explained: What Every Developer Must Know

SMTP Error Codes Explained: What Every Developer Must Know

SMTP error codes are the diagnostic language of email delivery. Most developers know "550 error" means rejected, but the enhanced status codes tell a much richer story.

The SMTP Status Code Structure

Every SMTP response has a enhanced status code: class subject detail

4.2.0  - Persistent transient failure (retry)
5.7.1  - Permanent failure (never retry)
Enter fullscreen mode Exit fullscreen mode

Class 2: Success
Class 4: Persistent transient failure (try again)
Class 5: Permanent failure (suppress)

The Most Important Codes

550 5.1.1 - User Unknown

Permanent. This email address does not exist. Add to suppression immediately. Never retry.

450 4.2.0 - Mailbox Busy

Transient. The recipient's mailbox is temporarily unavailable. Retry with exponential backoff. Usually resolves within hours.

421 4.4.2 - Connection Throttled

Transient. Your sending is too fast for this receiver. Slow down and retry. KumoMTA handles this automatically via adaptive throttling.

550 5.7.1 - Blocked by Policy

Permanent. The receiver's policy blocked this message. Could be spam content, attachment policy, or sender reputation. Investigate before retrying.

554 5.6.0 - Invalid Content

Permanent. The email content triggered a filter. Check for spam patterns, suspicious attachments, or encoding issues.

KumoMTA's Classification Engine

KumoMTA maps raw SMTP responses to enhanced codes automatically:

# Example bounce classification
code = parse_smtp_response(response)
enhanced = classify_enhanced_status(code)

# enhanced.code = "4.2.0"
# enhanced.text = "Mailbox status"
# enhanced.retry = True
# enhanced.suppress = False
Enter fullscreen mode Exit fullscreen mode

This enables intelligent queue management. Some bounces get immediate retry. Others get permanent suppression.

The Diagnostic Power

Without enhanced codes, you cannot distinguish:

  • "Mailbox does not exist" (suppress) from "Mailbox full" (retry)
  • "Connection throttled" (slow down) from "Server shutting down" (wait longer)
  • "Policy violation" (fix content) from "Sender reputation" (fix sending)

Using Bounce Data

Store every bounce with full enhanced code:

CREATE TABLE bounces (
  recipient TEXT,
  smtp_code TEXT,
  enhanced_code TEXT,
  retry_count INTEGER,
  first_seen TIMESTAMP,
  last_seen TIMESTAMP
);
Enter fullscreen mode Exit fullscreen mode

This data becomes your suppression list intelligence. Over time you learn which receivers are reliable and which require extra retry tolerance.

PostMTA provides real-time bounce dashboards with enhanced code analysis, so you always know why messages fail and what action to take.

Top comments (0)