Delivery status notifications
When a message cannot reach a recipient, the sender needs to know, because otherwise the message is silently lost. A delivery status notification (DSN, RFC 3464) is the message that carries this news. A mail server sends it to the envelope sender of a message to report what happened to the message. It can report three outcomes: that the message could not be delivered to a recipient, that its delivery is delayed and still being retried, or, when the sender asked for it, that it was delivered. Users know these notifications as bounces.
Stalwart sends DSNs for the messages in its queue. This page describes when it sends them, how senders control them, who they come from and how to suppress them. It also covers the other direction: how Stalwart uses DKIM2 to check the DSNs it receives.
Notification types
Section titled “Notification types”Stalwart checks after each delivery attempt whether the sender should learn about any recipient. It then sends one DSN per message, which reports every recipient whose status the sender should learn. A recipient is reported in one of three kinds of notification:
| Notification | Reported when |
|---|---|
| Failure | The recipient failed permanently, because the receiving server refused it or the message expired in the queue. |
| Delay | The recipient is still being retried and a delay notification is due according to the recipient’s schedule. |
| Success | The recipient was delivered, and the sender requested a success notification. |
Each recipient is reported once for each kind. The subject of the DSN reflects its content, for example Failed to deliver message, Warning: Delay in message delivery, Successfully delivered message or Partially delivered message.
The DSN itself is a multipart/report message (RFC 6522), a format that combines a part for people with parts for software. It contains the following:
- A readable explanation.
- A machine-readable delivery status for each recipient.
- The headers of the original message, up to 4 KiB, whatever the
RETparameter requests.
The DSN carries Auto-Submitted: auto-generated, and the remote server’s reply for each failed recipient.
No DSN is sent for a message whose envelope sender is empty (<>). DSNs themselves are sent with that empty sender, so this rule ensures that two servers never exchange bounces about bounces.
DSN parameters
Section titled “DSN parameters”Senders differ in which notifications they want for a message. The SMTP DSN extension (RFC 3461) lets the sender of a message control its notifications with parameters on the SMTP commands. These parameters are available only when the extension is offered to the client, which by default is to authenticated sessions only (EHLO stage):
| Parameter | Command | Effect |
|---|---|---|
NOTIFY | RCPT TO | Which notifications to send for the recipient: NEVER, or any of SUCCESS, FAILURE and DELAY. Without the parameter, failure and delay notifications are sent. |
ORCPT | RCPT TO | The original address of the recipient, reported in the Original-Recipient field. |
ENVID | MAIL FROM | An identifier of the message chosen by the sender, reported in the Original-Envelope-Id field. |
RET | MAIL FROM | FULL or HDRS. Stalwart returns only the headers in its own DSNs, and passes the parameter on to the next server. |
The parameters do not stop at Stalwart. When the next server also supports the DSN extension, Stalwart passes the parameters on to it, so that the final server can report to the original sender.
Sender settings
Section titled “Sender settings”A DSN is a message like any other, so it needs a sender and, to be trusted by receivers, a DKIM signature. These are set on the DsnReportSettings singleton (found in the WebUI under Settings › MTA › Reports › DSN). Each field is an expression evaluated with the queue sender variables, so the values can depend on the message being reported:
fromNameandfromAddressset the display name and the address of the DSN’s sender.dkimSignDomainsets the domain whose DKIM keys sign the DSN.
The default sender address and signing domain are built from system('report_domain'). This expression returns the report domain shared by all reports, or the default domain unless the report domain is set.
The Reporting-MTA field of each DSN, which names the server that produced it, is the outboundReportSubmitter of the server. The following object body sends DSNs from a postmaster address of the organisation’s domain:
{ "fromName": {"else": "'Mail Delivery System'"}, "dkimSignDomain": {"else": "'example.org'"}}Suppressing notifications
Section titled “Suppressing notifications”Some recipients should never cause a notification, whatever the sender requested. A system Sieve script at the RCPT TO stage can override the NOTIFY parameter of a recipient by setting envelope.notify. The following script suppresses notifications for messages sent to any mailer-daemon address:
require ["variables", "envelope"];
if envelope :matches "to" "mailer-daemon@*" { set "envelope.notify" "NEVER";}The script takes effect once it is selected with the script field of MtaStageRcpt.
Incoming notifications and DKIM2
Section titled “Incoming notifications and DKIM2”Forged DSNs are a common way to deliver unwanted mail. A server cannot tell from a DSN alone whether it really sent the message being reported, so a spammer can disguise a message as a bounce of mail the recipient never sent. DKIM2 closes this gap, because a DKIM2-signed DSN returns the signed original, and the original sender can check its own signature on it.
Stalwart applies this check when three conditions hold:
- A DSN signed with DKIM2 arrives.
dkimVerifyis enabled, as it is with its default ofrelaxed.- The message that the DSN returns is also signed with DKIM2.
Stalwart then verifies that both chains of signatures are valid and that the DSN reports a message this server sent. A DSN that fails these checks is refused with 550 5.7.1 DSN rejected due to DKIM2 verification failure.
A check can also fail to complete because a public key lookup failed temporarily. The outcome then depends on the mode of dkimVerify. When it is strict, the DSN is refused with 451 4.7.5 Unable to verify DKIM2 DSN, try again later. In relaxed mode, the DSN is accepted, and the result is logged as smtp.dkim2-fail.
Each refusal is logged as smtp.dkim2-dsn-rejected, with the reason in its details. The exact conditions are listed in DKIM2.
The DSNs that Stalwart sends are new messages, so they carry no DKIM2 chain of their own, and their DKIM2 signature starts a chain at i=1. They are signed with DKIM2 only when their From header field is Authentic for the signing domain. Otherwise they are sent without DKIM2 header fields (Reports and notifications).