DKIM Fail: Every DKIM Error Explained and How to Fix It
Seeing dkim=fail, permerror, temperror, or body hash did not verify? This guide explains every DKIM result you will find in email headers, what causes each one, and the exact fix.
DKIM (DomainKeys Identified Mail) adds a cryptographic signature to your outgoing mail. The receiving server fetches your public key from DNS, recomputes the signature, and compares. When the two do not match, or the key cannot be found, the receiver records a DKIM failure in the message headers and your mail loses one of the two authentication signals that DMARC depends on.
The good news is that a DKIM failure always tells you why it failed. The reason is written into the header. This guide shows you how to read it, what each result means, and how to fix every common cause.
Start with the header: a worked example
Here is the Authentication-Results header from a real-world style failure, as Gmail would record it. Open any message in Gmail, choose "Show original", and you will find a block like this near the top.
Authentication-Results: mx.google.com;
dkim=fail (body hash did not verify) [email protected] header.s=s1 header.b=K3pQ9x2f;
spf=pass (google.com: domain of [email protected] designates 198.51.100.24 as permitted sender) [email protected];
dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=example.com
Three pieces of that line answer most questions before you touch DNS:
header.s=s1is the selector. The receiver looked for your public key ats1._domainkey.example.com.[email protected]is the signing domain. It must align with the From domain for DMARC to pass on DKIM.- The reason in parentheses, here
body hash did not verify, names the failure family. The fixes below are organised by that reason.
Further down the same message you will find the signature itself:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=s1;
h=from:to:subject:date:message-id:mime-version:content-type;
bh=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN/XKdLCPjaYaY=;
b=K3pQ9x2fVb1n4Qm9...
d=ands=are the domain and selector the signer used. If they do not match theheader.iandheader.svalues above, you are looking at a different signature (some messages carry several).h=lists the headers that were signed. If any of these changed after signing, the signature fails.bh=is the hash of the message body as it was when signed. Abody hash did not verifyfailure means the body no longer produces this hash.b=is the signature over the headers and the body hash.
In the example, SPF passed but DKIM failed on the body hash and DMARC failed because the SPF domain ([email protected]) is the same organisational domain, so alignment should have rescued it. That combination usually means the message went through a mailing list or a gateway that rewrote the body. Keep reading for the fix.
The six DKIM results
| Result | Meaning | Severity |
|---|---|---|
| `pass` | Signature verified and key found | None, working correctly |
| `fail` | Signature present but verification failed | High, needs fixing |
| `permerror` | Permanent configuration error (key, selector, or syntax) | High, needs fixing |
| `temperror` | Temporary error, usually a DNS timeout | Medium, often self-resolves |
| `none` | No DKIM signature on the message | Medium, you should be signing |
| `neutral` / `policy` | Signature present but the receiver would not use it (weak key, unsupported algorithm) | Medium, regenerate the key |
What each failure means and how to fix it
dkim=fail (signature verification failed)
The receiver found your public key but the signature did not check out against it.
Causes:
- The private key used for signing does not match the public key in DNS. This is the classic symptom of a key rotation where DNS was never updated, or the wrong key was pasted into DNS.
- One of the headers listed in the
h=tag was modified after signing. Gateways that rewrite the Subject line (adding "[EXTERNAL]", for example) do this. - The signature was created with an old key that has since been removed from DNS.
Fix: Regenerate the key pair in your sending service and republish the public key. If you rotate keys, keep the old public key in DNS for at least a week so mail already in transit still verifies. If a gateway is rewriting headers, sign after the gateway or stop it modifying signed headers.
dkim=fail (body hash did not verify)
The headers were fine but the body changed after it was signed.
Causes:
- A mailing list, forwarder, or security gateway added a footer, disclaimer, tracking pixel, or warning banner.
- Line endings were converted between LF and CRLF somewhere in the pipeline.
- Character encoding changed, or an attachment was rescanned and re-encoded.
Fix: For systems you control, make DKIM signing the last step before the message leaves. Move disclaimer and footer insertion before signing, and check for content-altering security appliances. For mail that legitimately passes through lists and forwarders, this failure is expected. DMARC will still pass if SPF passes and aligns, and receivers increasingly honour ARC (Authenticated Received Chain) for forwarded mail. See why email forwarding breaks authentication.
dkim=permerror
A permanent problem with the configuration itself. The receiver could not even attempt verification. The reason in parentheses tells you which of these you have:
no key for signature: nothing exists atselector._domainkey.yourdomain. Either the record was never published or the selector in the signature does not match the DNS name.key syntax errororinvalid tag-value syntax: the record exists but is malformed. Look for a missingv=DKIM1, a truncatedp=value, stray whitespace, or line breaks introduced when the key was pasted.selector not found: thes=tag references a selector your DNS does not have. Common when a service changes its default selector or when Microsoft 365 alternates betweenselector1andselector2.
Fix: Query the exact name the receiver used and compare it with what your sending service expects. The four-step diagnosis below does this.
dkim=temperror
A temporary failure, almost always DNS.
DNS lookup timed out: the receiver could not reach your nameservers in time.DNS server error: your DNS provider returned an error.
These are not directly fixable from the sender side, and most clear on retry. If they persist, look at your DNS hosting. Slow or flaky authoritative nameservers cause temperrors for every receiver at once, which turns a DNS problem into a deliverability problem. Reliable DNS hosting, sensible TTLs, and DNS monitoring are the answer.
dkim=none
The message was not signed at all.
Causes: DKIM is not enabled in the sending service, signing is disabled for a particular message type, or a self-hosted mail server was never configured to sign.
Fix: In Google Workspace or Microsoft 365, enable DKIM signing in the admin console for the sending domain. In an ESP such as SendGrid or Mailchimp, complete domain authentication so the service signs with your domain instead of its own. On a self-hosted server, install and configure OpenDKIM or equivalent and check the mail log for signing errors.
Weak key, unsupported algorithm, or expired signature
Three less common results that look like failures:
key too smallordkim=policy (weak key): a 512-bit or 768-bit key. Receivers reject these. Generate a 2048-bit key. See DKIM key length.unsupported algorithm: an old signing algorithm such as rsa-sha1. Use rsa-sha256, or ed25519 where your service supports it.signature expired: the signature carries anx=expiry tag that has passed. Remove the tag or extend it. Expiry tags are rarely useful on transactional mail.
The eight configuration mistakes behind most failures
Most DKIM failures come down to one of these.
1. No DKIM record published
The service signs, but you never added the public key to DNS. Every service that sends as your domain needs its own record.
2. Wrong selector
The selector in the signature must match the DNS name exactly.
| Service | Default selector | DNS record location |
|---|---|---|
| Google Workspace | `google` | `google._domainkey.yourdomain.com` |
| Microsoft 365 | `selector1`, `selector2` | `selector1._domainkey.yourdomain.com` |
| SendGrid | `s1`, `s2` | `s1._domainkey.yourdomain.com` |
| Mailchimp | `k1`, `k2`, `k3` | `k1._domainkey.yourdomain.com` |
| Amazon SES | Three random tokens | `token._domainkey.yourdomain.com` |
Multiple records do not conflict. Each service uses its own selector, so a domain that sends through Google Workspace and SendGrid simply has both records.
3. Key mismatch after rotation
Keys were rotated in the service but DNS still holds the old public key, or the wrong key was copied. See the rotation procedure below.
4. Message modified in transit
Mailing lists, auto-forwarders, corporate gateways, and antivirus scanners all rewrite mail. This is the usual cause of body hash failures on mail that verified fine when it left you.
5. DNS propagation
After adding or changing a record, some resolvers still serve the old answer until the TTL expires. Allow up to 48 hours, and lower the TTL before planned changes.
6. Record syntax errors
The public key is long and easy to truncate. Compare the p= value in DNS character by character with the one your service shows you.
# Broken (truncated)
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC...
# Correct (complete key)
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsR8rRwZ...complete...key==
Some DNS providers split long TXT records into 255-character chunks automatically. Others require you to do it. Either is fine as long as the chunks concatenate to the full key.
7. Key too short
Anything under 1024 bits fails at major receivers. Use 2048 bits.
8. CNAME published as TXT, or the reverse
SendGrid, Mailchimp, and Amazon SES give you CNAME records that point at keys they host. Google and Microsoft give you TXT records. Publishing the wrong type produces no key for signature.
s1._domainkey.yourdomain.com CNAME s1.domainkey.u12345.wl.sendgrid.net
Diagnose it in four steps
Read the selector and domain from the failing message
In the DKIM-Signature header, note s= and d=. In the example above, s=s1 and d=example.com.
Query DNS for the key the receiver looked up
Run dig +short TXT s1._domainkey.example.com. No answer means no record (or wrong selector). An answer that does not start with v=DKIM1 means a syntax problem.
Compare the key with your sending service
Open the DKIM settings in the service that sent the message and compare the p= value it shows with what DNS returned. Any difference is a key mismatch.
Check the reason in Authentication-Results
If DNS and the key are correct and the reason is body hash did not verify, the message was altered after signing. Look at the path the message took, not at DNS.
DKIM Test runs steps two and three for you: enter the domain and selector and it fetches the record, validates the syntax, and reports the key length.
Fix it step by step
- Identify the signing service. Corporate mail (Google, Microsoft), a marketing platform, or a transactional service. The failing selector tells you which.
- Get the DKIM record from that service. Generate keys if none exist, then copy the record exactly as shown, including the record type.
- Publish it in DNS. Correct type, correct selector, complete key.
- Enable signing. Some services require an explicit toggle after the record verifies.
- Send a test and read the header. You want
dkim=passwith the selector you expect andheader.imatching your From domain.
Rotating keys without breaking DKIM
Key rotation is where most avoidable failures come from. The safe order is:
- Generate a new key pair in the sending service, on a new selector.
- Publish the new public key in DNS.
- Wait for propagation, 24 to 48 hours.
- Switch signing to the new selector.
- Leave the old public key in DNS for at least seven days, then remove it.
Services that rotate keys automatically (Microsoft 365 alternates between selector1 and selector2, and Amazon SES rotates its tokens) rely on the CNAME records you published pointing at keys they control. If you replaced those CNAMEs with static TXT records, automatic rotation will break signing.
Testing after changes
Confirm the DNS record
dig +short TXT selector._domainkey.yourdomain.com from at least two networks, since propagation is uneven.
Send a real message
Send through the production service to a Gmail, Outlook.com, and Yahoo mailbox you control.
Read Authentication-Results
Look for dkim=pass and check that header.s is the selector you just changed.
Watch DMARC reports for a week
Aggregate reports will show any sending source that is still failing DKIM. See DMARC aggregate reports explained.
Debugging checklist
| Header says | Check | Fix |
|---|---|---|
| permerror (no key for signature) | Does the record exist at selector._domainkey? | Publish the key, or correct the selector |
| permerror (key syntax error) | Does it start with v=DKIM1 and have a complete p=? | Re-paste the record from the service |
| fail (signature verification failed) | Does the DNS key match the service's key? | Regenerate and republish; keep old key during rotation |
| fail (body hash did not verify) | Did anything rewrite the body after signing? | Sign last; accept it for forwarded mail and rely on SPF alignment or ARC |
| none | Is DKIM enabled for this domain in this service? | Enable signing and complete domain authentication |
| temperror | Are your nameservers slow or down? | Fix DNS hosting; retry |
| policy (weak key) | Is the key under 1024 bits? | Generate a 2048-bit key |
DKIM failures look cryptic but they are almost always a DNS record, a key mismatch, or a message modified in transit. Read the reason in the header first, and it points you straight at the fix.
Related Articles
Related Articles
- DMARC Fail: Troubleshooting DMARC Authentication Failures
- SPF Fail, Softfail, and Hardfail Explained
- DKIM Key Rotation: How and When to Rotate Keys
- DKIM Key Length: Choosing Between 1024-bit and 2048-bit Keys
- Email Authentication Failed: How to Fix SPF, DKIM, and DMARC Failures
- SPF vs DKIM vs DMARC: What's the Difference?
Monitor DKIM Automatically
The Email Deliverability Suite monitors your DKIM records, SPF, DMARC, MX records and blacklist status daily. Get alerts when DKIM configuration breaks, before your emails start failing.
Catch DKIM issues early
SPF, DKIM, DMARC, MX, and blacklist monitoring for unlimited domains. $39/month.