Start with SMTP reply class
RFC 5321 defines 4xx replies as transient negative completion responses and 5xx replies as permanent negative completion responses. That high-level distinction should survive all the way into your lead database. A 421 or 451 normally means “not accepted now”; a 550-class unknown-user response can mean “this address cannot be delivered as addressed.” If both are collapsed into one boolean bounced=true field, the system cannot make a sensible retry or suppression decision.
Use enhanced status codes to refine the reason
RFC 3463 adds structured x.y.z status information. The first digit still distinguishes success, persistent transient failure, and permanent failure, while later digits describe subject and detail. Store the enhanced status when the receiver provides it. A 4.2.2 mailbox-full event and a 4.7.28 provider rate limit are both temporary classes, but they point to different operational actions. Likewise, a 5.1.1 invalid mailbox is different from a 5.7.x policy rejection.
Permanent recipient failure should travel across mailboxes
If a recipient address is confirmed invalid with a permanent mailbox-level failure, suppress it globally rather than letting another sender mailbox try the same lead tomorrow. Rotating mailboxes does not make a nonexistent address exist. Global suppression protects domain reputation and prevents embarrassing repeated attempts. Record the evidence that created the suppression—timestamp, SMTP code, diagnostic text, and original address—so a future manual override can be reviewed rather than guessed.
Temporary failures belong in a delivery state, not a delete state
A 4xx response should usually preserve the lead while the transport retries or the operator investigates. Do not automatically schedule a fresh campaign touch; the existing message may still be in the MTA queue. Track states such as deferred, retrying, expired, and accepted separately from hard-bounced. Once the transport gives up according to its queue policy, the outbound application can decide whether the campaign touch should be rescheduled, but the address still should not be labeled permanently invalid based only on the transient response.
Policy 5xx may implicate the sender, not the recipient
A permanent 5.7.x rejection can be caused by authentication, content, or sender policy. Suppressing the recipient because Outlook returned 5.7.515 would hide a sender-side authentication failure and unnecessarily shrink the list. The suppression rule should therefore inspect the failure subject, not only the first digit. Recipient-address failures are strong hygiene signals; sender-policy failures are infrastructure incidents. A good parser routes them to different queues.
Mailbox full needs patience and a limit
Mailbox-full conditions are commonly temporary, especially when reported in a 4.2.2 class. Retry according to the transport policy, but do not retry forever. If the condition persists across repeated attempts over a meaningful period, mark the lead for manual review or stale-address re-verification rather than blindly continuing every campaign. The distinction is important: “temporarily full today” is not the same evidence as “mailbox does not exist,” but persistent inability to accept mail still affects whether the address is useful for outbound.
Build a suppression taxonomy
At minimum, separate permanent invalid recipient, temporary recipient issue, sender authentication or policy failure, provider throttling, content policy block, and unknown parser result. Each class should map to a different action. Invalid recipient becomes global suppression; temporary recipient failure enters retry; authentication failure pauses the sender path; throttling reduces pressure; unknown results retain the raw message for review. This structure keeps one SMTP error from triggering the wrong operational response.
Test your parser with real provider strings
Do not design the classifier only from ideal RFC examples. Feed it real Gmail, Outlook, Yahoo, and provider-generated DSNs collected from your own operations. Keep the raw diagnostic beside parsed fields so future provider wording changes are visible. Unit tests should include at least one temporary rate limit, temporary mailbox issue, permanent unknown user, and permanent authentication policy rejection. The parser is part of deliverability safety because it decides who gets retried and who gets suppressed.
Make suppression depend on recipient evidence, not only the first digit
The first SMTP digit is the starting branch: 4xx means a temporary condition and 5xx means a permanent failure for that attempt. But suppression policy still needs the enhanced status code and diagnostic context. A permanent `5.1.x` recipient-address failure is strong evidence that the address should not be attempted again across your outbound mailboxes. A `5.7.x` policy rejection may instead describe your sender authentication, reputation, or message policy and can affect perfectly valid recipients. If you globally suppress the address for every 5xx response, you can convert a sender-side incident into unnecessary list loss.
Represent delivery state with explicit reason fields: SMTP class, enhanced status, provider diagnostic, recipient, sending domain, and timestamp. Then define narrow terminal states such as invalid recipient, domain does not accept mail, or confirmed opt-out separately from sender-policy failures. Temporary mailbox-full and rate-limited responses remain retryable until your queue expiry policy decides otherwise. This structure also improves campaign analytics: list-quality metrics can count genuine recipient failures without being inflated by a temporary provider block. Test the parser against raw strings from Google, Yahoo, Microsoft, and your own DSNs because providers wrap the same basic classes in different wording. A suppression rule should be explainable from stored evidence, not hidden inside a regex named `hardBounce`.
Field checklist
- Store SMTP reply class and enhanced status code separately.
- Suppress permanent recipient failures globally across mailboxes.
- Do not suppress a lead for a sender-side 5.7.x policy rejection.
- Keep 4xx deliveries in retry/review state rather than hard bounce.
- Retain raw provider diagnostics for parser QA.
- Unit-test the classifier against real Gmail, Outlook and Yahoo examples.
Primary sources
Standards and provider policies can change. These links are the reference points used for this field note.
- RFC 5321 — Simple Mail Transfer ProtocolIETF / RFC Editor — SMTP reply classes, retry semantics, envelopes and mail transport behavior.
- RFC 3463 — Enhanced Mail System Status CodesIETF / RFC Editor — 2.x.x, 4.x.x and 5.x.x delivery status code classes.
- SMTP Error CodesYahoo Sender Hub — Yahoo guidance for temporary deferrals, permanent errors, unknown recipients and traffic-pattern problems.
- Gmail SMTP errors and codesGoogle Gmail Help — Temporary and permanent Gmail SMTP errors, including authentication and unusual-rate failures.
- Outlook requirements for high-volume sendersMicrosoft Defender for Office 365 Blog — SPF, DKIM and DMARC requirements for high-volume mail to Outlook.com consumer domains.