Bounce processing and DSNs explained

Bounce processing means catching every delivery failure, reading its status code, and deciding whether to retry, fix something on your side, or stop mailing the address. Failures reach you in two ways: as a rejection during the SMTP session, or as a delivery status notification (DSN) mailed later to your return path. A DSN has a standard, machine-readable format: RFC 3464 fields inside an RFC 6522 multipart/report message. Suppress permanent address failures at once, retry temporary ones, and suppress an address only when its temporary failures keep repeating.

Two ways a bounce reaches you

At SMTP time. The receiving server refuses the recipient or the message with a 4xx or 5xx reply while your server is still connected. Your mail server or sending platform records the reply. If it was relaying the message for you, it then writes a DSN itself: RFC 3464, section 2.2.2, says that when a relaying client gets an error reply to RCPT, the client generates the DSN.

Later, by mail. The receiving server accepted the message and failed afterwards, for example because it was relaying the message and the next system refused it, or the address was a mailing list. RFC 5321, section 6.1, then requires it to send a notification to the envelope return path, with a null sender (<>).

M3AAWG's Sender Best Common Practices (version 3.0, February 2015, section 3.8) puts it in numbers: in practice about 95% of returns happen during the SMTP session, and the rest can arrive hours or days later. Your process has to handle both, at the same volume and rate at which you send.

The return path

Every message has an envelope sender, the address in the MAIL FROM command (RFC 5321 calls it the reverse-path). At final delivery, the receiving server copies it into a Return-Path header field (section 4.4). Its main purpose is to say where non-delivery messages go. It may differ from the sender's own mailbox: the RFC mentions a dedicated error-handling mailbox and mailing lists that route errors to the list maintainer.

Notifications themselves are sent with an empty return path, MAIL FROM:<>, so a failed notification cannot cause another one (RFC 5321, section 4.5.5; RFC 3464, section 2). For senders, this means: use a return path whose mail is processed by software, not a person's inbox.

VERP: one return path per recipient

Bounces may not say which address failed, or may name a forwarding target that is not on your list. D. J. Bernstein's Variable Envelope Return Paths (February 1997) solves this by giving each recipient a different envelope sender that encodes the recipient's address. For a message to pat@example.net:

MAIL FROM:<news-bounces-pat=example.net@example.com>
RCPT TO:<pat@example.net>

Any bounce for that copy comes back to that address, however unhelpful its content, so the failed address is in the envelope. The same trick works per message, with a send id in the return path. Your mail server must set the sender per recipient and deliver all news-bounces-* addresses to one handler. Keep each message's return path identical on every retry, or greylisting servers may treat each retry as a new message.

The DSN format

The multipart/report container

RFC 6522 (January 2012) defines multipart/report, a container for mail system reports. Its report-type parameter names the type of the second part. It has two or three parts, in this order:

  1. a human-readable explanation (required);
  2. a machine-readable report (required), for a DSN of type message/delivery-status;
  3. the returned message or part of it (optional), sometimes only its header as text/rfc822-headers.

RFC 3464, section 2, adds the DSN rules: the report-type is delivery-status, the DSN goes to the original envelope return address, it is sent with MAIL FROM:<>, and its From field should be a person responsible for the reporting mail system, such as the postmaster. One DSN covers exactly one message, but may report on several of its recipients.

The delivery-status fields

The message/delivery-status part has one block of per-message fields, then one block per recipient, separated by blank lines (RFC 3464, section 2.1). Section 3 says a minimal DSN carries only Reporting-MTA, Final-Recipient, Action and Status, so your parser must not depend on the rest.

FieldLevelWhat it tells you
Reporting-MTAmessage, requiredThe server that attempted the delivery and reports on it.
Original-Envelope-Idmessage, optionalYour ENVID value, if you sent one (see below).
Arrival-Datemessage, optionalWhen the message reached the reporting server.
Original-Recipientrecipient, optionalThe address you sent to, if you passed it with ORCPT.
Final-Recipientrecipient, requiredThe recipient address as the reporting server had it, possibly after forwarding.
Actionrecipient, requiredfailed, delayed, delivered, relayed or expanded.
Statusrecipient, requiredAn enhanced status code such as 5.1.1.
Remote-MTArecipient, optionalThe server that gave the error. If absent, the reporting server issued it.
Diagnostic-Coderecipient, optionalThe original reply, such as an SMTP line with its text.
Will-Retry-Untilrecipient, delayed onlyWhen the server plans to give up.

Read Action and Status together. Section 2.3.3 points out that a temporary 4.x.x status can come with Action delayed (still retrying) or Action failed (the server gave up). A delayed DSN is not a bounce.

An example DSN

An illustrative failed DSN, written by the sender's own server after the receiving server refused the recipient, and returned to the VERP address above:

Return-Path: <>
From: Mail Delivery System <postmaster@mta1.example.com>
To: news-bounces-pat=example.net@example.com
Subject: Undelivered Mail Returned to Sender
Date: Thu, 05 Nov 2026 14:12:09 +0000
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
    boundary="dsn-b1"

--dsn-b1
Content-Type: text/plain; charset=us-ascii

Your message to pat@example.net could not be delivered.
The receiving server says this mailbox does not exist.

--dsn-b1
Content-Type: message/delivery-status

Reporting-MTA: dns; mta1.example.com
Original-Envelope-Id: nov-update-8f3a2c
Arrival-Date: Thu, 05 Nov 2026 14:12:03 +0000

Original-Recipient: rfc822; pat@example.net
Final-Recipient: rfc822; pat@example.net
Action: failed
Status: 5.1.1
Remote-MTA: dns; mx.example.net
Diagnostic-Code: smtp; 550 5.1.1 <pat@example.net>: Recipient address rejected: User unknown
Last-Attempt-Date: Thu, 05 Nov 2026 14:12:09 +0000

--dsn-b1
Content-Type: text/rfc822-headers

From: Example News <news@example.com>
To: pat@example.net
Subject: November update
Message-ID: <20261105141203.8f3a2c@example.com>

--dsn-b1--

The DSN SMTP extension

RFC 3461 lets a sender ask for specific notifications. A server that supports it lists DSN in its EHLO reply, and the client adds parameters (section 4):

MAIL FROM:<news-bounces-pat=example.net@example.com> RET=HDRS ENVID=nov-update-8f3a2c
RCPT TO:<pat@example.net> NOTIFY=FAILURE,DELAY ORCPT=rfc822;pat@example.net

ENVID and ORCPT let you match a DSN to your send and to the address on your list. They only help while every server on the path supports the extension, the weakness Bernstein's VERP note pointed out; VERP needs only your own server. For addresses with non-ASCII characters, RFC 6533 adds an international address type and a message/global-delivery-status report (see internationalized email addresses).

Enhanced status codes

The Status field uses the codes of RFC 3463: class.subject.detail. The class is 2 (success), 4 (persistent transient failure: a later attempt may succeed) or 5 (permanent failure: the message or the destination must change). The subject says where the problem is:

SubjectArea
X.1.XAddressing, such as a mailbox that does not exist
X.2.XMailbox, such as a full mailbox
X.3.XThe destination mail system
X.4.XNetwork and routing
X.5.XThe mail delivery protocol
X.6.XMessage content or media
X.7.XSecurity or policy, such as filtering and authentication

A client must recognize the class even when it does not know the subject (section 2). For specific codes and what each provider means by them, see the bounce code dictionary.

Classify and suppress

M3AAWG defines a hard bounce as a permanent failure, such as an address or domain that does not exist, and a soft bounce as a temporary one, such as a full mailbox, a connection problem or throttling. It also warns that the codes tell the server what to do, not whether to keep the address, so read the text as well. Many 5xx replies are policy refusals about your sending, not the address.

What came backClassWhat to do with the address
550 5.1.1: mailbox does not existHardSuppress now. Do not retry.
452 4.2.2: mailbox fullSoftKeep; let the queue retry. Suppress if it keeps repeating.
552 5.2.2: mailbox full, given upHard, usuallySuppress if it names the recipient's mailbox; at Microsoft 365 it can be your own sending quota.
5.7.x policy refusal, such as 550 5.7.1Sending problemKeep the address; fix reputation, authentication or the listing.
4.x.x deferral, Action delayedNot a bounceNothing yet.
4.4.7: delivery time expiredDepends on the last errorLook at the last error recorded before it expired.

When to suppress, according to the sources that give a rule:

Two more rules. DSNs can be forged as easily as any mail (RFC 3464, section 4.1), so act only on DSNs that match a message you sent, by VERP address or ENVID. And suppress rather than delete, so a later import cannot bring the address back (list cleaning).

Where verification fits

Bounce processing reacts after a send; verification finds many bad addresses before one. An address that does not exist is invalid with the reason no_mailbox, and a mailbox over its limit is invalid with mailbox_full; both carry the action remove. A check is a snapshot, so a valid address can still bounce later, and policy refusals have nothing to do with the address. You still need bounce processing. The wider plan is in reduce your bounce rate.

Questions

Is a DSN the same as an NDR?

Mostly. A non-delivery report (NDR) is any message saying a delivery failed. A DSN with Action failed is the standard format for one; some systems use their own formats, which is why parsers also read the text.

Why did I get a DSN when nothing bounced?

Check the Action field. Delayed means the server is still retrying, and Will-Retry-Until may say until when. Delivered or relayed is a positive notification, usually because you asked for one with NOTIFY=SUCCESS.

Try it

Before your next campaign, run the list through bulk email verification and suppress the rows whose action is remove, or look up a single address in the free email checker.

Sources

How we wrote this: drafted by the email-validation.org team with the help of AI writing tools, from our product documentation and the sources linked in the text.

Get up to 500 free credits. No card needed.

New accounts get 500 free credits (100 when you sign up with a free email provider such as Gmail, Outlook or Yahoo, or another personal mailbox such as a paid one like Fastmail or one from your internet provider). Try it on your own list before you buy.

Updated · Maintained by the email-validation.org team