Builds delivery status notifications (RFC 3464), the messages that tell a sender their mail was not delivered (or not yet).
A notification is a multipart/report (RFC 6522) with three parts: a
human-readable explanation, a message/delivery-status report for
programs, and the headers of the original message
(text/rfc822-headers; the body is not returned).
DSN.build(%{
kind: :failure,
reporting_mta: "mx.example.com",
from: "MAILER-DAEMON@mx.example.com",
to: "alice@example.com",
recipients: [
%{recipient: "bob@example.net", status: "5.1.1", remote_mta: "mx.example.net",
diagnostic: "550 5.1.1 User unknown"}
],
headers: "From: alice@example.com\r\nSubject: hi\r\n\r\n"
})The result is a complete message with CRLF line endings. Send it with
the null reverse-path (MAIL FROM:<>), as RFC 5321 §6.1 requires, so a
failing notification never causes another one.
Text from remote servers (diagnostics) is untrusted: control and
non-ASCII characters are replaced with ?, and long values are cut,
so it cannot inject header fields or MIME boundaries.
Summary
Functions
Builds the notification message. Returns the message and its body type:
:"8bitmime" if the original headers contain 8-bit bytes, otherwise
:"7bit".
Types
@type recipient() :: %{ :recipient => String.t(), :status => String.t(), optional(:remote_mta) => String.t() | nil, optional(:diagnostic) => String.t() | nil, optional(:reason) => String.t() | nil, optional(:last_attempt) => DateTime.t() | nil }
One recipient in the report.
:recipient- the address. Required.:status- enhanced status code, such as"5.1.1". Required.:remote_mta- host name of the server that gave:diagnostic.:diagnostic- the remote server's SMTP reply.:reason- a local explanation, used when there is no SMTP reply (for example "Host or domain name not found").:last_attempt- time of the last delivery attempt.
@type report() :: %{ :kind => :failure | :delay, :reporting_mta => String.t(), :from => String.t(), :to => String.t(), :recipients => [recipient(), ...], optional(:headers) => binary() | nil, optional(:queue_id) => String.t() | nil, optional(:arrival_date) => DateTime.t() | nil, optional(:will_retry_until) => DateTime.t() | nil, optional(:date) => DateTime.t(), optional(:message_id) => String.t(), optional(:boundary) => String.t() }
The report.
:kind-:failure(the listed recipients will never get the message) or:delay(still trying). Required.:reporting_mta- this server's host name. Required.:from- address in theFrom:field, usuallyMAILER-DAEMON@<host>. Required.:to- the original sender. Required.:recipients- at least one. Required.:headers- the original message's header section.:queue_id- the original message's queue ID.:arrival_date- when the original message was received.:will_retry_until- for:delay, when delivery will be given up.:date,:message_id,:boundary- default to now, a new ID, and a random boundary.