DKIM fail: what the reason in the header means and how to fix it
dkim=fail means the receiver's DKIM verification failed. Read the reason in brackets, then fix the message path, the DNS record or the key that does not match.
On this page
dkim=fail in an Authentication-Results header means the message carried a DomainKeys Identified Mail (DKIM) signature and the receiving server's verification of it failed. RFC 8601 (opens in a new tab) defines the result that way: the message was signed, but the signature failed the verification tests. Microsoft's header documentation (opens in a new tab) adds that the text after fail says why. RFC 6376 (opens in a new tab), the DKIM standard, defines the verifier's failure results, and the three you will meet in a header are a body hash that does not match, a public key that cannot be found, and a signature that does not verify against the key. Each one points at a different fix, so read the reason first and jump to the matching section.
Read the reason in the Authentication-Results header
The receiver records the outcome of its DKIM check in the Authentication-Results header it adds to the message. Microsoft's anti-spam headers documentation (opens in a new tab) gives the syntax its servers use:
dkim=<pass|fail (reason)|none> header.d=<domain>
A failing line from a Microsoft 365 mailbox looks like this, with the domain replaced by example.com:
Authentication-Results: spf=pass (sender IP is 203.0.113.10)
smtp.mailfrom=example.com; dkim=fail (body hash did not verify)
header.d=example.com; dmarc=fail action=none header.from=example.com
Three parts matter. dkim= carries the result and, on a failure, the reason in brackets. header.d= is the domain from the signature's d= tag, which is the domain the receiver queried for the public key. RFC 8601 (opens in a new tab) registers two more properties receivers may report: header.s=, the selector, and header.a=, the signing algorithm. RFC 6376 (opens in a new tab) builds the DNS query from the d= and s= tags, so header.d= and header.s= together name the record the receiver looked for. A result of none means the message was not signed, and temperror means the receiver hit an error that is likely transient, such as a temporary inability to retrieve the public key.
If you use Google Workspace, Google's troubleshooting guide (opens in a new tab) walks through it: open the message in Gmail, show the original, copy the full header, and paste it into the Google Admin Toolbox Messageheader tool to read the DKIM status.
Check your domain now
See the SPF, DKIM and DMARC records your domain publishes and what to fix first. Free, no account needed.
Body hash did not verify
A DKIM signature carries bh=, the hash of the message body, and b=, the signature data computed over the selected header fields. RFC 6376 (opens in a new tab) tells the verifier to recompute the body hash and compare it with bh=; if the two differ, the verifier returns body hash did not verify and the whole signature is treated as failed.
The cause is something that changed the body after the sender signed it. Microsoft's troubleshooting guide (opens in a new tab) names mailing lists, transport rules and other intermediary services that modify the body after signing. Google's DKIM troubleshooting (opens in a new tab) names forwarding servers and outbound gateways that add a footer to every outgoing message, and states that body hash did not verify next to the dkim entry means the message was modified during transit.
So the place to look is the path the message took: a gateway or signature-footer service, a mailing list, or a forwarding server. Google's advice is to make sure your outbound gateway does not modify outgoing messages and, per Google's DMARC troubleshooting (opens in a new tab), to find out whether the message was routed through another server and ask that server's administrator not to modify messages. Microsoft's advice for intermediaries you trust is to configure them as trusted Authenticated Received Chain (ARC) sealers. A second lever is canonicalisation: RFC 6376 defines a simple algorithm that tolerates almost no modification and a relaxed algorithm that tolerates common modifications such as whitespace replacement and header line rewrapping, with simple as the default when the signer specifies nothing.
No key for signature
The verifier builds the DNS name from the signature's s= and d= tags: for d=example.com and s=selector1 the query is selector1._domainkey.example.com, as RFC 6376 (opens in a new tab) specifies. If that record does not exist, the verifier returns no key for signature; if the record exists but does not follow the key format, it returns key syntax error; and if the DNS query gets no response, it may return a temporary failure and try again later.
Start with the DNS name the header implies. Take header.d= and header.s= from the Authentication-Results line and query the record yourself:
dig TXT selector1._domainkey.example.com
A key record starts with the version tag v=DKIM1 and carries the public key in p=. Checked against live DNS, google._domainkey.demisignal.com answers with a record of that shape, v=DKIM1;k=rsa;p=.... Google's DKIM setup page (opens in a new tab) states the record type is TXT, the value starts with something like v=DKIM1, and that it can take up to 48 hours after adding the key for DKIM authentication to start working. Microsoft 365 (opens in a new tab) uses two CNAME records instead, selector1._domainkey and selector2._domainkey, and starts signing when it detects those CNAME records in DNS; the s= value in the DKIM-Signature header shows which selector signed a given message. In both cases, compare the name you were asked to publish with the header.s= and header.d= values in the failing header.
Signature did not verify
If the body hash matched and the key was found, the verifier checks the b= signature against the header hash with that key. RFC 6376 (opens in a new tab) returns signature did not verify when that check fails. Microsoft's troubleshooting guide (opens in a new tab) describes the usual cause as a public key in DNS that does not match the private key used to sign, or a missing selector record, and lists regular key rotation as routine maintenance. Check first whether the key was rotated recently and whether the record under the selector matches the key your provider shows now.
Incomplete records are a specific trap with long keys. Google's DKIM troubleshooting (opens in a new tab) explains that a 2048-bit key cannot be entered as a single text string where the DNS host limits a TXT string to 255 characters, so the key may be truncated or the strings stored out of order; the fix is to split the key into several quoted strings in the one record. RFC 6376 requires a verifier to join those strings with no whitespace between them, and treats a selector with more than one TXT record as undefined. A related case is a revoked key: RFC 6376 defines an empty p= value as a revoked key and returns a failure for it.
The fix is to republish exactly what the provider's console shows. Copy the record value from the console, compare it character by character with the live DNS answer, remove any duplicate record under the same selector, and test again once the change has propagated.
DKIM-signature is not aligned is a DMARC result
A header or report that reads DKIM signature not aligned is not a DKIM failure. DKIM may have passed. Alignment is a DMARC rule: the d= domain in the signature has to match the domain in the From address. Microsoft documents this case (opens in a new tab) as DKIM passing while DMARC still fails because the d= domain does not match the From address domain, and gives the fix as configuring DKIM for the exact domain used in the From address. Google's DMARC troubleshooting (opens in a new tab) lists the same check: verify that the authentication method is aligned with the header From address. Microsoft's DMARC setup guide (opens in a new tab) shows the common shape, a service signing with its own domain in d= while the From address uses yours, and the fix of configuring custom DKIM signing at the service with your domain. The dmarc=fail guide covers alignment and the fixes for each service.
Check the selector and your records
The free DemiSignal check reads the public DNS records of the domain you enter, with no account, and looks for DKIM keys under commonly used selectors, flagging keys that are weak, revoked or of an unknown type. Add your email address to see the DKIM and MX details. Two limits to keep in mind. A DNS finding shows how your domain is set up, not where a particular message landed. And if your provider uses a selector the check does not try, the key is there but the check cannot see it; your provider's admin console shows the selector it uses. For Google Workspace, the setup guide covers the SPF, DKIM and DMARC records the domain publishes and where each value comes from in the Admin console.
Sources
- RFC 8601 section 2.7.1: DKIM results in Authentication-Results (opens in a new tab)
- RFC 6376: DomainKeys Identified Mail (DKIM) Signatures (opens in a new tab)
- Microsoft Learn: anti-spam message headers (opens in a new tab)
- Microsoft Learn: troubleshoot email authentication in Microsoft 365 (opens in a new tab)
- Microsoft Learn: use DKIM for email in your custom domain (opens in a new tab)
- Microsoft Learn: set up DMARC for your custom domain (opens in a new tab)
- Google Workspace Admin Help: troubleshoot DKIM issues (opens in a new tab)
- Google Workspace Admin Help: troubleshoot DMARC issues (opens in a new tab)
- Google Workspace Admin Help: set up DKIM (opens in a new tab)
Tools for this
-
SPF, DKIM and DMARC check
Check the email records a domain publishes today and see what to fix first.
Frequently asked questions
Does a DKIM fail mean my email was blocked?
Not by itself. A receiver treats a message that fails DKIM verification as unsigned. Microsoft notes that a message can still be allowed after a composite authentication failure when its other assessments do not look suspicious.
Why does DKIM fail only for forwarded mail?
Forwarders, mailing lists and gateways can change the message after it was signed. The receiver recomputes the body hash, it no longer matches the bh= tag, and the result is body hash did not verify. Microsoft and Google both point at the intermediary rather than your DNS for this case.
How long after changing the DNS record does DKIM pass?
There is no fixed time. Google states DKIM authentication can take up to 48 hours to start working after a key is added, and Microsoft ties the start of signing to detecting the CNAME records in DNS. Send a test to an external mailbox and read the header rather than waiting a set period.
Check your domain now
See the SPF, DKIM and DMARC records your domain publishes and what to fix first. Free, no account needed.