Fixing "dkim=fail (body hash did not verify)"
dkim=fail (body hash did not verify) header.d=example.com
This one is maddening because the DKIM key is published correctly and the signature parses — yet the verdict is:
Authentication-Results: mx.google.com; dkim=fail (body hash did not verify) header.d=example.com
The b= (signature) may be fine; it is the bh= (body hash) that no longer matches. That means the message body changed between signing and verification — the cryptographic hash the sender computed is not the body the receiver saw.
Why it happens
Something in the path modified the message: a mailing list or forwarder that appends a footer, an antivirus/appliance that rewrites links or adds a "scanned by" banner, a signing order bug where the content is altered after signing, or a relay that re-encodes the body (line-ending or MIME changes). The l= body-length tag can also let trailing content be appended and still fail.
Diagnose it
Confirm the key itself is healthy first (below) — key type, size, and that it is not in test mode. Then send a plain test to a Gmail account, open Show original, and check whether DKIM passes when nothing forwards it. If direct passes but a forwarded copy fails, an intermediary is rewriting the body.
Fix it
1. Sign as late as possible in your outbound path, after every appliance that touches content.
2. Remove the l= tag so partial-body signing can't mask edits.
3. For list/forwarding scenarios, rely on DMARC alignment via SPF, or adopt ARC so intermediaries can vouch for the original result.
4. If an on-prem appliance adds a disclaimer, move disclaimer insertion before the DKIM signer.
Diagnose your own domain in seconds:
Check your DKIM key nowStill stuck? Paste the whole bounce and we'll pinpoint the exact failure and fix.
Diagnose my bounce