Knowledge base

PMTA knowledge base›Block Global›Directive§ 3.3.1.31

dsn-failed-body-template-from

Global

The file the failure report body is taken from
in the configuration this is a linedsn-failed-body-template-frominside the block Global
The report body is taken from a file, not a string

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 main trap is that the manual writes the substitution name in two ways. The value list in § 3.3.1.31 has hostname, the neighboring line’s example has ${hostname}, and the body sample from the same section has ${hostName}, with a capital letter. Two spellings out of three are lowercase; which one the engine understands can only be checked by experiment.

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.

What the Hub does. It does not write it — and the line cannot show up: suppress-local-dsn true, in effect in all submission sources, turns off report generation entirely.

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.

Recommended values

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.

The list of nine substitutions, the syntax and the example come from the manual, § 3.3.1.31. The discrepancy in spelling the substitution name and in the example file path is our finding. The content requirements are ours.
Example configuration
# 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
The first two lines carry the text directly, the third a path to a file. The set of substitutions is common to all three.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends2 mistakes▶

Relying on the substitution spelling from the manual's text

§ 3.3.1.31

What it costsThe same value is named in two ways in the section. A wrong spelling causes no error: the substitution stays in the report body as is, and the recipient sees curly braces instead of the node name.
How to spot itThe substitution names themselves are visible in the received report.
How to do it rightCheck with a message to a non-existent address and keep the spelling that worked.

Putting internal details into the template

our experience

What it costsThe report goes outside — to the sender of the original message, who may be anyone. Internal node names and service addresses travel along with it.
How to spot itThe template contains machine names and service addresses.
How to do it rightKeep in the body only what explains the failure: the receiver’s reply, the recipient and the time.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Reference data
Syntax
dsn-failed-body-template-from <path>
Values
a path to the template file
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
Global
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The directive is written at the root of the configuration file and applies to the whole node: there is no block for it and no inheritance either. Different reports for different senders or recipients cannot be set — there is one template.
How to check on the node
The line is visible in the configuration, but it has to be checked with a message:
grep -n 'dsn-failed\|custom-dsn-from-header\|suppress-local-dsn' /etc/pmta/config
ls -l /etc/pmta/dsn-body-template.txt
If report suppression is on, the template will not show up at all. If it is off — send a message to a known non-existent address and look at what arrives: a wrong substitution will stay in the text as is, without any error.
In the Hub
Cost of a mistake
safe: a wrong value breaks nothing
Scenarios
Receiving inbound mail