Suped

How do I interpret SpamAssassin DKIM test results and troubleshoot DKIM signature issues?

Published 29 May 2025
Updated 8 Oct 2026
17 min read
Summarize with
SpamAssassin DKIM test results and signature troubleshooting illustrated with email and DNS icons.
Updated on 8 Oct 2026: We clarified SpamAssassin DKIM scores and added checks for DNS failures and verifier configuration.
If a SpamAssassin report shows DKIM_SIGNED with DKIM_INVALID, the message has a signature header, but SpamAssassin found no valid signature. Confirm the local definition of a label such as DKIM_INVALID_DKIM before drawing the same conclusion. The small score beside the rule, such as 0.1, is only a SpamAssassin score contribution. It is not proof that the message landed in spam, and it is not proof that your whole domain has broken DKIM.
Start with the raw message headers, especially Authentication-Results. Then compare each DKIM-Signature with DNS and the visible From domain. A correct DKIM DNS record does not guarantee that a specific email passes signature verification. Message changes after signing, an incorrect selector, or a failed public key lookup can break verification. A passing signature without DKIM alignment is a separate DMARC issue.
  1. SpamAssassin rule names are clues about what its local engine observed.
  2. A small positive value adds to the spam score; a negative value subtracts from it. The weight depends on the local SpamAssassin configuration.
  3. The fix is in the signature, message path, selector DNS, or scanner input, not in the score.
  4. For DMARC's DKIM path, at least one signature must pass with DKIM alignment to the visible From domain. SPF with SPF alignment is the other path.

Interpret SpamAssassin DKIM rules and scores

SpamAssassin is a scoring engine. A rule hit means one test matched. It does not mean the message failed every mailbox provider's filtering, and it does not mean the rule is wrong. It means that SpamAssassin's DKIM plugin and local rule set produced that result for that exact copy of the message.
Apache SpamAssassin's default rules use DKIM_INVALID for the meta rule DKIM_SIGNED && !DKIM_VALID. A label such as DKIM_INVALID_DKIM can come from a local rule or the way a report presents the result. If you run your own installation, check the installed rules and active score files before treating a public description as authoritative for your server.
The short version
Treat SpamAssassin DKIM results as diagnostic output. The important question is whether at least one signature passed in the receiving system's trusted Authentication-Results header and whether that signature can satisfy DMARC.
  1. The message has at least one DKIM-Signature header.
  2. The default DKIM_INVALID rule means DKIM_SIGNED fired and DKIM_VALID did not.
  3. The points are local SpamAssassin weighting, not a universal inbox placement score.
  4. Use full headers and DNS, not screenshots of a partial score table.

Rule

Meaning

Action

DKIM_SIGNED
At least one signature header is present
Check validation
DKIM_VALID
At least one signature passed
Check DMARC alignment
DKIM_VALID_AU
Author-domain signature passed
Confirm the From domain
DKIM_VALID_EF
Envelope-from signature passed
Do not assume DMARC pass
DKIM_INVALID
Signed, but no signature passed
Inspect each signature
DKIM_INVALID_DKIM
Local or report-specific invalid label
Confirm its local definition
Common SpamAssassin DKIM rules and the practical next step.
Illustrative SpamAssassin DKIM score combinationstext
Signed message with no valid signature: 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.1 DKIM_INVALID DKIM or DK signature exists, but is not valid Message with a valid author-domain signature: 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain
A positive DKIM_SIGNED score alongside negative DKIM_VALID and DKIM_VALID_AU scores is expected for a valid author-domain signature. These are separate tests, and their contributions are added to the total. The sample weights are illustrative; check the active scores on your server.

Why a correct DNS record does not guarantee DKIM

The most common misunderstanding is treating a correct DNS record as proof that every outgoing message is correctly signed. DNS proves the public key is available. It does not prove that a specific message body, header set, selector, and signing domain all match the signature placed on that message.
DNS record is correct
This confirms that a public key is published, but not that it matches the private key used by the signer.
  1. The selector record resolves in DNS.
  2. The TXT record parses as DKIM.
  3. It says nothing about later message changes.
  4. A different selector can still fail.
Message signature is valid
This proves the signed message survived verification.
  1. The body hash matches the body.
  2. Signed headers still match.
  3. The d= domain identifies the signer; a valid signature alone does not establish DKIM alignment.
  4. The checked content is unchanged after canonicalization; harmless formatting changes can still pass.
A different envelope domain is not, by itself, a DKIM failure. DKIM validates the DKIM-Signature header and the d= signing domain. The envelope sender matters for SPF and for DMARC's SPF path. For DKIM to support a DMARC pass, the signing domain must meet DMARC alignment requirements for the visible From domain under the published adkim mode.
DKIM verification checks the signature header, signed headers, body hash, and DNS key.
DKIM verification checks the signature header, signed headers, body hash, and DNS key.

Start with Authentication-Results

The best next move after a SpamAssassin DKIM hit is to inspect the full raw email. Authentication-Results records what a receiver actually checked. Use the header generated inside the receiving system's trust boundary, with its expected authentication service identifier, rather than trusting header position alone.
Authentication-Results exampletext
Authentication-Results: mx.example.net; dkim=fail reason="signature verification failed" header.d=example.com header.s=selector1; spf=pass smtp.mailfrom=bounces.sender.example; dmarc=fail header.from=example.com
This header tells you whether the DKIM failure is real at the receiver and whether DMARC had another path to pass. If the trusted Authentication-Results header says dkim=pass, but a separate SpamAssassin run says invalid, compare the exact message copies and check whether SpamAssassin received the complete body. Also compare DNS answers and verifier settings at the time of each check.
  1. dkim=pass means the receiver verified at least one DKIM signature.
  2. dkim=fail means verification failed. Read the reason field, then check that signature's selector and signed content.
  3. dkim=temperror indicates a temporary verification problem, such as a DNS timeout. Check the resolver and retest.
  4. dkim=permerror indicates an unrecoverable verification error, such as malformed signature data. Inspect the stated reason.
  5. header.d identifies the signing domain to compare with the visible From domain.
  6. header.s identifies the selector to use when querying the public DKIM key.
Header trust matters
A message can contain several Authentication-Results headers, including forged ones. Trust results authenticated by your receiving system or the mailbox provider handling your mail. Treat older headers as unverified history unless their source is trusted.
Apache SpamAssassin terminal output showing DKIM_SIGNED and DKIM_INVALID_DKIM rule hits.
Apache SpamAssassin terminal output showing DKIM_SIGNED and DKIM_INVALID_DKIM rule hits.

Handle multiple signatures and truncated messages

One message can carry several DKIM-Signature headers, and each signature is verified independently. A trusted Authentication-Results header can therefore contain both dkim=pass and dkim=fail entries. For DMARC, the useful result is any passing signature that has DMARC alignment with the visible From domain. A failed extra signature does not cancel that DMARC pass. A missing DKIM_VALID_AU hit is not a DMARC verdict; that test also has its own key-size checks.

Result pattern

Interpretation

Next check

Pass and fail signatures
Different signatures had different results
Map each d= and s=
DKIM_VALID without DKIM_VALID_AU
A signature passed, but the AU test did not match
Check DKIM alignment and key-size settings
Large message fails locally
Check whether the scanner received a truncated body
Compare complete raw input
Attachment messages fail
Check for MIME changes or truncation
Inspect the mail path
How to read less obvious DKIM result combinations.
An attachment does not inherently invalidate DKIM. Attachments are MIME body content and are included in the signed body hash. If only messages with attachments fail, check whether the message exceeded a scanner input limit, whether a gateway rewrote the MIME structure, or whether the copy supplied to SpamAssassin was incomplete.
Check for truncated scanner input
SpamAssassin can use verified DKIM results supplied by a trusted calling mail system when only a truncated message is passed for scanning. Inspect __TRUNCATED and __DKIM_DEPENDABLE in debug output and check how the integration supplies those results. This is not the same as trusting an arbitrary Authentication-Results header.

Check the SpamAssassin DKIM verifier

When the same raw email passes at a receiver but fails in a local scan, inspect the verifier before editing the signing setup. Run these checks with the configuration and service account used by the production scanner.
Validate configuration and capture DKIM debug outputbash
spamassassin --lint spamassassin -t -D dkim < message.eml > scanned.eml 2> dkim-debug.log
  1. Confirm that Mail::SpamAssassin::Plugin::DKIM is loaded and that its Mail::DKIM dependency is installed.
  2. Enable network tests and check DNS resolution using the scanner's resolver. The -L or --local option disables network tests.
  3. Check local score overrides. Setting DKIM_VALID to 0 disables that rule and can leave DKIM_INVALID without a validation hit.
  4. Read timeout messages before increasing dkim_timeout. Apache's 4.0.x documentation gives a default of 5 seconds; a timeout leaves scanning without a DKIM result.
Apache's DKIM plugin documentation describes the dependency and timeout behavior. Compare the service configuration with the standalone command's configuration when results differ.

Check the DKIM signature fields

Once the headers confirm a DKIM failure, inspect the relevant DKIM-Signature header. This header tells you the signing domain, selector, canonicalization mode, signed headers, body hash, and signature value. Map those fields to the matching Authentication-Results entry when the message has more than one signature.
Illustrative DKIM-Signature with placeholder valuestext
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=selector1; t=1710000000; h=from:to:subject:date:message-id; bh=abc123base64=; b=def456base64=
  1. The d= tag is the signing domain. It must satisfy the active adkim mode for DKIM to support DMARC.
  2. The s= tag is the selector. Query s._domainkey.d, using the actual s= and d= values in this signature.
  3. The c= tag specifies canonicalization. relaxed/relaxed normalizes defined whitespace and header formatting differences, but substantive body changes still fail.
  4. The h= tag lists signed headers and must include From. Changes to these headers after canonicalization can break verification.
  5. The bh= tag is the body hash. A mismatch means the canonicalized signed body differs from what was signed.
  6. The b= tag is the digital signature, verified against the signed header hash using the public key. A wrong key or altered signed header can cause failure even when the body hash matches.
  7. The a= tag specifies the signing algorithm. Check that the verifier supports it and that it is allowed by current DKIM requirements.
  8. An optional x= tag sets signature expiry. If the reason says expired, check this value and the verifier clock, then send a freshly signed message.
Illustrative DKIM TXT record with an abbreviated keydns
selector1._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."
For a quick DNS-level validation, enter the signing domain and selector in Suped's DKIM checker. That checks whether the public key is published and parseable; it does not verify a specific email signature.

DKIM checker

Check selector records and public key configuration.

?/7tests passed
If the selector was published or rotated recently, compare the authoritative answer with the recursive answer used by the verifier. Cached DNS can retain the prior record until its TTL expires. Keep the old selector available long enough for previously signed mail to finish delivery, and sign new mail with the new selector. A cached missing-record answer can also persist. A long key split across quoted TXT strings is valid when the strings form one record and concatenate without added spaces; separate key records at the same selector are not equivalent.
A clean selector lookup narrows the problem. At that point, focus on the actual message path: where it was signed, what system touched it afterward, and whether the final received copy matches what the signer originally signed.

Troubleshoot in the right order

Work through the evidence in order. Isolate signature verification failures before checking DKIM alignment for DMARC; domain mismatch does not itself invalidate a DKIM signature.
A DKIM troubleshooting flow: raw email, SpamAssassin rule, authentication results, DKIM fields, DNS selector, root cause.
A DKIM troubleshooting flow: raw email, SpamAssassin rule, authentication results, DKIM fields, DNS selector, root cause.
  1. Use the full message source, including untouched headers and body.
  2. Find the trusted Authentication-Results header and each DKIM result.
  3. Record the signing domain, selector, signed headers, and body hash for the failed signature.
  4. Confirm SpamAssassin received the complete message and can run DKIM and DNS tests, or uses verified caller-supplied results.
  5. Confirm the selector has one usable DKIM key record and that the public key matches the signing private key.
  6. Look for footers, tracking rewrites, gateway edits, or MIME changes.
  7. Send a simple message through the same sender and compare results.
If your end symptom is landing in spam despite authentication passing, treat DKIM as only one part of the investigation. Content, complaint rate, sending patterns, and domain reputation still matter.

The most common DKIM failure causes

When SpamAssassin says the DKIM signature exists but no signature is valid, the cause is usually one of a small number of practical issues. Match the exact failure reason to the affected signature and message path before making a change.

Failure

Inspect

Typical fix

Body hash
Content or MIME changed
Sign after final changes
No key
Selector DNS
Publish the TXT record
Wrong key
Signer configuration
Correct or rotate selector
Header change
Signed header list
Stop the rewrite
DNS format
TXT assembly
Fix the record
Truncated input
Scanner integration
Pass complete data or results
DNS timeout or SERVFAIL
Scanner resolver and timeout logs
Restore DNS resolution and retest
Revoked key
Empty p= in the selector record
Publish a new selector and sign with its matching key
Expired signature
x= tag and verifier clock
Correct the clock or send newly signed mail
Disallowed algorithm or short RSA key
a= tag and key size
Use rsa-sha256 with a 2048-bit RSA key
Common DKIM failure causes and where to inspect first.
RFC 8301 prohibits rsa-sha1 and RSA keys shorter than 1024 bits. Use rsa-sha256 with a 2048-bit RSA key for new RSA signing configurations. A revoked key has an empty p= value, so a record can exist in DNS while verification still fails.
A body hash failure usually means the canonicalized message body differs from what was signed. If that is your exact header result, use the body hash verification troubleshooting path before editing DNS. Footer insertion, MIME rewriting, and link decoration after DKIM signing are common causes.
If the result mentions no public key, the selector lookup is the first place to fix. The no key errors pattern usually means the selector in the header does not resolve at the signing domain, the record is under the wrong host name, or the verifier received a stale cached answer.
Do not fix the wrong layer
If a single test message fails DKIM, changing the domain's DKIM record without checking the actual selector, complete scanner input, and message path can break mail that was already passing. Prove the failure layer first.

How DMARC changes the interpretation

DKIM passing is not the same as DMARC passing. DMARC evaluates the visible From domain and the published adkim mode. Relaxed DKIM alignment, the default, requires the passing signing domain and From domain to share the same Organizational Domain. Strict alignment requires an exact domain match. RFC 9989 specifies a DNS Tree Walk for Organizational Domain discovery; receivers using older DMARC implementations can use a public suffix list instead.
A message with multiple DKIM signatures can satisfy DMARC when any passing signature has DMARC alignment. SPF can provide the other DMARC path only when SPF passes for an authenticated domain that has DMARC alignment with the visible From domain under the published aspf mode.
DKIM passes but DMARC fails
  1. No passing signing domain meets DMARC alignment requirements under the active adkim mode.
  2. SPF passed for a domain without DMARC alignment with From.
  3. The receiver applies the policy discovered for the visible From domain.
  4. Configure a DKIM signing domain that satisfies the intended adkim mode.
DKIM fails but DMARC passes
  1. SPF passed using a domain with DMARC alignment to the visible From domain.
  2. That SPF result satisfied DMARC on this delivery.
  3. Forwarded mail often loses SPF, so DKIM still needs a fix.
  4. Repair DKIM instead of relying on SPF as the only path.
This is where DMARC monitoring matters. A one-off SpamAssassin result tells you about one message. Aggregate DMARC reports show which sources repeatedly pass, fail, or use a domain without DMARC alignment.
DMARC record detail view showing SPF, DKIM, DMARC, rDNS diagnostics, and DNS records
Suped's DMARC reporting product groups authentication results by sending source, so you can identify repeated DKIM failures and review the affected signing domains and selectors.
Suped's domain health checker reviews domain-level authentication records. Use the exact d= and s= values for a DKIM selector check.

Find local SpamAssassin DKIM rule definitions

There is no single public explanation for every SpamAssassin test label you will see. The Apache rule files explain the standard rules, but local installations can add rules, change scores, or run plugins in a different configuration. Some results are set by plugin code rather than a plain rule file.
Finding local SpamAssassin rule definitionsbash
grep -R -E 'DKIM_INVALID(_DKIM)?' /usr/share/spamassassin /var/lib/spamassassin /etc/mail/spamassassin
  1. Search the installed and updated rule directories when a report label differs from the default rules.
  2. DKIM_INVALID is built by combining DKIM_SIGNED with the absence of DKIM_VALID.
  3. DKIM checks can come from Perl plugin behavior instead of a simple pattern.
  4. The same rule name can carry a different score in another installation.
Use the score carefully
A public SpamAssassin score report can be useful for fast testing, but it is not the same as a receiver decision. Use it to find obvious authentication issues, then confirm with complete headers, DNS, and aggregate reporting.

What to fix first

The priority depends on what the trusted headers show. Give tiny score changes low priority when at least one DKIM signature passes with DKIM alignment. Fix production sources when DKIM failures are repeated or also cause DMARC failures.
DKIM troubleshooting priority
Treat SpamAssassin points as low priority unless trusted headers show a real authentication failure.
Informational
Low
Rule hit only
Investigate
Medium
Trusted header says DKIM failed
Fix now
High
DKIM failure also breaks DMARC
Monitor
Ongoing
DKIM passes, but source patterns changed
Suped's DMARC reporting product groups aggregate authentication results by sending source so teams can compare production pass rates before and after a fix. Raw messages remain necessary to diagnose the exact signature failure.
Suped workflow
  1. Find sources with repeated DKIM failures or signatures without DMARC alignment.
  2. Connect the issue to the affected source and DNS records.
  3. Watch later aggregate reports to confirm the correction.
  4. Review the same workflow across the domains your team operates.

Views from the trenches

Best practices
Use full raw headers before changing DNS, because partial score screenshots hide context.
Compare SpamAssassin output with trusted Authentication-Results before deciding on a fix.
Check the selector and signing domain together, because one without the other misleads.
Retest with a simple message path after each fix so new edits do not hide the cause.
Common pitfalls
Treating DKIM_SIGNED as a pass causes teams to overlook invalid signatures in raw headers.
Assuming a correct DNS key proves every message is signed correctly wastes troubleshooting time.
Blaming a different envelope domain for DKIM failure confuses SPF with DKIM checks.
Using a public score as a deliverability verdict overstates what SpamAssassin proves.
Expert tips
Search installed SpamAssassin rules when public descriptions are too short to act on.
Use DKIM debug output to separate DNS timeouts and skipped tests from signature failures.
Fix post-signing body edits before rotating keys when the body hash is failing now.
Track aggregate DMARC reports so repeated DKIM failures become issues for a sending source.

Marketer view

Marketer from Email Geeks says public SpamAssassin rule documentation is incomplete, so installed rules and plugin behavior often explain more than the public list.
2024-07-19 - Email Geeks

Marketer view

Marketer from Email Geeks says DKIM_SIGNED confirms a signature header exists, while the DKIM_INVALID_DKIM label in their reported test indicated unsuccessful verification.
2024-07-19 - Email Geeks

Frequently asked questions

No. DKIM_SIGNED means the message has at least one DKIM-Signature header. You still need DKIM_VALID, dkim=pass in trusted Authentication-Results, or another clear verification result to treat a signature as passed.

Apache SpamAssassin's default rule is DKIM_INVALID, which fires when DKIM_SIGNED is present and DKIM_VALID is absent. DKIM_INVALID_DKIM can be a local rule or report-specific label, so check that installation's rule definition.

No. The envelope domain affects SPF and the SPF path for DMARC. A DKIM failure points to signature verification, selector DNS, message modification, or incomplete scanner input. The envelope domain still matters when you evaluate DMARC's SPF alignment path.

SpamAssassin uses weighted scoring. A positive 0.1 adds a small amount to the spam score, while a negative value subtracts from it. DKIM_SIGNED can appear alongside DKIM_VALID on valid mail. Check local weights and investigate repeated failures confirmed in trusted headers.

The attachment itself does not invalidate DKIM. Attachments are part of the MIME body, so a gateway rewrite, post-signing change, or truncated copy supplied to SpamAssassin can make attachment messages fail.

Check the trusted Authentication-Results header and map each result to its DKIM-Signature d= and s= fields. Confirm SpamAssassin received the complete message and can perform DKIM and DNS tests. Then query the matching selector record and inspect post-signing changes.
DMARC monitoring

Start monitoring your DMARC reports today

Suped DMARC platform dashboard
What you'll get with Suped
Real-time DMARC report monitoring and analysis
Automated alerts for authentication failures
Clear recommendations to improve email deliverability
Protection against phishing and domain spoofing