DKIM Body Hash Did Not Verify: Causes and Fixes

VigilDog Team · September 28, 2026 · 6 min read

You set up DKIM, tested it, and it passed. Then reports start trickling in: some of your mail is failing DKIM with the oddly specific reason 'body hash did not verify.' It's one of the most confusing DKIM errors because the signature itself is valid, the problem is that something changed the message body after you signed it. This guide explains exactly what that means and how to track down the culprit.

What 'body hash did not verify' actually means

Every DKIM signature covers two things: a set of message headers and a hash of the message body. The signer computes a hash of the body, stores it in the bh= tag of the DKIM-Signature header, then signs the whole thing with a private key. When a receiver validates the message, it recomputes the body hash and compares it to bh=. If those two hashes don't match, you get the specific failure 'body hash did not verify.'

This is a narrower problem than a general DKIM failure. A signature can also fail because the public key is missing from DNS, the key was rotated, or a signed header was altered. 'Body hash did not verify' points at one thing only: the bytes of the message body changed between the moment it was signed and the moment it was checked. The cryptography is fine, the content moved.

The usual suspects: what modifies a body in transit

The failure almost always comes from something in the delivery path editing the body after your server signed it. The common offenders:

  • Mailing lists (Mailman, Google Groups) that append an unsubscribe footer or tag the subject line. The footer changes the body and breaks the original signature.
  • Email security gateways and appliances that inject an 'External sender' banner or a legal disclaimer after signing.
  • URL-rewriting features (Proofpoint URL Defense, Mimecast) that replace links in the body for click-time protection.
  • Auto-forwarding rules that reformat or re-encode the message before relaying it.
  • Re-encoding of content transfer encoding, a relay that rewraps quoted-printable text or changes line endings can shift a single byte and invalidate the hash.
Senderyour domainSPFauthorised IP?DKIMsignature valid?AlignmentFrom matches?DMARC policynone / quarantine / rejectInbox
How SPF, DKIM and DMARC verify an email

Canonicalization: relaxed vs simple

DKIM never hashes the raw body directly. It first runs the body through a canonicalization algorithm, declared in the c= tag as header/body, for example c=relaxed/relaxed. The body algorithm you pick decides how forgiving the hash is.

'simple' body canonicalization is strict: any change to whitespace, and any added or removed blank line, changes the hash. 'relaxed' is more tolerant, it collapses runs of whitespace and ignores trailing empty lines, so trivial reformatting by a relay won't necessarily break verification. If your signer uses simple/simple and mail passes through even one relay that touches whitespace, expect intermittent body-hash failures. Switching to relaxed/relaxed removes a whole class of them.

There's also the optional l= tag, which signs only the first N bytes of the body. It was meant to survive appended footers, but it's a security risk, an attacker can append content past the signed length, and many receivers ignore or distrust it. Prefer fixing the signing order over reaching for l=.

How to diagnose it

Start with the receiver's own verdict. Open the raw message and read the Authentication-Results header, a body-hash failure usually shows as dkim=fail with a reason like 'body hash did not verify.' From there, isolate the path:

  • Compare a direct message to one sent through the suspect path. Email yourself directly, then via the mailing list or gateway. If direct passes and the routed copy fails, that path is modifying the body.
  • Check your canonicalization. Look at the c= tag in the DKIM-Signature header. If it's simple/simple, that alone can explain the flakiness.
  • Confirm signing order. In your MTA or ESP, DKIM signing must be the last step, after any footer, disclaimer, or banner is added.
  • Run a suspect message through a validator like our free DMARC and authentication checker to see the parsed result and where it breaks.

How to fix it and keep it fixed

Most body-hash failures come down to signing too early or canonicalizing too strictly. Work through these in order:

  • Use relaxed/relaxed canonicalization unless you have a specific reason not to.
  • Sign last, make sure disclaimers, banners, and footers are added before the signing step, never after.
  • For mailing lists, don't fight it: the list should re-sign outgoing mail with its own DKIM key, and ARC (Authenticated Received Chain) lets downstream receivers trust the original authentication even after the list modifies the message.
  • Audit any security gateway that rewrites URLs or appends banners; some can be configured to re-sign after they modify the body.
  • Drop the l= tag if you added it as a workaround.

Catching regressions before your inbox does

A single fix is easy; the hard part is noticing when it regresses. A gateway update or a newly added mailing list can silently reintroduce failures, and DMARC only tells you after aggregate reports roll in, days later. VigilDog's email deliverability monitoring watches SPF, DKIM, and DMARC continuously and alerts you when authentication starts failing, before a client asks why their mail landed in spam. For the end-to-end setup, see our guide to fixing SPF, DKIM, and DMARC.

Questions

Frequently asked

Is 'body hash did not verify' different from a normal DKIM failure?

Yes. A general DKIM failure can be a missing DNS key, a rotated key, or an altered signed header. 'Body hash did not verify' specifically means the message body changed between signing and verification, the bh= tag no longer matches the recomputed body hash.

Why does my mail fail DKIM only when sent to a mailing list?

Mailing lists commonly append an unsubscribe footer or tag the subject, which modifies the body after your server signed it. The fix is for the list to re-sign with its own DKIM key and use ARC so receivers can still trust the original authentication.

Will switching to relaxed canonicalization fix it?

It fixes failures caused by trivial whitespace or blank-line changes from relays, which is a common cause. It won't fix failures where a footer, banner, or disclaimer is actually added to the body, for those you need to sign last or have the intermediary re-sign.

Turn a broken body hash into an alert, not a complaint

VigilDog keeps a constant eye on your SPF, DKIM, and DMARC so authentication failures reach you before your clients' spam folders do.

Your first domain is free forever