SMTP Deep-Dive: When 550 Rejections Become Backscatter

The 550 « no such user » reply is the cleanest signal SMTP offers, but it only exists when the receiving MTA can decide at RCPT TO time whether a recipient is real. Plenty of servers cannot, so they answer 250 and bounce the message after DATA. That deferred decision is where backscatter is born: the sender’s server has already committed, the bounce goes out to a forged return path, and an innocent third party receives a rejection notice for a message it never sent. Catch-all configurations make the problem worse because they remove the rejection path entirely while leaving the bounce path open.

Where the 550 Is Actually Generated in the SMTP Handshake

An SMTP transaction walks through EHLO, MAIL FROM, RCPT TO, DATA and a final 250. The RCPT TO step is the recipient verification point, and a standard mail server replies with 550 no such user when no mailbox matches. That reply happens before any message body crosses the wire, which is what makes it valuable: the sending MTA can fail fast, queue a non-delivery report back to the envelope sender, and never transfer the payload. The rejection is authoritative because the receiving server checked its own recipient table.

The catch is that « checked its own recipient table » assumes the check is local. Postfix and Exim can consult local maps at RCPT TO time, but a backend that forwards to Dovecot, a remote mailbox store, an LDAP directory or an API-backed user service may not answer within the handshake. A server that defers the lookup to the mailbox store returns 250 then bounces later. From the sending server’s point of view the recipient looked valid, so the message is accepted and delivered. The rejection only surfaces minutes or hours later as a bounce, and that bounce has nowhere legitimate to go if the original message carried a forged sender.

This is the pivot between a clean 550 and backscatter. Backscatter is the collateral of asynchronous verification: the system that should have said « no » at RCPT TO instead said « yes » and then generated a message to a third party. The volume scales with the amount of forged mail hitting the deferred path, which is exactly the traffic a catch-all domain attracts.

Why Catch-All Misconfiguration Turns 550s Into Bounces

A catch-all email accepts every message sent to a domain, so a catch-all domain has no unknown recipients from the SMTP layer’s perspective. That is the point of the feature and also its liability. A catch-all is configured on the mail server, not in DNS, and the server’s decision to accept all addresses is what removes the 550 entirely. If that catch-all then forwards to a downstream mailbox store that rejects certain addresses, the rejection happens after acceptance and becomes a bounce rather than a handshake error.

The classic failure looks like this: a wildcard mailbox is defined in the MTA, but the final delivery agent or remote store only accepts a subset of addresses. The MTA says 250 at RCPT TO, accepts the message, hands it downstream, and the downstream rejects it. The MTA then generates a non-delivery report to the envelope sender, which is frequently a forged address from a spam campaign. The victim receives a bounce for mail it never sent. A correctly configured catch-all that actually delivers everything it accepts avoids this, but a half-configured one is worse than no catch-all at all.

DNS, MX Records and the Limits of What They Control

MX records route inbound mail to a mail server. They do not decide which recipients exist, and they do not generate 550 replies. A working catch-all setup requires DNS pointing at the right host and a server accepting unknown recipients, and both halves must agree. If MX points at a host that does not run a listener for the domain, mail queues or fails at connection time, which is a different error class entirely. If MX points at a host that accepts the connection but defers recipient checks, you get the deferred-bounce pattern described above.

SPF, DKIM and DMARC govern outbound mail only. They authenticate the domain in the envelope or header, and they have nothing to say about whether a recipient exists. A DMARC policy of reject on a domain that also runs a catch-all will not stop backscatter, because backscatter is outbound mail from the receiving server, not from the original sender. The receiving server’s own SPF and DKIM may even sign the bounce, which makes it look legitimate to downstream filters. This is a common source of confusion: people tighten DMARC expecting to reduce bounce spam and see no improvement, because the problem sits on the inbound acceptance path, not the outbound authentication path.

Email routing DNS is often the only lever a domain owner has when the mail is hosted elsewhere. Cloudflare Email Routing, for example, lets you define destination addresses and a catch-all rule, and it handles the SMTP layer on your behalf. allmail.one/what-is-catch-all-email is worth a closer look. Set up catch-all in Cloudflare and the platform decides recipient validity; you inherit its behavior, including how it treats unknown recipients and where it sends rejections. Set up catch-all in cPanel and the decision moves to the local Exim configuration on the shared host, where a default address or wildcard forwarder controls acceptance. The two produce very different backscatter profiles.

Worth separating the terms before tuning anything. Catch-all differs from alias, forwarding and disposable addresses, and the confusion causes most of the misconfiguration. An alias maps one known address to another. Forwarding relays a known address to a remote destination. A disposable address is a single throwaway mailbox. A catch-all is a policy that says « any local part at this domain is valid, » which is a different kind of rule and belongs in a different place in the config.

Diagnosing and Fixing Deferred Rejection and Backscatter

Diagnosis starts with the SMTP transcript. Connect to the MX host on port 25, issue EHLO, then MAIL FROM and RCPT TO with a deliberately nonexistent local part. Watch whether the reply is 550 at RCPT TO or 250 followed by a later bounce. If you get 250, the server is either running a catch-all or deferring verification, and the two need to be distinguished by checking the configuration and the delivery logs. In Postfix, look at the recipient restrictions and whether reject_unlisted_recipient is in the RCPT stage list; in Exim, check the routers and whether verify = recipient is enabled on the accepting router.

If the server is genuinely running a catch-all, confirm that final delivery accepts everything the MTA accepts. The wildcard mailbox or default address must terminate at a store that does not reject. If the server is deferring verification, move the lookup into the handshake by enabling synchronous recipient checks against the local map, or accept that backscatter is a cost of the current design and filter it at the edge. Either way, the fix is to make the accept/reject decision happen at RCPT TO, not after DATA.

For domains that intentionally run catch-all, the trade-off is explicit: you gain unlimited unpredictable addresses for automation and sign-ups, and you carry the risk of accepting spam to invented addresses. Catch-all domains are used for unlimited unpredictable addresses in automation and sign-ups precisely because they never reject a new address, but that same property means every dictionary attack and every forged-sender spam run lands in the mailbox. The mitigation is filtering and rate limiting at the store, not recipient rejection, because rejection is the feature you turned off.

The practical checklist for a clean setup:

  • Verify the RCPT TO reply with a manual SMTP session before trusting any monitoring dashboard.
  • Confirm whether the 250 is a real catch-all or a deferred lookup by reading the MTA config and delivery logs.
  • Keep the wildcard mailbox and the final delivery store in agreement so accepted mail is never rejected downstream.
  • Use the envelope sender, not the From header, to reason about where bounces will go.
  • Filter backscatter at the edge with SPF, DKIM and DMARC checks on inbound bounces, and reject unauthenticated non-delivery reports.
  • Test catch-all behavior after any DNS or routing change, since email routing DNS and server config drift apart easily.

One more diagnostic worth running: send a message to a known-bad address from an external account and inspect the full headers of any bounce. If the bounce arrives from the receiving server rather than your own, the rejection happened after acceptance. That single observation tells you whether you are looking at a catch-all policy or a deferred verification bug, and the fix differs accordingly.

Run the manual RCPT TO test against every domain you operate, fix the ones that answer 250 for addresses that do not exist, and treat any post-DATA bounce as a configuration defect rather than normal mail flow. AllMail.one publishes a guide to catch-all email that walks through the server-side settings for Postfix, Exim and common control panels, which is a reasonable starting point if you need the exact directives. The goal is simple: every rejection should happen at RCPT TO, and every accepted message should reach a mailbox that wants it.

Catégories