What the body hash is
When signing, the sending server computes a hash over the message body and stores it as the bh= tag inside the DKIM-Signature. The receiver computes the same hash over the body it received. If the values differ, the content changed in transit — and the signature is worthless, regardless of whether the key is correct.
Not to be confused with “no key for signature”: that one fails at DNS, this one at the content.
The usual culprits
- Mailing lists. The classic. The list appends a footer or writes
[List name]into the subject — either reliably destroys the signature. ARC exists for this, attesting the original verdict across the forward. - Gateways and security appliances. Virus scanners, disclaimer appenders and outbound DLP systems rewrite text. When such a device acts after signing, the signature is gone. The order must be reversed: modify first, then sign.
- Line breaks and encoding. A server that rewraps lines or changes the transfer encoding alters the body as far as the hash is concerned — even when it looks identical to a reader.
- The
l=tag. Signs only part of the length, which tolerates appended content but creates problems of its own. Better left unused. - Double signing. When two systems sign in sequence, the first signature can be invalidated by the second one's changes.
Narrowing it down
The decisive question: does the failure occur always, or only on certain paths? If a directly delivered message arrives clean and only the one via the mailing list does not, the list is responsible — your setup is fine. If direct delivery already fails, the culprit sits in your own outbound path.
To find out, send the same message once directly and once via the suspect path to hello@analyzemy.email and compare the two reports: signature status, signed headers and the ARC chain sit side by side there.