Skip to main content
Microsoft 365intermediate

DKIM Fail: Body Hash Did Not Verify - How to Fix

Fix the DKIM "body hash did not verify" failure. The message body changed after signing - find the transport rule, disclaimer, gateway or mailing list responsible.

8 min readUpdated August 2026

DKIM failing with "body hash did not verify"? The message body was altered somewhere between the server that signed it and the server that checked it. Your DKIM key, selector and DNS record are almost certainly correct — this is not a key problem.

The Error

In an Authentication-Results header:

Authentication-Results: mx.google.com;
       dkim=fail (body hash did not verify) header.i=@example.com
       header.s=selector1 header.b=Xk2mQp8v;
       spf=pass (google.com: domain of bounce@example.com designates
       203.0.113.10 as permitted sender) smtp.mailfrom=bounce@example.com

Or from other verifiers:

dkim=fail reason="signature verification failed" (body hash mismatch)
dkim=permerror (bad message/signature format)

The critical detail is the parenthetical: body hash did not verify. A different message — no key for signature, or signature did not verify — is a different fault with a different fix.


Why This Happens

RFC 6376 defines the bh= tag of the DKIM-Signature header as:

The hash of the canonicalized body part of the message as limited by the "l=" tag (base64; REQUIRED).

The signing server computes that hash over the body at the moment of signing. The receiving server recomputes it over the body it received. If the two differ by even one byte, verification fails. DKIM is working exactly as designed: it is telling you the message is not byte-identical to what was signed.

So the question is never "why is DKIM broken" — it is "what modified my message?" In rough order of frequency:

  1. A disclaimer or signature block appended after signing — most often an Exchange Online mail flow rule
  2. A security gateway rewriting URLs for click-time protection, or adding an external-sender banner
  3. A mailing list appending a footer or altering the subject
  4. Forwarding that re-encodes the body — changing quoted-printable to base64, or altering line endings
  5. An MTA rewriting line endings between CRLF and LF, or wrapping long lines
  6. Antivirus or DLP products injecting a scan-result notice

Fix 1: Identify Where the Change Happens

Get the full headers of a failing message and read the Received: headers from the bottom up — the bottom is the oldest hop. Locate the hop that applied the DKIM-Signature, then examine every hop after it.

Paste the whole header block into our email header analyzer to get the hops and authentication results laid out in order rather than reading them by eye.

Then run a controlled comparison:

  • Send a plain-text message with no signature block, no links and no attachments to an external mailbox you control. If that passes DKIM, the transport is clean and something about the content is triggering a modification.
  • Send the same message to a second external mailbox on a different provider. Passing at one and failing at the other localises the fault to the receiving side — typically a gateway in front of that recipient.
  • Send to an address on a mailing list. Failing only there confirms the list is modifying messages.

Fix 2: Find the Disclaimer Rule (Microsoft 365)

This is the leading cause inside Exchange Online tenants. Check for mail flow rules that append content:

Connect-ExchangeOnline

Get-TransportRule | Where-Object { $_.ApplyHtmlDisclaimerText -ne $null } |
    Format-List Name, ApplyHtmlDisclaimerLocation, ApplyHtmlDisclaimerText

Any rule with ApplyHtmlDisclaimerLocation set to Append is adding content to the body. Whether that breaks DKIM depends on the order of operations in your specific mail flow, but if a rule modifies the body after signing, the body hash cannot survive.

Options, best first:

  • Remove the disclaimer if it exists only for legacy legal habit. Many do.
  • Apply it only to external recipients so internal mail is unaffected, reducing the blast radius while you work out the ordering.
  • Move the disclaimer upstream so it is applied before signing rather than after.
  • Add it at the client via an Outlook signature, which becomes part of the message the user composes and is therefore present before signing.

Advertisement

If mail leaves your tenant through a third-party security gateway, or arrives at the recipient through one, that appliance may be modifying the body. Look for:

  • URL rewriting for click-time protection, which changes every link in the body
  • External sender banners injected into the body rather than added as a header
  • Attachment stripping or sandboxing notices appended to the message
  • Plain-text alternative regeneration in multipart messages

If the gateway sits between your signer and the internet, the correct configuration is for the gateway to sign after it finishes modifying — that is, it becomes the signer for your domain. Two systems both trying to sign the same mail is a reliable way to produce this failure.

If the gateway is on the recipient's side, you cannot fix it and you do not need to. Their receiving infrastructure broke the signature; your mail was correct when it left you. Confirm this by checking that the message passes at other providers.


Fix 4: Handle Mailing Lists Properly

Discussion lists routinely add a footer, prepend [list-name] to the subject, or strip attachments. All of these break DKIM, and there is no configuration on your side that prevents it.

The correct handling is on the list:

  • The list strips the original DKIM signature and re-signs as the list's own domain, taking responsibility for the modified message.
  • Or the list implements ARC (Authenticated Received Chain), which records the authentication results as they were before modification so downstream receivers can choose to trust the chain.

If you run the list, enable one of those. If you merely post to it, expect DKIM failures on list-delivered copies and make sure your DMARC policy accounts for it — this is one of the standard reasons to move to p=reject carefully rather than immediately.


What Not To Do

Do not reach for the l= tag. It limits the signature to the first N octets of the body, so appended footers no longer break the hash. RFC 6376 defines it, but the security cost is severe: everything beyond the signed length is unsigned, so an attacker who intercepts the message can append arbitrary content — new instructions, different payment details, a phishing link — and the message still passes DKIM. You would be trading a visible failure for an invisible vulnerability.

Do not disable DKIM signing to make the failure disappear. That removes the signal that survives forwarding, and DKIM is the authentication method DMARC depends on when SPF breaks.

Do not weaken DMARC to p=none as a permanent answer. It stops the symptom for spoofers as well as for you.


Verify the Fix

After removing or relocating the modification, send a fresh test to an external mailbox and read the results. In Gmail use Show original; in Outlook on the web use View message details. You want:

DKIM: 'PASS' with domain example.com

Check the DNS side is healthy too, so you can rule it out entirely:

# Microsoft 365 selectors
dig +short CNAME selector1._domainkey.example.com
dig +short CNAME selector2._domainkey.example.com

# Resolve the published key the selector points to
dig +short TXT selector1._domainkey.example.com

The selector name in DNS must match the s= tag in the DKIM-Signature header of the failing message. If it does, the key is not your problem and the body hash diagnosis stands.

Test from every sending path — mail client, application, marketing platform — because a transport rule may apply to only some of them.


Prevention

  • Review mail flow rules whenever DKIM starts failing; a newly added disclaimer is the usual culprit and the change is often made by someone who did not connect it to email authentication.
  • Keep exactly one system responsible for signing a given domain. Layered products each trying to sign is a recurring source of this failure.
  • Publish DMARC with rua= aggregate reporting and read it monthly. The reports show DKIM pass rates per source, so a body-hash problem appears as a trend long before anyone reports a bounce. Build the record with our DMARC generator.
  • When adding a security gateway, confirm during the pilot whether it modifies bodies, and settle the signing order before cutover rather than after.
  • Expect list mail to fail DKIM and account for it before tightening DMARC to reject.

Summary

  1. Read the parenthetical — "body hash did not verify" means the body changed, not that the key is wrong
  2. Trace the Received headers to find every hop after the signature was applied
  3. Check Exchange Online mail flow rules for appended disclaimers first
  4. Check gateways for URL rewriting and injected banners; ensure only one system signs
  5. Expect mailing lists to break it — the fix is re-signing or ARC on the list
  6. Never use l= to paper over it; it makes appended content unsigned and forgeable

Frequently Asked Questions

Find answers to common questions

The signing server hashed the message body and stored that hash in the bh= tag of the DKIM-Signature header. The receiving server hashed the body it actually received and got a different value. Something altered the body in transit, so the signature cannot validate. The key and the DNS record are fine.

"Body hash did not verify" means the message body changed. "Signature did not verify" means the cryptographic check over the signed header fields failed, which usually points to a modified header, a key mismatch or a rotated key. They are different faults with different fixes.

Because the modification happens on the path to those recipients. A mailing list that appends a footer, a recipient-side gateway that rewrites links, or a forwarding hop that re-encodes the body will break the body hash for that route only. Direct delivery to other recipients still passes.

Yes, if they are appended after signing. An Exchange Online mail flow rule that adds a disclaimer modifies the body, which invalidates the body hash. This is one of the most common causes in Microsoft 365 tenants.

Frequently. Lists that add a subject tag, a footer or an unsubscribe block change the message and break the signature. Well-configured lists strip the original signature and re-sign as the list domain, or use ARC so downstream receivers can see the original result.

Yes. Any product that rewrites URLs for click protection, appends a scanning banner, or adds an external-sender warning to the body is modifying the message after signing and will invalidate the body hash.

It limits signing to the first N octets of the body so later additions do not break the hash, but it is a bad trade. Anything appended beyond that point is unsigned, so an attacker can add arbitrary content to a message that still passes DKIM. RFC 6376 warns about this. Fix the modification instead.

Only for whitespace changes. Relaxed body canonicalization ignores trailing whitespace on lines and collapses repeated whitespace, so it survives cosmetic reformatting. It does not survive appended text, rewritten links or re-encoded content.

It depends on DMARC. If SPF passes and is aligned, the message can still pass DMARC overall. If SPF also fails or is unaligned and your policy is quarantine or reject, the message is junked or bounced.

Compare the Received headers to find every hop between signing and the failure, then look for a hop that adds a disclaimer, banner or rewritten link. In Microsoft 365, check Exchange Online mail flow rules first, then any security gateway in front of or behind the tenant.