DKIM Failures Explained: The Receiver-Side Verdict Catalogue (RFC 6376 §3.9 + RFC 8601 §2.7.1 — dkim=none / neutral / pass / fail / policy / temperror / permerror — Authentication-Results Anatomy, DMARC Alignment Bridge, and the Per-Verdict Diagnostic Decision Matrix)
The receiver-side verdict catalogue for DKIM. Documents each of the seven canonical Authentication-Results verdicts that an RFC 8601 §2.7.1 verifier emits for a DKIM-Signature header per RFC 6376 §3.9: none, neutral, pass, fail, policy, temperror, permerror. Pairs each verdict with its structural meaning (what state the verifier is reporting), common causes (what produces it in practice), operational consequence (whether DMARC alignment is impacted), and diagnostic next step (the action required to resolve it). Includes the Authentication-Results anatomy reference, the DMARC alignment bridge (why dkim=pass does NOT mean DMARC passes), the DMARC rua <auth_results><dkim> block format reference, and a per-verdict diagnostic decision matrix. Differentiation from sibling guides: help_dkim_explained.php is the sender-side protocol primer; help_dkim_canonicalization.php is the c=tag deep dive; help_dkim_for_microsoft_365.php and help_dkim_for_google_workspace.php are per-provider deployment guides; this page is the verdict-decode reference for operators arriving from a DMARC aggregate report row.
This reference is provided in English. RFC 6376 §3.9 status keywords (none, neutral, pass, fail, policy, temperror, permerror) and Authentication-Results syntax (dkim=X header.d= header.s= header.b= reason="..." comment per RFC 8601 §2.7.1) do not translate. We keep the body in the source language so technical terms remain consistent with IETF RFC documentation.
TL;DR
- Seven canonical DKIM verdicts
per RFC 6376 §3.9 + RFC 8601 §2.7.1:
none,neutral,pass,fail,policy,temperror,permerror. Each one tells you a structurally different thing about the message under verification. - none vs fail vs permerror are the three most-confused verdicts. none = no signature present at all. fail = signature present and evaluated, but cryptography failed. permerror = signature present but could not be evaluated (missing public key, malformed signature, unsupported algorithm).
- dkim=pass does NOT mean DMARC
passes. DMARC additionally requires
ALIGNMENT — the
d=tag must match (strict) or share an organizational domain with (relaxed) theFrom:header per RFC 7489 §3.1. The M365onmicrosoft.comand Workspacegappssmtp.comgotchas are pure alignment failures with cryptographic dkim=pass. - temperror is retryable; permerror is not. Concentrated temperror clusters from one receiver = transient DNS issue at THAT receiver; isolated temperror across receivers = your authoritative nameserver is flaky.
- policy is a receiver-side rejection
distinct from fail — common causes are a key the
receiver considers too weak (RFC 8301 permits RSA
from 1024 bits and recommends 2048), the
rsa-sha1algorithm (forbidden by RFC 8301; also reported as permerror), a signature the receiver considers too old (t=; a signature past itsx=is a permerror under RFC 6376), or headers the receiver's policy requires missing from theh=list. - fail is almost always a forwarder/list problem when the underlying signature was valid at origin. Mailing-list footer injection, MTA body re-encoding, Microsoft Defender anti-spoof rewrite, security-gateway sandboxing — all of these break the body hash. ARC sealing (RFC 8617) is the protocol-level fix.
- Per-verdict diagnostic-next-step matrix is the section below. Map the verdict to the action and execute.
- DKIM failures arrive most often
through DMARC aggregate reports
— DMARC Analyzer's reports view
(parsed via
includes/DmarcParser.php) breaks down DKIM verdicts per reporter and per source IP so you can localize a failure to a single receiver, source, or time window.
What this guide covers
A complete receiver-side verdict reference for
DKIM. Where
DKIM explained
documents how the signing pipeline works
(sender-side: key generation, header
canonicalization, body-hash computation,
DKIM-Signature header emission per RFC 6376)
and
DKIM
canonicalization documents the
c= tag's
simple-vs-relaxed tradeoff, THIS page documents
the receiver-side verdict the verifier emits
after evaluating the signature - what each
verdict means structurally, what it implies
operationally, and what diagnostic action it
calls for.
The seven verdict keywords are normative per
RFC 8601
§2.7.1 (Message Header Field for Indicating
Message Authentication Status); they map back
to the RFC 6376 §3.9 status enumeration that
DKIM verifiers internally produce. Every
DMARC aggregate report (RFC 7489 §7.2) that
your rua= mailbox receives
contains a <auth_results><dkim>
block whose <result>
element uses exactly these seven keywords.
The page is anchored against the Feb 2024 Google/Yahoo bulk-sender enforcement that demands aligned DKIM for high-volume senders. Misdiagnosing dkim=fail as "DKIM broken" when the actual cause is a forwarder body rewrite leads to wasted hours on the wrong fix; this page exists to short-circuit that misdiagnosis.
Anatomy of a DKIM verdict in Authentication-Results
The verifier records its verdict on each
message in an
Authentication-Results header per
RFC 8601. A representative DKIM-only stanza:
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=selector1 header.b=AbCdEf12;
dkim=fail (body hash did not verify) header.i=@list.example.org header.s=2024a header.b=ZyXwVu90;
A single message MAY produce MULTIPLE DKIM
verdicts when it carries multiple
DKIM-Signature headers - each
signer's signature is evaluated independently
and emits a separate dkim=
stanza. The example above shows the
sender's original signature passing
(dkim=pass header.d=example.com)
and a mailing-list re-signature failing
(dkim=fail header.d=list.example.org,
body rewritten by list footer injection).
Per-stanza fields
dkim=<verdict>— one of the seven RFC 6376 §3.9 / RFC 8601 §2.7.1 keywords. The verdict.(<optional reason>)— optional free-text describing the failure cause (e.g., "body hash did not verify", "key not found", "weak key size"). Receiver-specific format; not normative.header.i=<AUID>— the agent or user identifier from thei=tag of the DKIM-Signature header (typically@<signing-domain>).header.d=<domain>— the signing-domain identifier from thed=tag. THIS is the value DMARC alignment checks against theFrom:header.header.s=<selector>— the selector from thes=tag. Locates the public-key TXT at<s>._domainkey.<d>.header.b=<sig-prefix>— at least the first eight characters of theb=tag value (RFC 6008). Useful for cross-referencing the verdict with the actual signature header without quoting the full signature.
Multiple Authentication-Results headers
A message that traverses multiple
authentication-aware MTAs may accumulate
multiple Authentication-Results
headers, each scoped to the
authserv-id at the start of the
header (mx.google.com in the
example). When debugging always identify the
AUTHORITATIVE Authentication-Results — the
one whose authserv-id matches the receiving
MTA that ultimately delivered or rejected
the message.
Verdict: dkim=none
Definition: per RFC 8601 §2.7.1, the message was not signed — the verifier had nothing to evaluate.
What it means
The message arrived without a single
DKIM-Signature header. This is
different from dkim=fail (signature present,
crypto failed) or dkim=permerror (signature
present but unevaluable). The verifier did
not run cryptography at all because there
was no input.
Common causes
- DKIM was never enabled at the
sending platform. The #1 cause.
On M365 the
Set-DkimSigningConfig -Enabled $truestep was skipped; on Workspace the Start authentication click never landed. - The sender is mailing through a non-DKIM-enabled path — a bulk-mail platform that does not sign on the sender's behalf, an ESP whose free-tier account does not include DKIM signing, an SMTP-relay device that strips DKIM by default.
- An MTA in the path stripped the DKIM-Signature header. Rare in 2024 but possible with legacy appliances or misconfigured Default-Frontend Connectors on hybrid Exchange (see DMARC for Hybrid Exchange).
- The signing domain's outbound relay was bypassed — direct SMTP submission to the receiver that bypasses the platform's signing layer. Common with on-prem connectors and misconfigured SMTP-AUTH endpoints.
Operational consequence
DMARC requires at least one of DKIM or SPF to PASS AND ALIGN. dkim=none provides neither pass nor alignment (no signing domain to align against). If SPF also fails or misaligns, DMARC fails. dkim=none is the most-common DMARC failure root cause for senders that never finished DKIM rollout.
Diagnostic next step
Verify DKIM is enabled and active at the sending platform:
- For Microsoft 365:
Get-DkimSigningConfig -Identity <your-domain> | Format-List Enabled,Statusmust returnEnabled=True; Status=Valid. See DKIM for Microsoft 365. - For Google Workspace: Admin Console Authenticate email panel must show domain status Authenticating email. See DKIM for Google Workspace.
- For any platform: send a test message
to a mailbox you control and inspect
the headers. If no
DKIM-Signatureappears, signing is not happening on that path.
Verdict: dkim=neutral
Definition: per RFC 8601 §2.7.1, the message was signed, but the signature contained syntax errors or could not otherwise be processed.
What it means
The verifier saw a signature but reached neither pass
nor fail. RFC 8601 also uses neutral for
failures not covered by the other results, so
implementations vary in what they report under it.
Common emission cases
- The signing algorithm is one the verifier does not implement (e.g., ed25519-sha256 per RFC 8463 at a receiver that only supports RSA), so the signature cannot be processed.
- The verifier policy treats certain edge
cases as neutral rather than
fail. Some verifiers emit
neutral when a
l=(body-length-limit) tag is present but the partial-body verification was ambiguous. - Local policy quirks — receivers sometimes mark questionable signatures neutral pending policy refinement.
Operational consequence
Treat dkim=neutral like dkim=none for DMARC alignment purposes — it does not produce a DKIM-pass-and-align. Unlike fail it is not a verifier-rejection; the message is not being branded as unauthentic.
Diagnostic next step
Inspect the optional reason text in the Authentication-Results stanza for hints (some verifiers include the algorithm name or specific policy rule). If volume is concerning, contact the receiver operator — dkim=neutral is rare enough that it usually indicates a niche compatibility issue worth surfacing.
Verdict: dkim=pass
Definition: per RFC 8601 §2.7.1, the signature verified cryptographically — the public key resolved, the algorithm was supported, the body hash matched, and the header signature matched.
What it means
The DKIM verifier successfully completed every protocol step:
- Looked up
<s=>._domainkey.<d=>TXT and retrieved a validv=DKIM1; k=<algorithm>; p=<public-key>record. - Computed the body hash per the
c=tag's canonicalization rules and confirmed it matches thebh=tag. - Reconstructed the signed-header set per
the
h=tag and verified the signature using the public key. - Verified the algorithm in the
a=tag is supported and not deprecated.
What it does NOT mean
dkim=pass does not mean DMARC passes. Two messages can both have dkim=pass with different DMARC outcomes:
# Aligned - DMARC pass
From: alice@example.com
DKIM-Signature: ... d=example.com s=selector1 ...
Authentication-Results: dkim=pass header.d=example.com header.from=example.com
DMARC: pass (alignment via DKIM)
# Misaligned - DMARC fail
From: alice@example.com
DKIM-Signature: ... d=tenant.onmicrosoft.com s=selector1 ...
Authentication-Results: dkim=pass header.d=tenant.onmicrosoft.com header.from=example.com
DMARC: fail (no aligned authentication)
DMARC requires the d= tag to
MATCH the From: header per
RFC 7489 §3.1 — exact match for strict
alignment, organizational-domain match
(via the Public Suffix List) for relaxed
alignment. The M365
onmicrosoft.com gotcha and the
Workspace gappssmtp.com gotcha
both produce dkim=pass with DMARC fail
because the signing domain is the tenant
routing domain rather than the custom
domain.
Diagnostic next step
If dkim=pass but DMARC fails: read
DMARC
alignment for the alignment rules and
inspect the header.d versus
header.from in the
Authentication-Results.
Verdict: dkim=fail
Definition: per RFC 8601 §2.7.1, signature evaluation completed but the cryptographic verification failed — the public key resolved but did not validate the signature.
What it means
The verifier got far enough to attempt cryptographic verification but the comparison failed. This is structurally different from permerror (could not even attempt verification) and temperror (could not retrieve the key).
Common causes — ordered by frequency
- Body modification by a
forwarder — a mailing list
appended a footer ("You are
receiving this because you
subscribed to..."), a security
gateway rewrote URLs through a
sandbox, an outbound relay
normalized line-endings. The body
hash
bh=no longer matches. - MIME re-encoding by an intermediate MTA — base64 ↔ quoted-printable conversion, whitespace normalization in text/plain bodies. Any byte change invalidates the body hash.
- Header modification by an anti-spoof rewriter — Microsoft Defender's "From:" header rewrite for unauthenticated mail triggered for the wrong reason; anti-phishing scanners modifying Subject prefixes.
- Body-hash canonicalization
mismatch — sender signed with
c=simple/simple(strict) but a downstream MTA changed even a single byte;c=relaxed/relaxedis the modern default for forwarder tolerance. - Key mismatch — the operator rotated the key but the old TXT was retired before in-flight signed messages cleared the system.
What dkim=fail almost always IS
A FORWARDER or LIST problem. The original sender's signature was valid when it left the sending MTA; something between sender and final receiver modified the message. ARC sealing per RFC 8617 is the protocol-level fix — see ARC explained.
What dkim=fail rarely is
A genuine sender-side configuration failure. If the sender's outbound signing was broken, you would see dkim=fail CONSISTENTLY across all messages — not the intermittent dkim=fail that forwarder rewrites produce.
Diagnostic next step
- Check whether the failing messages
share a common
X-Mailing-List/List-Id/ forwarder signature header — a single source usually points at a single forwarder problem. - If forwarders are the cause, the ARC seal has to be added by the intermediary and trusted by the receiver (Defender for Office 365 has a Trusted ARC Sealers list; Google Workspace seals with ARC automatically).
- If the failure is consistent across all messages, suspect sender-side configuration: signing module broken, key rotated incorrectly, MTA stripped the signature before transmission. Send a test message and inspect the DKIM-Signature header BEFORE the forwarder hop.
Verdict: dkim=policy
Definition: per RFC 8601 §2.7.1, the signature was evaluated against a LOCAL receiver policy and the policy rejected it.
What it means
The signature itself may have been cryptographically valid, but the receiver applied a stricter local rule than the minimum RFC 6376 spec — and that rule rejected the signature.
Common policy rejections
- Forbidden algorithm —
rsa-sha1is forbidden by RFC 8301, which requires signing and verifying withrsa-sha256only; receivers report such a signature as policy or permerror. - Weak key size — RFC 8301 permits RSA keys from 1024 bits and recommends at least 2048; keys shorter than 1024 bits are a permanent failure. Strict receivers may reject 1024-bit keys by policy as well, so 2048-bit is the baseline.
- Signature too old — the
t=(signing timestamp) tag is older than the receiver-configured maximum. A signature past itsx=(expiration) tag is already a PERMFAIL under RFC 6376, i.e. permerror. - Missing required header in
h=tag — the receiver requiresFrom,Subject,Date,To, andMessage-IDall covered by the signature, but theh=list omits one of them. - Suspicious signing-domain pattern — receiver detected the d= tag is a freshly-registered throwaway or matches a known abuse catalogue.
Operational consequence
Like dkim=fail, dkim=policy does not provide DMARC alignment. Unlike dkim=fail the fix is almost always sender-side — you must upgrade your signing posture to meet the receiver's policy.
Diagnostic next step
- If the reason includes "weak key" or "key size", rotate to 2048-bit RSA per RFC 8301. See DKIM key rotation.
- If the reason includes
"algorithm", ensure your
signer uses
a=rsa-sha256(notrsa-sha1). - If the reason includes "expired", extend
the window of the
x=tag or find out why messages arrive that late. - If the reason is missing or generic, contact the receiver operator — local policy rules are not RFC-normative and often need direct communication to diagnose.
Verdict: dkim=temperror
Definition: per RFC 8601 §2.7.1, evaluation hit a TEMPORARY error that prevented completion — typically a DNS timeout while looking up the public key.
What it means
The verifier began evaluation but could not complete it. The signature is not necessarily invalid; the verifier just could not retrieve the public-key TXT in time. RFC 6376 calls this result TEMPFAIL and lets the verifier defer the message for later processing or try another signature (§6.1); RFC 8601 adds that a later attempt may produce a final result. Until the key is retrieved, the signature does not count as valid.
Common causes
- Authoritative nameserver outage — the operator's primary DNS host has a momentary outage while the verifier is querying.
- Recursive resolver flakiness — the receiver's resolver is overloaded or experiencing transient packet loss.
- CNAME-chain timeout — for M365 DKIM CNAMEs that resolve through the tenant onmicrosoft.com target, a slow resolution chain can time out before the TXT at the chain's end is retrieved.
- Anycast routing changes — DNS anycast pools occasionally shift traffic between sites mid-lookup; verifiers with aggressive timeouts hit these shifts as temperrors.
How to read temperror in aggregate reports
Isolated temperror rows (one or two from a single receiver in a 24-hour window) are routine and self-resolve.
Concentrated temperror clusters tell you something:
- If many rows from ONE receiver are temperror in a tight time window, that receiver's resolvers had an outage — not your problem.
- If many rows from ALL receivers are temperror across a 24-hour window, YOUR authoritative nameserver is flaky. Investigate your DNS provider.
Diagnostic next step
- Run continuous external DNS probes against
<your-selector>._domainkey.<your-domain>from multiple geographies for 24-48 hours. If the probes show consistent sub-100ms responses, the issue is receiver-side. - Validate the CNAME chain depth — long chains amplify lookup latency. M365 CNAMEs typically chain through 2 hops; more than 3 is suspicious.
- Verify TTL values are reasonable (3600-86400 for steady-state); very low TTLs increase lookup load and timeout risk.
Verdict: dkim=permerror
Definition: per RFC 8601 §2.7.1, evaluation hit a PERMANENT error that prevented completion — the verifier could not even attempt cryptographic verification.
What it means
Something is structurally wrong with the signature or its surrounding context such that the verifier cannot perform the crypto. Unlike temperror this is not retryable — the next lookup will produce the same permerror.
Common causes
- Public-key TXT does not
exist — the
<s>._domainkey.<d>query returns NXDOMAIN. Most common after a botched rotation that retired the old selector's TXT before in-flight signed messages cleared the system. - Public-key TXT is empty or
revoked — the TXT contains
v=DKIM1; k=rsa; p=with no public-key bytes (Workspace explicit revocation pattern). - Public-key TXT is malformed — invalid base64, wrong tag set, broken multi-string chunking past the 255-byte TXT character-string limit per RFC 1035 §3.3.14.
- DKIM-Signature header is
syntactically broken — missing
required tags (
v=,a=,d=,s=,h=,b=,bh=), invalid base64, malformed canonicalization spec. - Algorithm forbidden or not
supported — the
a=tag specifies rsa-sha1, which RFC 8301 treats as permanently failed, or an algorithm the verifier does not know at all (the latter is also reported as neutral).
Operational consequence
Like dkim=fail and dkim=policy, permerror does not produce DMARC alignment. Unlike fail, permerror almost always points at a sender-side publishing or signing problem, not a forwarder.
Diagnostic next step
- Look up the public-key TXT yourself:
dig +short TXT <s=>._domainkey.<d=>. If NXDOMAIN, the publishing side is broken. - Validate the TXT format with a DKIM record-syntax tool (or Domain Security Checker's DKIM block).
- Pull the failing message's full DKIM-Signature header (header.b= is in the Authentication-Results) and run it through Email Header Analyzer for the structural validation.
DKIM verdicts versus DMARC alignment
The single most-confused topic in DKIM diagnostics. DKIM verification is separate from DMARC alignment.
DKIM verification answers: "Did the signature cryptographically verify?" The answer is the verdict — one of the seven keywords above.
DMARC alignment answers: "Does the
d= tag of a dkim=pass signature
match (strict) or share an organizational
domain (relaxed) with the
From: header?"
Both must succeed for DKIM-based DMARC authentication. The standard error cases:
Case A: dkim=pass + DMARC pass
From: alice@example.com
DKIM-Signature: ... d=example.com s=selector1 ...
Authentication-Results: dkim=pass header.d=example.com header.from=example.com
DMARC: pass (DKIM aligned)
The happy path. d= equals From: so DMARC is satisfied.
Case B: dkim=pass + DMARC fail (M365 onmicrosoft.com gotcha)
From: alice@example.com
DKIM-Signature: ... d=tenant.onmicrosoft.com s=selector1 ...
Authentication-Results: dkim=pass header.d=tenant.onmicrosoft.com header.from=example.com
DMARC: fail (no aligned authentication)
Signature is valid (dkim=pass) but d=tenant.onmicrosoft.com does not match From=example.com — alignment fails. See DKIM for Microsoft 365 for the M365 fix.
Case C: dkim=pass + DMARC fail (Workspace gappssmtp.com gotcha)
From: alice@example.com
DKIM-Signature: ... d=tenant.gappssmtp.com s=20221208 ...
Authentication-Results: dkim=pass header.d=tenant.gappssmtp.com header.from=example.com
DMARC: fail (no aligned authentication)
Same structural problem as Case B but on Google Workspace. See DKIM for Google Workspace for the Workspace fix.
Case D: dkim=fail or dkim=permerror — alignment irrelevant
Without a dkim=pass verdict there is no DKIM-based alignment to evaluate. DMARC falls back to SPF-based alignment (or fails entirely if SPF also fails or misaligns).
Reading DKIM verdicts in DMARC aggregate reports
DMARC aggregate (rua) reports per RFC 7489
§7.2 include a
<auth_results><dkim>
block per signature evaluated. Schema:
<auth_results>
<dkim>
<domain>example.com</domain>
<selector>selector1</selector>
<result>pass</result>
<human_result></human_result>
</dkim>
<dkim>
<domain>list.example.org</domain>
<selector>2024a</selector>
<result>fail</result>
<human_result>body hash did not verify</human_result>
</dkim>
</auth_results>
The <result> element
uses the same seven keywords this guide
documents (pass, fail, neutral, temperror,
permerror, none, policy). The
<human_result> element
optionally carries the receiver's free-text
failure reason — exceptionally valuable
for diagnosis when present.
DMARC Analyzer's report drill-down
The Reports page (parsed via
includes/DmarcParser.php)
groups DKIM verdicts by:
- Reporter — who issued the verdict (mail.google.com, outlook.com, mx.yahoo.com, etc.). A single reporter producing all the failures usually = a forwarder problem at that one receiver.
- Source IP — what sending IP the message came from. A single source IP producing all the failures usually = a misconfigured outbound MTA.
- Signing domain (header.d) — what d= tag the signer used. Useful for catching the M365 onmicrosoft.com and Workspace gappssmtp.com gotchas.
- Time window — when the failures occurred. Concentrated time clusters often correlate with deployment events (key rotation, signer migration, MTA upgrade).
The dashboard's per-reporter breakdown is the fastest way to localize "is this failure my fault or the receiver's?" — typically the answer is visible in seconds.
Per-verdict decision matrix
Map verdict to action:
dkim=none→ DKIM is not enabled at the sending platform. VerifyGet-DkimSigningConfig(M365) or Admin Console status (Workspace); enable signing for the custom domain.dkim=neutral→ Rare; inspect the reason text; usually a niche algorithm or policy edge case. Contact receiver if volume is concerning.dkim=pass+ DMARC fail → Alignment problem, not a DKIM problem. Checkheader.dvsheader.from; almost always the M365 onmicrosoft.com or Workspace gappssmtp.com gotcha.dkim=fail→ Almost always a forwarder/list rewriting the body. Configure ARC sealing at the outbound MTA. If consistent across all messages, suspect sender-side signer breakage.dkim=policy→ Sender-side posture upgrade needed. Rotate to 2048-bit RSA + rsa-sha256; remove thex=tag if present; ensureh=covers From, Subject, Date, To, Message-ID.dkim=temperror→ DNS lookup transient failure. If isolated, ignore. If concentrated from one receiver, the receiver's DNS had an outage. If concentrated across all receivers, your authoritative nameserver is flaky.dkim=permerror→ Sender-side publishing or signing problem.digthe public key, validate the TXT format, parse the DKIM-Signature header structurally.
Frequently asked questions
- What does dkim=none mean in Authentication-Results?
- dkim=none per RFC 8601 §2.7.1 means the message arrived with no DKIM-Signature header at all - the verifier had nothing to evaluate. The most common cause is that the sending domain never enabled DKIM signing for outbound mail. On Microsoft 365 the fix is Set-DkimSigningConfig -Identity <your-domain> -Enabled $true after publishing the two CNAMEs; on Google Workspace it is the Start authentication click in the Admin Console after publishing the google._domainkey TXT. dkim=none is NOT a failure per se - it indicates absence rather than verification failure - but it is fatal for DMARC because DMARC requires at least one of DKIM or SPF to align with the From: header domain. When you see dkim=none in DMARC aggregate reports for messages your domain sent, the diagnostic next step is to verify DKIM is enabled at the sending platform.
- What is the difference between dkim=fail and dkim=permerror?
- dkim=fail means the signature was evaluated and FAILED cryptographically - the public key resolved correctly but the signature did not verify against the message content. Common causes: body modification by a forwarder, mailing-list footer injection, MTA header rewriting, body-hash mismatch from MIME re-encoding. dkim=permerror means the signature could not be evaluated at all due to a permanent error - the public key TXT does not exist or is malformed, the d= domain has no DNS record at the selector, the signature header itself is syntactically broken, or the algorithm is unsupported. The diagnostic distinction matters: dkim=fail = signature reached the verifier but the content was tampered (operationally a forwarder/list problem); dkim=permerror = the verifier could not even attempt verification (operationally a publishing/configuration problem). RFC 6376 §3.9 defines three verifier outputs (SUCCESS, PERMFAIL, TEMPFAIL); RFC 8601 §2.7.1 defines the seven dkim=X keywords that appear in Authentication-Results.
- What does dkim=temperror mean and should I be worried?
- dkim=temperror means the verifier hit a temporary failure that prevented evaluation - usually a DNS timeout while looking up the public key at <s=>._domainkey.<d=>. The signature itself may be valid; the verifier just could not retrieve the key in time. Common causes: authoritative nameserver outage, recursive resolver flakiness, transient network failure between verifier and the publishing nameserver, CNAME-chain timeout (M365 CNAMEs that resolve through the tenant target onmicrosoft.com). Per RFC 8601 a later attempt may produce a final result, and RFC 6376 §6.1 lets the verifier defer the message for later processing or try another signature - until the key is retrieved the signature does not count as valid. If you see ISOLATED dkim=temperror rows in aggregate reports they are usually transient and self-resolve. If you see CONCENTRATED dkim=temperror clusters (many rows from the same receiver, same time window) then your authoritative nameservers may be under-resourced or there is a CNAME-chain problem.
- What does dkim=neutral mean?
- dkim=neutral per RFC 8601 §2.7.1 means the message was signed, but the signature contained syntax errors or could not otherwise be processed. The RFC also uses it for failures not covered by the other results. The most common modern case is a signature using an algorithm the verifier does not implement (e.g., ed25519-sha256 per RFC 8463 at a receiver that only supports RSA), or an edge case a verifier prefers to report as neutral rather than fail. dkim=neutral is rare in practice and implementations vary in what they report under it. RFC 8601 adds that neutral, like none, means the message will be treated as if it had not been signed, so treat dkim=neutral like dkim=none for DMARC alignment purposes (it does not produce alignment). If you see dkim=neutral in aggregate reports at a concerning volume, check the syntax of your own signature and contact the receiving operator.
- What is dkim=policy and when does it appear?
- dkim=policy per RFC 8601 §2.7.1 means the message was signed, but some aspect of the signature was not acceptable to the receiving domain - a LOCAL receiver policy rejected it. Common policy rejections: a key the receiver considers too weak (RFC 8301 permits RSA from 1024 bits and recommends at least 2048, and strict receivers may demand more than the minimum), a signature older than the receiver accepts (the t= timestamp tag), a third-party signing domain the receiver does not accept, or an h= tag that does not cover a header the receiver requires signed per its local policy. Some receivers also report rsa-sha1 signatures as policy, although RFC 8301 treats them as permanently failed. dkim=policy is a receiver-side rejection, distinct from the protocol-level dkim=fail. The operational fix is sender-side: sign with rsa-sha256, upgrade to 2048-bit keys, and ensure the h= tag covers From (an RFC 6376 requirement) plus Subject, Date, To and Message-ID. See RFC 8301 for the modern algorithm/key-size requirements.
- My DKIM signature says dkim=pass but DMARC still fails - why?
- Because dkim=pass evaluates ONLY the cryptographic signature, not DMARC ALIGNMENT. DMARC requires the DKIM-Signature d= tag to ALIGN with the From: header domain (RFC 7489 §3.1) - either strict (exact match) or relaxed (organizational-domain match via PSL). The most common alignment-failure pattern is the M365 onmicrosoft.com gotcha (dkim=pass header.d=tenant.onmicrosoft.com but header.from=example.com - signature passes, alignment fails) and the Workspace gappssmtp.com gotcha (dkim=pass header.d=tenant.gappssmtp.com but header.from=example.com). The fix is to enable DKIM signing for the CUSTOM domain at the sending platform so the d= tag points at example.com instead of the tenant routing domain. See help_dmarc_alignment.php for the alignment-evaluation rules and help_dkim_for_microsoft_365.php / help_dkim_for_google_workspace.php for the per-provider fixes.
- How do I find DKIM failure verdicts in DMARC aggregate reports?
- DMARC aggregate (rua) reports per RFC 7489 §7.2 include, in every report row, an <auth_results> block with one <dkim> element for each evaluated signature. Each block contains a <domain> (the DKIM d= tag), a <selector> (the s= tag), and a <result> element that is one of pass, fail, neutral, temperror, permerror, none, or policy (matching the RFC 6376 §3.9 status keywords exposed via RFC 8601 §2.7.1). DMARC Analyzer parses these blocks via includes/DmarcParser.php and surfaces the per-domain DKIM verdict breakdown on the dashboard. To pivot from "I see dkim=fail in my Authentication-Results header" to "show me all rua rows for that domain and selector", upload the rua XML or feed it via IMAP/Graph and open the Reports drill-down. The drill-down groups DKIM verdicts by reporter so you can isolate whether a single receiver is producing the failures (likely a forwarder/list problem on their side) or all receivers are (likely a sender-side configuration problem).
- Can DKIM verdicts differ between receivers for the same message?
- Yes, by design. RFC 6376 leaves DKIM verification policy choices to receivers, and RFC 8601 only specifies the verdict vocabulary - not the verdict-emission rules. Three common divergence patterns: (1) Forwarder rewrites the message body between hop 1 (receiver A reports dkim=pass for the original signature) and hop 2 (receiver B reports dkim=fail because body-hash mismatches after the rewrite) - solved by ARC sealing per RFC 8617. (2) Local-policy strictness: receiver A accepts a signature made with a 1024-bit key as dkim=pass while receiver B emits dkim=policy on the same message - solved by sender-side migration to 2048-bit keys and rsa-sha256. (3) DNS-cache state: receiver A had the DKIM TXT cached from a prior lookup while receiver B emits dkim=temperror because its lookup hit a transient nameserver outage. The DMARC aggregate-report ecosystem reveals this divergence by reporting receiver-by-receiver verdicts; the dashboard pivot view shows where consistency breaks down.
Localize a DKIM failure in your reports now
DMARC Analyzer parses the
<auth_results><dkim>
blocks of every aggregate report via
includes/DmarcParser.php and
surfaces the per-domain, per-selector,
per-reporter verdict breakdown on the
dashboard. The Reports drill-down lets
you pivot from "I see dkim=fail" to
"here are the 47 rua rows that produced
that failure, grouped by reporter and
source IP". The
Email
Header Analyzer at
header_analyzer.php
structurally validates individual
DKIM-Signature headers via
includes/EmailHeaderParser.php
— paste a failing message's headers and
see the verdict breakdown plus the
DKIM-Signature tag-by-tag parse.