What the error literally means

DKIM stores a hash of the canonicalized body in the bh= tag of DKIM-Signature. A receiver applies the declared canonicalization to the body it received, hashes that result, and compares it with bh=. If the values differ, the body seen by the receiver is not the body the signer committed to. That is different from a selector-not-found error, a bad public key, or a DMARC alignment failure. Rotating DNS keys without understanding this distinction can waste time because the failure may occur before the verifier even reaches the part of the signature that depends on the public key.

Draw the message path around the DKIM signer

List every component that touches the message: application, mailbox provider, outbound gateway, security filter, footer service, and final transport. Mark where DKIM signing occurs. Any component after that point that changes body bytes can invalidate the body hash. A footer or banner inserted before signing is included in the signed body and normally does not create this particular mismatch. The same footer inserted after signing does. This simple diagram turns a vague deliverability problem into a sequencing problem you can reproduce.

Check raw headers before touching DNS

Open the raw source of a failed message and locate Authentication-Results plus DKIM-Signature. Note header.d, header.s, c=, and the reported failure. Then query the selector only to confirm the key resolves. If the receiver explicitly says body hash did not verify, a resolving key is consistent with the evidence. Also inspect Received headers to identify hops after the signer. The troubleshooting order should follow the failure semantics instead of a generic checklist that starts by republishing DKIM every time any DKIM result is red.

Test with a body that is hard to modify accidentally

Send a minimal plain-text message with no tracking links, signature block, attachments, or template engine. Route it through the same path. If that message passes but the normal template fails, compare the two paths and body transformations. Then add one feature back at a time: HTML, link rewriting, footer, attachment, or gateway policy. This controlled reduction often finds a modifier faster than staring at DNS. Keep the received raw source for each test because what matters is the exact body bytes that arrived, not what the composer UI displayed.

Understand what relaxed canonicalization can and cannot save

DKIM canonicalization can tolerate some formatting differences, depending on the selected mode, but it does not make arbitrary content changes invisible. Adding a sentence, rewriting a URL, changing MIME structure, or inserting a banner alters meaningful body content. A common mistake is to assume relaxed/relaxed makes DKIM immune to gateways. It only normalizes specific whitespace and formatting patterns defined by the standard. If an intermediary is performing substantive modification, move that transformation before signing or configure the system so the final signer runs after the modification.

Do not confuse body integrity with DMARC alignment

DMARC can use a DKIM signature only if the signature verifies and its d= domain aligns with the visible From domain. A body-hash failure prevents that signature from being a valid DKIM pass in the first place. Alignment is therefore a later question. If SPF is aligned and passes, DMARC may still pass while this broken DKIM signature exists, which can hide the problem until routing changes. Fix the body-hash failure even when aggregate DMARC numbers look acceptable, because redundancy between aligned SPF and DKIM is useful during real-world forwarding and provider changes.

A practical before-and-after test

Suppose a provider signs the message, then a gateway appends “External communication notice” to every outbound body. Direct tests pass, gateway tests fail. Disable only the footer rule for one controlled recipient and send the same message again. If DKIM passes, you have isolated the modifier. The durable fix is usually to apply the footer before the signing stage or to let the downstream gateway sign the final version with an aligned domain. The key is evidence: one variable changed, the receiver result changed, and the raw source shows why.

Keep a signing-boundary note for future infrastructure changes

Once repaired, document which component owns the final DKIM signature and which components are allowed to modify the body before it. This becomes important when someone later enables antivirus banners, link scanning, legal footers, or a different relay. A two-line architecture note can prevent the same failure from returning months later. During future changes, send a raw-header test before scaling traffic. Authentication incidents are much easier to correct at five test messages than after an entire outbound queue has been processed.

Prove the modifier with paired raw-message captures

When the suspected modifier is a gateway footer, collect two received copies of the same minimal message: one that bypasses the footer path and one that traverses it. Save the full raw source rather than forwarding the samples, because forwarding can introduce another transformation. Compare the DKIM-Signature fields first, then the MIME body as delivered. Google’s Workspace troubleshooting guidance explicitly calls out the “body hash did not verify” result when a message is changed in transit and notes outbound gateways that append footers as an example. That makes a paired capture much more persuasive than rotating keys or republishing DNS while the actual mutation remains in place.

The long-term control is to define a finalization boundary. Components before that boundary may rewrite links, add footers, normalize MIME, or apply policy banners; the component at the boundary signs the final representation; components after it should relay without substantive body changes. If a downstream security service must modify content, either configure the upstream signer accordingly or arrange an aligned signature after modification. Add a regression test to infrastructure changes: send one plain-text and one representative HTML message through the production route, preserve the received source, and confirm that the intended aligned DKIM signature verifies. This catches a signing-order regression before campaign volume turns it into a deliverability incident.

Field checklist

  • Confirm the receiver specifically reports a DKIM body-hash mismatch.
  • Record d=, s= and c= from the failed signature.
  • Map every message modifier before and after the signer.
  • Reproduce with a minimal plain-text test message.
  • Move substantive body changes before the final signing step where possible.
  • Retest DMARC after DKIM verification returns to pass.

Primary sources

Standards and provider policies can change. These links are the reference points used for this field note.

  1. RFC 6376 — DKIM SignaturesIETF / RFC EditorDKIM signing and verification behavior.
  2. Troubleshoot DKIM issuesGoogle Workspace HelpGoogle DKIM troubleshooting, including body-hash failures caused by message modification and outbound gateways that add footers.
  3. RFC 9989 — DMARCIETF / RFC EditorCurrent DMARC base specification, published May 2026.