DSN: what RFC 3461-3464 actually define
A standards-first look at Delivery Status Notifications: the machine-readable bounce format that replaced free-form, unparseable failure messages.
Before Delivery Status Notifications existed, every mail transfer agent (MTA) wrote its own free-form bounce text. One server said "user unknown." Another said "550 mailbox not found." A third buried the reason in three paragraphs of prose aimed at a human reader, not a parser. Any system that needed to act on a failure, suppress a dead address, retry later, alert an operator, had to guess at the cause from whatever wording that particular server happened to choose.
The problem with free-form bounces
Parsing a bounce message meant writing regexes against text that had no contract. A server upgrade could reword its failure message overnight and silently break every downstream system that depended on the old phrasing. Two servers could report the identical failure, a nonexistent mailbox, in wording different enough that no shared pattern caught both. There was no field for "this is a permanent failure" versus "try again later," only a paragraph a human was expected to read and interpret.
What DSN defines
Four RFCs, published together in 2003, define Delivery Status Notifications as a set.
RFC 3461 defines the SMTP extension a sender uses to request a DSN: the RET and ENVID parameters on MAIL FROM, and the NOTIFY parameter on RCPT TO. RFC 3462 defines the multipart/report MIME container that carries the notification, a format later reused by the Abuse Reporting Format (ARF). RFC 3464 defines the DSN message format itself: the machine-readable fields that describe what happened, to whom, and why. RFC 3463 defines the enhanced status code format, the x.y.z notation that classifies a failure independent of the SMTP reply code that came with it.
Together, they turn a bounce from prose into a structured record with a defined field for the outcome, the recipient, and the reason.
How DSN works
A sender requests a DSN by adding parameters to the SMTP envelope:
MAIL FROM:<sender@example.com> RET=FULL ENVID=xyz123RCPT TO:<recipient@example.net> NOTIFY=SUCCESS,FAILURE,DELAY
RET tells the generating MTA whether to include the full original message or just its headers. ENVID is an opaque identifier the sender attaches so it can match a returned DSN back to the message that triggered it. NOTIFY lists which outcomes should generate a report: success, failure, delay, or some combination.
When one of those conditions occurs, typically a failure, the receiving or relaying MTA generates a multipart/report message and sends it back to the envelope sender. That message bundles three parts: a human-readable explanation, a machine-readable message/delivery-status part, and optionally the original message or its headers, depending on what RET requested.
Anatomy of a DSN
A message/delivery-status part has two groups of fields: one block that describes the message as a whole, and one block per recipient.
Per-message fields:
| Field | What it holds |
|---|---|
Original-Envelope-Id | The sender's ENVID, echoed back so the DSN can be matched to the original send |
Reporting-MTA | The server that generated this DSN |
Arrival-Date | When the message arrived at the reporting MTA |
Per-recipient fields:
| Field | What it holds |
|---|---|
Final-Recipient | The address this block reports on |
Action | One of failed, delayed, delivered, relayed, or expanded |
Status | The enhanced status code, x.y.z, from RFC 3463 |
Diagnostic-Code | The underlying protocol-specific response, typically the raw SMTP reply |
Remote-MTA | The server the reporting MTA was talking to when the condition occurred |
A single DSN can carry more than one per-recipient block, one per address that matched a requested NOTIFY condition.
Worked example
A message sent to a nonexistent mailbox produces a 550 5.1.1 failure. The MTA that rejected the message during the SMTP conversation isn't the one that writes the DSN. The DSN comes back from the server that accepted the message and then failed to relay it onward, addressed to the original envelope sender as a multipart/report:
Content-Type: multipart/report; report-type=delivery-status; boundary="dsn-boundary"--dsn-boundaryContent-Type: text/plain; charset=us-asciiThis is an automatically generated Delivery Status Notification.Delivery to the following recipient failed permanently:recipient@example.net--dsn-boundaryContent-Type: message/delivery-statusReporting-MTA: dns; mx.example.comArrival-Date: Tue, 11 Aug 2026 09:12:03 +0000Final-Recipient: rfc822; recipient@example.netAction: failedStatus: 5.1.1Diagnostic-Code: smtp; 550 5.1.1 No such user--dsn-boundary--
The human-readable part exists for a person reading the bounce in a mail client. The message/delivery-status part exists for a program: Action: failed and Status: 5.1.1 are enough on their own to classify the failure as permanent and act on it without parsing any wording at all.
Limits of DSN
Generating a DSN is optional. Nothing in the SMTP extension requires an MTA to honor a NOTIFY request, and plenty of servers never send one, regardless of what the sender asked for.
Some providers go further and deliberately suppress DSNs to a sender that wasn't authenticated on the original message. That's a defense against backscatter: if an attacker forges your address as the sender of spam, every recipient MTA that generates a DSN sends its bounce to you, the forged party, not the attacker. Suppressing DSNs to an unverified sender limits how much of that traffic lands on an address that never sent the original message.
A DSN also only reports what happened at the transport layer. It says nothing about whether the message landed in a spam folder, and nothing about a later content-based rejection that happens after the SMTP transaction already completed successfully.
Check it yourself
Send a message to an address you know doesn't exist, at a domain that's known to return full bounces rather than silently drop the failure. Wait for the DSN, then open its raw source instead of the rendered summary your mail client shows.
Look for the multipart/report structure, then find the message/delivery-status part inside it. The Action, Status, and Diagnostic-Code fields tell you exactly what the receiving side classified the failure as, independent of whatever text the human-readable part used to describe it.
Where DSN fits
NOTIFY and RET are SMTP extensions, defined on top of the base protocol covered in the SMTP guide. DSN reports a delivery outcome; it's a different notification type from MDN, which reports what a recipient did with a message after it arrived, not whether it arrived. DSN also shares its multipart/report container with ARF, which reports abuse complaints rather than delivery failures. For the wider set of standards this cluster covers, see the reference hub.
Nuntly surfaces this as bounce events and a bounce-rate metric; see the sending observability guide and the sending webhooks reference.
FAQ
Is a DSN guaranteed when a message fails?
No. DSN generation is optional for an MTA, and some providers deliberately suppress DSNs to unauthenticated senders to avoid backscatter. A failure can happen with no DSN ever arriving.
What does Action: relayed mean?
The message was handed off successfully to another MTA that doesn't support DSN. The reporting MTA can't confirm final delivery from that point, only that it passed the message along.
Do enhanced status codes replace SMTP reply codes?
No, they complement them. The three-digit SMTP reply code, like 550, is the wire-level response. The enhanced code, 5.1.1, is a more specific, protocol-independent classification carried inside the DSN body.
Does a DSN mean my message was read?
No. A DSN reports the transport-layer delivery outcome only. Confirming a human actually saw the message is what MDN, a separate standard, is for.
RFC reference
RFCs covered: RFC 3461, RFC 3462, RFC 3463, RFC 3464. Superseded / updated by: RFC 3464 obsoletes RFC 1894. RFC 3463 obsoletes RFC 1893. RFC 3461 and RFC 3462 have no successor.