Knowledge base

PMTA knowledge base›Block <domain>›Directive§ 3.3.10.23

dkim-headers-canon

<domain>

How tolerant the signature is of edits to headers in transit
in the configuration this is a linedkim-headers-canon relaxedinside the block <domain>
What counts as a change to a header

Between your node and the mailbox, a message passes through other people’s servers, and they reformat headers: wrap long lines, collapse spaces, change the case of names. The content does not change, but the bytes do — and the signature over them breaks.

Canonicalization decides what counts as a change. The default relaxed brings headers to a common form before signing and before verification: the name in lower case, spaces collapsed into one, the line wrap removed. simple forgives nothing: any byte out of place — and the signature does not match.

The pair to this line is dkim-body-canon: the same fork for the message body. In the signature they stand side by side, in the c= field, separated by a slash.

The main trap is simple for headers on the open internet. Headers are reformatted not by attackers but by ordinary mail nodes along the way; with simple the signature breaks for the share of recipients whose mail goes through an intermediary — and that share is unpredictable.
What the Hub does. It does not write it — the vendor relaxed stays, and it is the right value. simple makes sense where the message’s path is controlled end to end; in bulk mail there is no such thing.
Recommended values

Leave relaxed. It is the default both here and in the vast majority of other people’s configurations.

simple — only for a controlled path. For example, between two of your own nodes, where there are no intermediaries.

Different values for body and headers are allowed. Usually relaxed is taken for both, but the pair relaxed/simple does occur — it is visible directly in the signature, in the c= field.

The advice to keep the tolerant method is ours. From the manual here: both values and the default.
Example configuration
# the default is left deliberately: the message's path is beyond our control
<domain *>
    dkim-headers-canon relaxed    dkim-body-canon relaxed
</domain>
Together the two lines give what looks like c=relaxed/relaxed in the signature — the variant most tolerant of edits in transit.
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▶

Setting simple for the sake of strictness

our experience

What it costsStrictness here does not protect but breaks: headers are reformatted by ordinary mail nodes along the way. The signature stops matching for an unpredictable share of recipients.
How to spot itVerification failures at some recipients with a correct key and a correct header set.
How to do it rightReturn to relaxed.

Changing canonicalization while investigating verification failures

our experience

What it costsThe cause is almost never there: more often the key, the header set or the body length limit is to blame. Editing canonicalization changes the signature without removing the cause, and it muddles the investigation.
How to spot itThe value was changed, the failure rate is the same.
How to do it rightLook at the d=, s= and h= fields in the signature — they show which key was used and what was signed.
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
dkim-headers-canon <enumeration>
Values
simple or relaxed
Default
relaxed § 3.3.10.23
Applying
reload, no restart needed
Queue
will not touch what is already queued
Where to write it
<domain>
How many times
once in the block
Everything here comes from the manual, with the section.
Inheritance
The value is merged across <domain> blocks from general to specific: the best-matching block wins, not the last one in the file. It is picked up by pmta reload; for queued messages it applies from the next attempt.
How to check on the node
The effective value is printed by the queue settings command; what actually came out is visible in the signature’s c= field:
pmta show settings gmail.com/vmta1 | grep -i canon
grep -i 'DKIM-Signature' /var/log/pmta/pmta.log | tail -3
In the c= field the first value is the method for headers, the second for the body. The Hub does not write this line — the vendor value stays.
In the Hub
Cost of a mistake
reversible: harms only while it is set
Scenarios
Message signing and authentication