SMTP Error Codes: Enhanced Status Codes and Retry Decisions
An SMTP code is an instruction about one command or delivery attempt, not a complete diagnosis. The first digit provides the broad action: success, transient failure or permanent failure. Enhanced status codes and the full remote text add context. Operators need all three, plus the command, MX, time and queue history, before automating a response.
Read SMTP reply classes and enhanced status codes
RFC 5321 defines SMTP reply classes. A 2xx reply is positive completion for the command. A 4xx reply is transient negative completion, so the client normally queues and retries within its configured lifetime. A 5xx reply is permanent negative completion; retrying the same unchanged recipient and message is not expected to succeed.
Enhanced status codes use X.Y.Z. The class repeats success, temporary or permanent meaning. The subject identifies address, mailbox, mail system, network or routing, delivery protocol, content or media, or security and policy. The detail refines that subject. RFC 5248 maintains the registry, while providers may add explanatory text and operational links.
Why the complete reply and SMTP command matter
Parsing only the visible three-digit reply loses important evidence. Treating every 4xx as a reason to retry aggressively can amplify rate limiting; treating every 5xx as an invalid address can wrongly suppress a valid recipient after a content or policy rejection. The action depends on reply class, enhanced subject, command and provider context.
Provider text can change, and one numeric code can accompany different policies. Preserve the full response and version parsers conservatively. Use known structured codes for automation, but route unknown combinations for observation rather than guessing a permanent recipient state. Store the parser decision beside the original reply so later rule changes can be audited and historical incidents can be reclassified without losing source evidence.
Classify SMTP responses and choose safe queue actions
- Capture the complete attempt. Log UTC timestamp, remote MX and IP, local IP, TLS state, SMTP command, basic reply, enhanced code, full text, queue ID and attempt.
- Classify the reply. Use the first digit for immediate queue behavior, then use the enhanced subject and text for diagnostic routing.
- Handle success correctly. Record the accepted recipient and continue the SMTP transaction. Acceptance proves handoff, not inbox placement.
- Handle transient failure. Keep the message queued, honor retry-after guidance if present, apply bounded backoff and avoid opening excessive connections.
- Handle permanent failure. Stop unchanged retries for that recipient. Decide whether to suppress the address, correct authentication, change content or escalate policy.
- Aggregate patterns. Group by receiving organization or MX, reply signature, IP, domain, stream, cohort and deployment so incidents emerge from individual attempts.
- Protect retry budgets. Set maximum queue age and attempt controls by message purpose. Expired time-sensitive mail should fail visibly rather than arrive uselessly late.
- Verify remediation. Test a representative message, observe the new remote reply and confirm queues drain without complaint or volume spikes.
Map SMTP evidence to retry, suppression or repair
| Reply evidence | Queue action | Investigation |
|---|---|---|
| 2xx after final content | Mark recipient accepted | Continue delivery accounting; do not label inbox |
| 4xx mailbox or system condition | Queue and retry with control | Watch duration and provider-wide distribution |
| 4xx security or policy condition | Slow and investigate | Review authentication, reputation, rate and full text |
| 5xx address failure | Stop and suppress address when definitive | Protect against repeated invalid-recipient attempts |
| 5xx content or policy failure | Stop unchanged retry | Correct the causal message or policy issue before resubmission |
Worked incident: provider policy deferrals build a queue
A sender sees a growing queue for one receiving network. Replies are 4xx policy deferrals, not connection failures. The surge began after a volume increase from a less-engaged cohort. Opening more connections would worsen the signal.
The MTA reduces the affected stream’s rate, keeps messages within their useful queue lifetime and preserves every full reply. Operations pauses the new cohort and verifies authentication and complaint data. As deferrals decline, capacity rises gradually. Permanent address failures discovered elsewhere follow the separate suppression path and are never retried as though they were temporary.
SMTP attempt and queue evidence to retain
- Attempt: queue ID, message ID, recipient hash or protected identifier, attempt count, time and message age.
- Connection: receiving domain, MX, remote IP, local IP, TLS result, connection count and session timing.
- Reply: command, three-digit code, enhanced status code, full text and provider reference URL.
- Context: stream, campaign, tenant, DKIM and From domain, sending IP, cohort and recent change.
- Outcome: later acceptance, permanent failure, queue expiry, suppression, corrected retry or incident linkage.
SMTP parsing and retry mistakes that cause harm
- Retrying 5xx unchanged: this wastes capacity and can look abusive.
- Suppressing every 5xx address: content, authentication and policy failures do not prove the mailbox is invalid.
- Ignoring the SMTP command: a reply to RCPT TO differs operationally from one returned after message content.
- Discarding full text: enhanced detail and provider remediation instructions may be present only there.
- Using endless retries: queue lifetime must match message value and generate a visible terminal outcome.
SMTP response troubleshooting checklist
- Log the full reply, command, MX, IP, time and queue ID.
- Parse both basic and enhanced codes conservatively.
- Treat 2xx as acceptance, not proof of inbox placement.
- Back off and bound retries for 4xx responses.
- Stop unchanged recipient retries after definitive 5xx failure.
- Separate address, content, system and policy actions.
- Aggregate patterns by provider, stream and recent change.
- Retest the repaired path and verify queue recovery.
Read the basic reply, enhanced code and text together
550 5.1.1 Recipient address rejected: user unknown
| | |
| | +-- remote explanatory text
| +-------- enhanced status: class.subject.detail
+------------ basic SMTP replyThe reply also belongs to an SMTP command. A 550 after RCPT TO can reject one recipient before message content is transferred. A 550 after the final dot can reject the completed message for content or policy. Store the command stage with the reply.
Use enhanced status subject families for routing
| Subject | Family | Typical investigation |
|---|---|---|
X.0.X | Other or undefined | Use full text and provider documentation |
X.1.X | Addressing | Recipient, sender or destination syntax/existence |
X.2.X | Mailbox | Disabled, full, inactive or recipient policy |
X.3.X | Mail system | Receiver capacity, configuration or message size |
X.4.X | Network and routing | DNS, connection, timeout or routing loop |
X.5.X | Delivery protocol | Unsupported command or protocol state |
X.6.X | Content or media | Encoding, conversion, content or media capability |
X.7.X | Security or policy | Authentication, reputation, rate, content policy or authorization |
The first digit still controls the broad queue action: 4 is temporary and 5 is permanent for that attempt. The subject does not turn every 5.7.X into an invalid recipient.
Interpret common enhanced status codes conservatively
| Code | Common meaning | Safe sender action |
|---|---|---|
2.0.0 | Success | Record acceptance for the completed command |
2.1.5 | Destination address valid | Continue transaction; not proof of final inbox placement |
4.2.0 | Other temporary mailbox condition | Queue with bounded retry and inspect duration |
4.2.2 | Mailbox full | Retry within policy; expire visibly when queue lifetime ends |
4.3.0 | Temporary mail-system condition | Correlate receiver-wide pattern and back off |
4.4.1 | No answer from host | Check DNS/network and normal retry path |
4.4.2 | Bad connection | Retry with connection controls and inspect TLS/network |
4.7.0 | Temporary security/policy condition | Slow down and investigate full provider text |
5.1.1 | Bad destination mailbox address | Stop unchanged retry and suppress when definitive |
5.1.2 | Bad destination system address | Verify domain/routing; do not classify solely as user unknown |
5.2.1 | Mailbox disabled | Stop delivery and apply address-state policy |
5.2.2 | Mailbox full as permanent response | Stop unchanged retry; retain exact provider text |
5.3.4 | Message too big | Correct message size before resubmission |
5.6.1 | Media not supported | Correct MIME/content representation |
5.7.1 | Delivery not authorized or refused | Investigate policy, authentication, reputation and full text |
Providers can return additional registered or provider-specific detail and URLs. Maintain provider parsers as versioned hints, while the raw reply remains the source evidence.
Interpret the same class differently by SMTP stage
| Stage | What a failure may indicate | Evidence |
|---|---|---|
| Connect | Network, listener, reputation block or concurrency pressure | Remote IP, timeout/refusal, TLS and connection rate |
| EHLO/HELO | Protocol, hostname or receiver policy | Presented name and advertised capabilities |
| MAIL FROM | Envelope sender, authentication or sender policy | Return path, SPF identity and full reply |
| RCPT TO | Recipient state, relay authorization or recipient policy | Protected recipient identifier and per-recipient reply |
| DATA command | Receiver not ready to accept content | Session history and size declaration |
| End of DATA | Message content, authentication, reputation or policy | Message ID, DKIM/From, content and full final response |
Inspect Postfix and Exim queues before changing them
# Postfix: list queue, JSON output where supported, inspect one message
postqueue -p
postqueue -j
postcat -q QUEUE_ID
# Exim: list queue and inspect headers, body and log for one message
exim -bp
exim -Mvh MESSAGE_ID
exim -Mvb MESSAGE_ID
exim -Mvl MESSAGE_IDRun inspection commands with appropriate privileges and protect message content. Queue bodies can contain personal or confidential data.
Unsafe/destructive commands: postsuper -d QUEUE_ID and exim -Mrm MESSAGE_ID remove queued mail. Use an exact validated ID, capture evidence first and obtain operational approval. Never replace the ID with an unresolved variable or broad queue selection. Deletion does not correct the source that generated the mail.
Use bounded provider-aware retries
Temporary failures need delayed retry, not immediate repeated connections. Use increasing intervals with jitter, provider-specific concurrency and rate controls, and a maximum queue age appropriate to message purpose. A password reset that arrives after two days may be useless; a nonurgent statement may tolerate a longer window.
| Pattern | Adjustment |
|---|---|
| Connection-level 4xx across a receiver | Reduce concurrency and connection creation |
| Policy 4xx after volume spike | Reduce recipient rate and investigate audience/reputation |
| One mailbox temporarily full | Retry that recipient without slowing unrelated providers |
| Message-specific temporary content response | Hold affected message class and inspect before mass retry |
| Queue nearing useful lifetime | Expire visibly and notify the owning application |
Do not reset retry counters by repeatedly reinjecting the same unchanged message.
Separate synchronous SMTP replies from later DSNs
An SMTP server can accept a message and later generate a Delivery Status Notification when downstream delivery fails. Parse the DSN fields and original recipient information safely; do not treat the human-readable attachment as the only evidence.
| Evidence | Meaning |
|---|---|
| Final-Recipient | Recipient identity for the reported delivery action |
| Action | Failed, delayed, delivered, relayed or expanded |
| Status | Enhanced status associated with the DSN outcome |
| Diagnostic-Code | Remote or gateway diagnostic detail |
| Will-Retry-Until | Declared retry horizon when provided for delay |
Authenticate and validate incoming bounce sources where possible, correlate with the original envelope/message ID, and prevent forged DSNs from suppressing unrelated recipients.
Version the SMTP parser and preserve unknown replies
if basic_class == 2:
action = "accepted_for_this_command"
elif basic_class == 4:
action = "queue_with_bounded_backoff"
elif basic_class == 5:
action = classify_permanent(enhanced_code, command, full_text)
else:
action = "manual_or_protocol_review"This pseudocode intentionally avoids suppressing every 5xx recipient. A definitive 5.1.1 at RCPT can drive address suppression; a 5.7.1 after DATA requires policy/authentication/content investigation. Store parser version, selected action and raw reply so old incidents can be reclassified when provider behavior changes.
Parse the complete SMTP reply before assigning a cause
451 4.7.0 Temporary server error. Please try again later.
| | |
| | provider text and possible support reference
| enhanced status code
basic three-digit replyThe first digit separates positive, temporary negative and permanent negative completion. Enhanced status codes add class, subject and detail, but provider text supplies operational context and can change. Preserve the remote hostname, command stage, complete multiline reply, queue ID, recipient domain, sending IP and UTC time. A dashboard label such as “blocked” discards evidence.
Do not parse human text alone. Normalize known codes while keeping raw replies so new or changed responses remain diagnosable.
Interpret the command stage and recipient scope
| Stage | Example boundary | Operational meaning |
|---|---|---|
| Connect/banner | Network, rate or service availability | No message transaction began |
| EHLO/STARTTLS | Protocol or transport policy | Check capability, certificate and MTA-STS/DANE context |
| MAIL FROM | Sender identity or session policy | May affect all recipients in transaction |
| RCPT TO | Recipient validity or sender policy | Classify per recipient |
| After DATA | Message/content/authentication policy | Receiver assessed submitted message |
| Later DSN | Downstream failure after acceptance | Correlate original recipient and status fields |
The same numeric reply at another stage can require a different response.
Retry temporary failures without creating a traffic attack
next_delay = min(max_delay,
base_delay * 2^attempt + random_jitter)
queue key: receiver organization + route + reply class
stop: permanent recipient failure or queue lifetime expiryUse the MTA’s standards-compliant scheduler and provider feedback. Do not immediately retry every 4xx recipient or open more connections to compensate; synchronized retries amplify receiver pressure. Separate queues by receiving organization, cap concurrency, reuse connections responsibly and preserve oldest-message age.
A 5xx is normally permanent for that transaction or recipient, but policy can change after remediation. Do not repeatedly resend the same rejected campaign automatically. Correct authentication, permission or content first and create a controlled new attempt only when justified.
Map error families to accountable investigations
| Family | First evidence | Do not do |
|---|---|---|
| Unknown user | Recipient source, first-seen and prior delivery | Retry permanently invalid addresses |
| Authentication/policy | Received artifact, SPF/DKIM/DMARC and provider requirement | Change IP before fixing identity |
| Rate/reputation deferral | Provider-hour volume, complaints, replies and queues | Increase concurrency blindly |
| Content/malware | Exact MIME, URLs, attachment and security release | Randomly rewrite until accepted |
| Mailbox full/resource | Enhanced code, duration and recipient history | Suppress immediately without policy |
Maintain provider-specific parsers as versioned mappings, but route unknown replies to review. Official support pages are more reliable than copied code lists.
Handle delivery status notifications and multiline replies without losing recipients
An SMTP transaction can produce one reply for a connection, one for each RCPT command and another after DATA. A message with ten recipients can have some accepted and some rejected before content submission. Store disposition per recipient and a transaction-level result. Do not label the whole message delivered because one recipient returned 250.
550-5.7.1 First explanatory line
550-5.7.1 Additional policy context
550 5.7.1 Final line with support reference
Final-Recipient: rfc822; [email protected]
Action: failed
Status: 5.1.1
Diagnostic-Code: smtp; 550 5.1.1 recipient does not existMultiline replies repeat the code with a hyphen until the final line uses a space. Preserve every line. A later DSN is a structured MIME report and can describe delayed, failed or delivered status after another server accepted the message. Parse its per-recipient fields and correlate Original-Envelope-ID, Final-Recipient, Action, Status and Diagnostic-Code where present.
| Class | Queue action | Audience action |
|---|---|---|
| 2.x.x success | Complete that SMTP responsibility boundary | No engagement inference |
| 4.x.x temporary | Retry under bounded schedule | Do not suppress merely from one transient reply |
| 5.1.1 invalid recipient | Stop retrying recipient | Durably suppress invalid address |
| 5.7.x policy/security | Stop transaction as directed | Investigate identity/reputation; do not call address invalid |
Provider-specific codes sometimes embed remediation URLs or identifiers. Sanitize them for dashboards but keep the raw value under access control. Group variants into a normalized family only after exact parsing tests, and measure the unknown family so parser drift cannot disappear.
When a receiver changes wording, update mappings prospectively and replay a governed sample. Do not rewrite historical categories without recording the classifier version.
Turn normalized replies into safe queue controls
Define actions at provider and reply-family level: normal scheduling, reduced concurrency, longer backoff, route hold, recipient suppression or security escalation. Automatic rules need minimum volume, expiry and an owner. A temporary reputation deferral should slow the relevant receiver queue; it should not block unrelated networks or convert recipients to hard bounces.
Monitor attempted recipients, unique recipients, reply events, oldest queue age, retry attempts and final outcomes. Event count can grow during retries even when recipient count does not, so use both. Alert on a rising share of unknown replies because provider wording or parser behavior may have changed.
When an incident ends, let the queue recover under controlled throughput. Releasing every deferred message at once can recreate the condition. Prefer oldest appropriate wanted mail, respect message expiry and suppress recipients whose status became permanent meanwhile. Keep a sample of final replies after recovery to prove the receiving boundary normalized.
Test the reply parser against real and adversarial fixtures
Maintain sanitized fixtures for multiline replies, missing enhanced codes, IPv6 addresses, Unicode text, provider URLs, commas, line wrapping and DSNs with several recipients. Assert the raw value remains intact, normalized family is correct and no address or token leaks into broad dashboards.
Unknown input must produce an unknown classification, not success. Version mappings, measure classification coverage and require review before an automated action becomes more destructive, such as suppression or route shutdown.
Escalate with a compact reproducible case
Provide the receiving organization, affected IP/domain, UTC window, representative full replies, queue behavior, authentication evidence, recent changes and corrective actions. Use anonymized recipient examples requested by the provider. A support ticket should demonstrate that the sender has stopped harmful traffic and can reproduce the failure; it should not ask the receiver to override unresolved permission or security problems.
Primary references
- RFC 5321: Simple Mail Transfer Protocol
- RFC 3463: Enhanced Mail System Status Codes
- IANA SMTP Enhanced Status Codes registry


