DKIM "Body Hash Did Not Verify": Causes and Fixes

Your DKIM signature is failing with body hash verification errors. Understand why email body modification breaks DKIM and how to fix it.

7 min readerrorsThomas Johnson

What This Error Means

A DKIM "body hash did not verify" error means something modified the email body after the sending server signed it. When DKIM signs a message, it computes a cryptographic hash of the body and stores it in the bh= tag of the DKIM-Signature header. The receiving server independently hashes the body and compares results. If the hashes differ, verification fails.

This error appears in the Authentication-Results header as:

dkim=fail (body hash did not verify) header.d=example.com

The fix: identify which system in your mail pipeline modifies message bodies after DKIM signing, then either move signing to the last hop or stop the modification.

Why It Matters

A DKIM body hash failure means DKIM authentication fails entirely for that message. The consequences depend on your overall authentication posture:

Configuration Impact
DMARC p=none Message likely delivered, but DMARC reports show failures
DMARC p=quarantine Message routed to spam (if SPF also fails alignment)
DMARC p=reject Message rejected outright (if SPF also fails alignment)
No DMARC Message may still deliver, but reputation degrades over time

Even without DMARC, persistent DKIM failures erode your domain's sending reputation. Receiving servers track authentication results over time, and a domain that consistently fails DKIM sees lower deliverability across all recipients.

Common Causes

1. Mailing Lists Adding Footers

Mailing list software (Mailman, LISTSERV, Google Groups, Sympa) appends subscription management footers, unsubscribe links, or list-specific headers to messages. Any addition to the body after signing invalidates the hash.

This is one of the most widespread causes of body hash failure because mailing lists are structurally designed to modify messages in transit.

2. Email Security Gateways Rewriting URLs

Security-focused email gateways (Proofpoint, Mimecast, Barracuda, MailRoute, Microsoft Defender for Office 365) may rewrite URLs in the email body to route clicks through their scanning infrastructure. A link like https://yoursite.com/page becomes https://urldefense.proofpoint.com/v2/url?u=.... This changes the body and breaks the hash.

3. Anti-Spam Systems Modifying Content

Gateway appliances that strip or modify HTML content, remove attachments, add spam score headers that change MIME boundaries, or convert HTML emails to plain text will invalidate the body hash.

4. Forwarding Services Appending Disclaimers

Corporate email systems, university forwarding, and compliance tools append legal disclaimers, confidentiality notices, or branding footers to outbound or forwarded messages. If this happens after DKIM signing, the hash breaks.

5. HTML Rewriting by Intermediate Servers

Some intermediate mail transfer agents (MTAs) rewrite HTML for compatibility, compress images, or normalize character encoding. Even seemingly minor changes — converting line endings from \r\n to \n or stripping trailing whitespace — invalidate the hash if the signing used "simple" body canonicalization (RFC 6376 Section 3.4.3).

6. Content-Transfer-Encoding Changes

If an intermediate server re-encodes a MIME part (e.g., converting from quoted-printable to base64), the raw body bytes change even though the decoded content is identical. DKIM hashes the raw bytes, not the decoded content.

How to Diagnose the Problem

Step 1: Analyze the Headers

Paste the full email headers into the mxio Header Analyzer. Look for two things:

The DKIM-Signature header:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com;
    s=selector1; bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
    h=From:To:Subject:Date:MIME-Version:Content-Type;
    b=...

Note the c= tag (canonicalization) and the bh= tag (the body hash the signer computed).

The Authentication-Results header:

Authentication-Results: mx.google.com;
    dkim=fail (body hash did not verify) header.d=example.com header.s=selector1

If the failure says "body hash did not verify" rather than "signature verification failed," the body was modified. The public key and signature math are not the issue.

Step 2: Check the Received Headers

Walk through the Received: headers (bottom to top) to trace the message path. Identify every server that handled the message between the signing server and the receiving server. Any of these could have modified the body.

Step 3: Verify the DKIM Key

Run the mxio DKIM Checker with your domain and selector to confirm the public key is correctly published. A wrong key produces a different error ("signature verification failed"), but ruling it out narrows the diagnosis.

Step 4: Send a Test Message Directly

Send a test email directly from your mail server to a Gmail or Yahoo address, bypassing any gateways, mailing lists, or forwarding. If DKIM passes on the direct message but fails on messages routed through intermediaries, an intermediate system is modifying the body.

How to Fix It

Fix 1: Sign After All Modifications

The most reliable solution: ensure DKIM signing occurs after all content modifications. If your email flows through a security gateway or compliance system that adds disclaimers, move DKIM signing to the last hop before the message leaves your infrastructure.

Correct architecture:

Compose → Disclaimer Engine → Security Gateway → DKIM Signing → Internet

If DKIM signing happens before the gateway, rearrange the pipeline so signing is last.

Fix 2: Use Relaxed Body Canonicalization

The c= tag in the DKIM signature controls canonicalization — how the body is normalized before hashing. The format is c=header/body, where each can be simple or relaxed.

  • simple — Body hashed as-is, only trailing empty lines ignored
  • relaxed — Trailing whitespace per line removed, whitespace sequences collapsed to a single space

If your signing server uses c=relaxed/simple or c=simple/simple, switch to c=relaxed/relaxed. This does not fix all body modifications (it only addresses whitespace changes), but it eliminates a category of false failures.

Fix 3: Use the l= Tag (with Caution)

The l= (length) tag specifies how many bytes of the body to hash. If set, only the first N bytes are signed, and appended content does not invalidate the hash.

DKIM-Signature: ... l=1024; ...

This solves mailing list footer problems because footers are appended, not inserted. However, l= introduces a security risk: an attacker could append malicious content to a legitimately signed message and the signature would still verify. Many security experts recommend against l=, and some receivers discount signatures that include it. Use this only when you understand the trade-off.

Fix 4: Contact Your ESP or Gateway Vendor

If the modification happens at a third-party service:

  • Mailing lists: Configure the list software to not modify message bodies (some lists support a "pass-through" mode), or have the list re-sign with its own DKIM key
  • Security gateways: Ask the vendor about DKIM-aware URL rewriting that re-signs after modification, or configure the gateway to preserve DKIM signatures
  • ESPs: Reputable ESPs (SendGrid, Postmark, Amazon SES) sign messages after all template processing. If you see body hash failures from an ESP, contact their support

Fix 5: Ensure DMARC Alignment via SPF

While you resolve the body hash issue, ensure that SPF is configured with proper DMARC alignment as a fallback. DMARC passes if either SPF or DKIM passes with alignment. A working SPF alignment means your emails do not fail DMARC even while DKIM body hash issues persist.

Prevention and Ongoing Monitoring

  • Audit your mail flow — Map every server and service that touches outbound email, and confirm where in the pipeline DKIM signing occurs
  • Monitor DKIM results — Use DMARC aggregate reports (rua=) to detect body hash failures before they become widespread delivery problems
  • Test after infrastructure changes — Any change to email gateways, security tools, or mail routing should be followed by a DKIM verification test
  • Standardize on relaxed canonicalization — Configure c=relaxed/relaxed on all signing servers unless you have a specific reason not to
  • Set up domain health monitoring to catch DKIM failures the moment they start — before they degrade your sending reputation
Was this article helpful?

Related Articles