Global
The value is a path to a file, not the text itself: a failure report body is too big for a configuration line.
Nine values of the original message are substituted in the template:
| Substitution | What it gives |
|---|---|
| hostname | the name of the node that generated the report |
| originator | the sender of the original message |
| recipient | the recipient it did not reach |
| subject | the subject of the original message |
| date | the date the report was generated |
| timeQueued | when the message entered the queue |
| retryAfter | the retry interval |
| bounceAfter | the deadline after which the message is bounced |
| response | the receiver’s reply — what the report is read for |
The same set is used by the neighboring lines — the subject template dsn-failed-subject-template and the sender header template dsn-failed-from-template.
Of the nine values one matters more than the others: the receiver’s reply. It is what tells a person what happened — the rest is framing.
The second half is smaller but of the same kind: in the example the file is named /usr/joe/dsn-body-template.txt, while the heading of the next block declares the contents of the file /usr/admin/dsn-body-template.txt. The paths differ, and this is a vendor typo.
The practical conclusion is one: check the template with a message, not by reading. A wrong substitution will not cause an error — it will simply stay in the text as is.
Everything a report contains arrives to us as accounting records via the webhook: the receiver’s reply, the time of queuing, and the addresses. There is no reason to package this data as a message.
What to set. A path to a file; the rules follow from the purpose:
| Property | Why |
|---|---|
| a file next to the configuration | it is read by the node process, and the same permissions are needed |
| the receiver’s reply in the text is mandatory | without it the report explains nothing |
| no internal names and addresses | the report goes outside, to the message sender |
The file itself is read when the report is generated, not when the configuration is loaded — so an edit takes effect without a reload.
# three lines define the whole report: the header, the subject and the body from a file dsn-failed-from-template "${hostname} <postmaster@abc.com>" dsn-failed-subject-template "Email failed, Re: ${subject}" dsn-failed-body-template-from /etc/pmta/dsn-body-template.txt
what people get wrong and how it ends2 mistakes▶
§ 3.3.1.31
our experience
1 relation
dsn-failed-from-templateGlobalThe set of substitutions common to all three report templates is listed there. § 3.3.1.29dsn-failed-subject-templateGlobalThe set of substitutions common to all three report templates is listed there. § 3.3.1.30suppress-local-dsn<source>Suppression cancels all report appearance settings at once: there will simply be no message to format. § 3.3.7.30
grep -n 'dsn-failed\|custom-dsn-from-header\|suppress-local-dsn' /etc/pmta/config ls -l /etc/pmta/dsn-body-template.txt
3 articles
◇Who is allowed to submit mail and for whom to accept itOut of the box, the node accepts submission only from the machine itself; two different questions — “who can send through us” and “for whose addresses we accept mail” — are answered by different directives.◇Two inbound report processors and what to do with themBounces by message and complaints are parsed by two identically structured blocks; each has its own address list and its own pair of decisions about the message’s fate.◇Address lists — named and unnamedA list of addresses, domains, patterns or hashes; a named one is attached by directives such as suppression, an unnamed one lives inside an inbound mail processor.