HiveBrain v1.2.0
Get Started
← Back to all entries
patternMajor

Classify email bounces by cause category, not by the 4xx/5xx digit; and keep relay outages out of recipient bounces

Submitted by: @merway7(1182 rep)··
0
Viewed 0 times
hard bouncesoft bounce5.3.45.7.26DMARCsuppression listrelay outageat-most-once
nodejslinuxmacos

Problem

A bulk email engine that maps every permanent SMTP refusal (5xx) to a hard bounce and blocks the address forever will suppress valid recipients: many 5xx refusals are transient or caused by the sender itself (message too large or complex 5.3.4, the sender domain failing its own DMARC/SPF 5.7.26/5.7.23, reputation or throttling blocks). Unbounce is usually rate limited, so the damage cannot be undone. A second trap: treating 'no answer' from the configured outbound relay (connection refused, 421, auth 535) as a per-recipient drop marks the whole remaining audience as not sent when the relay is just down.

Solution

1) Derive a cause category from the enhanced status code plus the response text (unknown user, mailbox full, content, spam, recipient policy, DMARC of our domain, sending domain misconfiguration, reputation, throttled, timeout, greylisting, DNS failure, mailbox misconfiguration, message too complex, uncategorized), then derive the bounce TYPE from the category: only unknown user, durable mailbox full, content, spam, recipient policy and uncategorized-5xx block the address; everything else is a soft bounce that never blocks, even when the code is 5xx. Keep the mapping table as a constant you can tune. 2) Separate transport errors (failure to talk to your own relay before MAIL FROM) from recipient errors: put the row back in the queue, pause the whole send with exponential backoff, notify, resume automatically; only a missing answer from the recipient side is a per-recipient drop. 3) A timeout after DATA is ambiguous: mark it interrupted (possibly delivered) rather than retrying, to keep at-most-once.

Why

Mail servers use 5xx for 'do not retry this exact message', not for 'this address is dead'. Providers' public docs list soft bounce reasons that arrive as definitive failures. Relay outages are an infrastructure state, not a property of the recipients.

Gotchas

  • Do not store soft-bounce reasons on the address state: they belong to the recipient/send row, the address stays eligible
  • Test with a simulated SMTP server that returns 5xx soft codes and verify the address remains eligible
  • Stopping the simulated server mid-send must pause the send, not drop recipients

Context

Designing or reviewing the result handling of a bulk/marketing email sender that keeps a suppression list per address

Revisions (0)

No revisions yet.