Skip to content
Webmaster Tools
EmailEmail DeliverabilityBody hash did not verify

DKIM body hash did not verify

What the DKIM error body hash did not verify means, why the message body changed after it was signed, and how to find and fix the server or list that modified it.

What it means

A DKIM signature contains a hash of the message body in its bh= tag. When a receiver hashes the body it received and gets a different value, the signature can't verify: body hash did not verify. It means the body was changed somewhere between signing and delivery. The DNS key and the selector are fine; the signature was found and checked, the content just isn't the same any more.

Gmail reports it like this:

Authentication-Results: mx.google.com;
       dkim=neutral (body hash did not verify) header.i=@example.com header.s=s1 header.b=AbCdEf12;
       spf=pass smtp.mailfrom=example.com;
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com

Other receivers use dkim=fail with similar wording. DKIM is defined in RFC 6376.

Common causes

  • Mailing lists that add a footer ("You received this because…") or an unsubscribe link to the body.
  • Outbound gateways that append disclaimers, legal notices or tracking links after the message was signed.
  • Security appliances that rewrite URLs for click protection, strip attachments or add banners such as "External sender".
  • Encoding changes: a relay that converts 8-bit content to quoted-printable or base64, or rewraps long lines.
  • Line endings or trailing whitespace changed by a server or by code that builds the message, combined with simple body canonicalization, which tolerates almost no change.
  • Signing too early: your own mail server signs, then a later step (antivirus, footer, list software) modifies the message.

How to find the cause

  1. Compare paths. Send the same test message directly to a Gmail or Outlook address and through the suspect route. If only one route fails, the extra hop is modifying the body.
  2. Read the Received headers in the failing copy, from bottom to top, to see every server it passed through. The Email Header Analyzer lists the hops in order.
  3. Look for visible changes: footers, banners, rewritten links.
  4. Check the canonicalization in the signature, the c= tag.
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=s1;
        h=from:to:subject:date:message-id; bh=...; b=...

How to fix it

  • Sign last. On your own server, DKIM signing should be the final step before the message leaves, after disclaimers and footers. In Postfix with OpenDKIM as a milter, make sure any content filter that edits messages runs before the milter that signs.
  • Use relaxed canonicalization: c=relaxed/relaxed. It tolerates whitespace and line-wrapping changes. It does not tolerate added text.
  • Move disclaimers into the sending application or template, so they are part of the body before signing.
  • Exclude signed mail from URL rewriting where your security product allows it, or have it re-sign.
  • For mailing lists, you can't fix it from the sending side. Lists that change messages should rewrite the From address and sign with their own domain; many already do.

Avoid the l= (body length) tag as a workaround. It lets the signature cover only part of the body, so anyone can append content to a signed message.

Does it break DMARC?

Only if nothing else aligns. In the sample above, SPF passed for example.com and DMARC still passed. After forwarding, though, SPF fails too, and a broken DKIM signature then means dmarc=fail.

Check your DKIM key and the rest of your setup with the Email Checker, using your own selector.