Era Host hosting
EraHost – Free Domain, Cheap Hosting!
Client Area
Support 24/7
Menu

Message has a DKIM or DK signature, not necessarily valid: what it means and how to check DKIM

27 min read
11.09.2026

The line Message has a DKIM or DK signature, not necessarily valid looks like a warning about a broken DKIM signature, but in SpamAssassin it means something different. The DKIM_SIGNED rule only reports that a DKIM or legacy DomainKeys signature was found in the message. It does not say whether the signature passed verification.

That means you should not change DNS, generate a new key, or reconfigure the mail server just because DKIM_SIGNED appears. Check the other verification results first. If DKIM_VALID is present as well, at least one signature has passed verification. Real troubleshooting starts when you see DKIM_INVALID or dkim=fail in the Authentication-Results header.

Short answer: the phrase not necessarily valid means "this particular rule does not verify signature validity," not "SpamAssassin considers the signature invalid."

If DKIM is actually failing, start with the specific message: identify the d= signing domain and s= selector, check the corresponding public key in DNS, then inspect the signing server configuration, and only after that look at intermediate filters, relays, and applications that may have modified the message after it was signed. Do not change DNS blindly: the problem message already contains most of the data needed for troubleshooting.

What does "Message has a DKIM or DK signature, not necessarily valid" mean in SpamAssassin?

DKIM_SIGNED is triggered when SpamAssassin finds a DKIM signature in a message. That is where this particular rule stops. It is not a final verdict saying "DKIM is working" or "DKIM is broken."

A full report might look like this:

 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

The numbers above are only an example. Scores depend on the SpamAssassin ruleset version, local configuration, and the rules enabled on a particular server. A score does not tell you "how valid" a DKIM signature is.

The important part is the combination of rules. In the example above, DKIM_SIGNED means a signature was found. DKIM_VALID means at least one signature passed verification. DKIM_VALID_AU additionally indicates a valid signature from the author's domain. These results do not contradict each other.

This result is different:

DKIM_SIGNED
DKIM_INVALID

Here a signature exists, but SpamAssassin did not confirm a valid DKIM signature. This is where there is actually something to troubleshoot.

DKIM_SIGNED + DKIM_VALID

Normal situation. A DKIM signature was found and successfully verified.

DKIM_SIGNED only

One line is not enough to draw a conclusion. Check the full report and Authentication-Results.

DKIM_SIGNED + DKIM_INVALID

This is a real troubleshooting path: message headers, selector, DNS, key, and mail flow.

Do not judge DKIM validity by the score of the DKIM_SIGNED rule. Even a positive score does not mean SpamAssassin has "penalized" the message for an invalid signature.

If you see DKIM_SIGNED, immediately check the other DKIM_* rules from the same report. If DKIM_VALID is already there, leave DNS alone for now.

Lines such as Similar message reported on pyzor should not be treated as part of the DKIM error either: that is a separate SpamAssassin check.

How do DKIM_SIGNED, DKIM_VALID, and DKIM_INVALID differ?

SpamAssassin separately records the presence of a signature and the result of cryptographic verification. That is why several DKIM-related rules can trigger at the same time, and they should be read as one diagnostic set.

If the same report contains Pyzor scores, do not mix them with DKIM: Pyzor Check serves a different purpose and evaluates the message as an anti-spam signal rather than verifying the DKIM signature.

Rule What it means Does it need fixing? What to check next
DKIM_SIGNED The message contains a DKIM/DK signature No, this is normal by itself DKIM_VALID, DKIM_INVALID
DKIM_VALID At least one DKIM/DK signature passed verification No If necessary, determine which signature passed
DKIM_VALID_AU There is a valid signature from the author's domain No Compare it with the visible From: domain
DKIM_VALID_EF There is a valid signature from the envelope-from domain No Do not confuse this with the final DMARC result
DKIM_INVALID A signature was found, but no valid signature was confirmed Yes, troubleshooting is required Headers, DNS, keys, MTA, and message path

DKIM_SIGNED does not mean DKIM fail

An administrator sees the word SIGNED, then the phrase not necessarily valid, and starts regenerating the key. But if the same report also contains DKIM_VALID, at least one signature has already passed verification. Regenerating the key does not solve anything because the problem has not even been proven yet.

DKIM_VALID means at least one signature is valid

The phrase "at least one" becomes critical when a message contains multiple DKIM-Signature headers. Your own server may sign the message as d=example.com, while an external SMTP relay adds another signature from d=relay.provider.net. If only the second signature passes, DKIM_VALID can still appear.

So "is DKIM_VALID present?" is only the first question. The next one is: "which signature actually passed?"

DKIM_INVALID is the point where you move to the actual message

In SpamAssassin's standard logic, DKIM_INVALID is associated with a situation where a signature is present but a valid DKIM signature has not been confirmed. At that point it makes sense to save the message as an .eml file, extract d= and s=, and check the record for that exact selector.

If SpamAssassin with the DKIM plugin is installed, you can run the saved message in debug mode:

spamassassin -D -t < message.eml 2>&1 | grep -i dkim

Do not stop at one matching line. Look at several lines before and after it: debug output may separately show signature parsing, DNS lookup, and the final verification result.

Where can you see the actual DKIM verification result in message headers?

If SpamAssassin really reports a problem, open the source of the exact message that reached the recipient. You need two headers: DKIM-Signature and Authentication-Results. The first contains the signature parameters; the second contains the verification result produced by the receiving system.

What to look for in DKIM-Signature

A shortened header may look like this:

DKIM-Signature: v=1;
 a=rsa-sha256;
 c=relaxed/relaxed;
 d=example.com;
 s=mail;
 h=from:to:subject:date;
 bh=...;
 b=...

For the next check, the two most important values are d= and s=:

  • d=example.com — the signing domain used to create the signature;
  • s=mail — the selector that determines the DNS name containing the public key.

If DNS looks correct, the other tags become useful as well. c= defines header and body canonicalization, h= lists the signed headers, bh= contains the canonicalized body hash, and b= contains the cryptographic signature itself.

What to look for in Authentication-Results

After successful verification, the receiving server may add:

Authentication-Results: mx.example.net;
 dkim=pass header.d=example.com header.s=mail;
 spf=pass;
 dmarc=pass

If you already have dkim=pass for the expected header.d, there is no reason to fix the DKIM record again just because DKIM_SIGNED appeared.

A failed result may look like this:

Authentication-Results: mx.example.net;
 dkim=fail header.d=example.com header.s=mail

But pass and fail are not the only possible states. That matters when the issue appears intermittently.

dkim=fail, temperror, and permerror are different troubleshooting paths

Result What it means Where to look
dkim=pass The signature passed verification If DMARC still fails, check alignment rather than the DKIM key
dkim=fail Signature verification completed with a negative result Key, body hash, signed headers, and post-signing modifications
dkim=temperror Verification could not complete because of a temporary condition DNS timeout, temporary resolver failure, or another transient problem
dkim=permerror Verification encountered a permanent data or format error Invalid selector record, malformed key, or invalid signature data
dkim=none No suitable DKIM signature was verified Check whether DKIM-Signature exists and where it is supposed to be added

Do not treat temperror by immediately replacing the key. If one DNS query timed out but the same selector resolves normally a minute later, the cause may have been temporary. permerror is different: the same data consistently causes a permanent error and the record or signature needs to be inspected.

A forwarded message may contain several Authentication-Results headers. An intermediate gateway may have checked the message before it was modified, while the final MX checked it afterward. Look at which server added each header and where that server appears in the Received chain.

In a saved .eml file, you can quickly find the relevant lines with:

grep -iE '^(DKIM-Signature|Authentication-Results):' message.eml

If DKIM-Signature is folded across multiple physical lines, a simple grep will show only the first line. For a full analysis, open the message source and inspect the continuation lines together with the header start.

How do you check the DKIM selector and public key in DNS?

When you see dkim=fail, do not look for an arbitrary _domainkey record in the control panel. The selector must come from the specific message you are troubleshooting.

Suppose the signature contains:

d=example.com
s=mail

The DNS record name is then:

mail._domainkey.example.com

Start with:

dig TXT mail._domainkey.example.com

Or use the shorter output:

dig +short TXT mail._domainkey.example.com

The response normally contains a DKIM key record with the public key in p=. The v=DKIM1 tag is commonly present, but its appearance alone does not prove that the key is usable. The key has been found. Now verify that it is the right one.

If dig returns NXDOMAIN or an empty response

First recheck s= and d=. After a migration, a very simple situation can occur: an old selector such as default is still visible in the control panel, while the new MTA is already signing messages with s=mail. The administrator keeps checking a perfectly valid old record even though the message is requesting a different DNS name.

The same logic applies to subdomains: the selector is built relative to the signing domain from d=. A similar setup is covered in the article about DomainKeys for a subdomain.

Check the authoritative DNS servers:

dig NS example.com

Then query the selector directly from one of the authoritative servers:

dig @ns1.example-dns.net TXT mail._domainkey.example.com

If the authoritative server already returns the new record while a public recursive resolver still returns an old state, check TTL and caching. If the record is missing even on the authoritative server, waiting for "DNS propagation" will not help: the zone itself must be fixed first.

If the DKIM selector is configured through CNAME

An external mail provider may not store the public key directly in your domain's zone. Instead, the selector can be delegated through CNAME, for example:

mail._domainkey.example.com. CNAME mail.example.provider.net.

Check it with:

dig CNAME mail._domainkey.example.com

Then query the TXT record at the target name:

dig TXT mail.example.provider.net

Do not try to keep a working CNAME and your own conflicting TXT record at the same DNS name. If the provider manages the selector, the authoritative key data lives behind the CNAME target.

If several TXT records are published for one selector

Two independent DKIM key records under one selector are not redundancy. The verifier needs an unambiguous key for the specific s= value. If the same DNS name returns multiple competing records with different p= values, verification can become invalid or ambiguous.

For key rotation, use a new selector such as mail2026, publish a separate key for it, and switch the signer to the new selector. The old selector can remain temporarily so previously sent messages can still be verified. Do not publish two active public keys under the same name as a form of backup.

An empty p= is not a working public key

A record like:

v=DKIM1; p=

does not mean "DKIM is published but the key is hidden." An empty p= value is used to revoke the key. If current messages are still being signed with that selector, the verifier cannot validate them using a revoked key.

Why a long TXT record may be displayed as several strings

dig may display a long TXT record as several quoted strings:

"v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."
"...AQAB"

This does not mean the key is broken into invalid pieces. A single TXT resource record can contain several string fragments that are concatenated when interpreted. A more serious problem is multiple separate TXT resource records containing competing DKIM keys.

  1. Take d= and s= from the problem message.
  2. Build the s._domainkey.d name.
  3. Query the TXT record.
  4. If there is no TXT record, check CNAME and authoritative DNS.
  5. If multiple records are returned, make sure they are not competing DKIM key records.
  6. Check that p= is not empty.
  7. Then move on to verifying that the DNS public key matches the signer's private key.

DNS is responding. Good. But that is only half of the check.

Why can DKIM fail even when the TXT record exists?

dig finds the selector, p= is populated, but the receiving server still reports dkim=fail. At this point, saving the TXT record again usually does not help. You need to check which private key the MTA is actually using and whether the message is being modified after signing.

Symptom Where to look What to check
No TXT record DNS or wrong selector d=, s=, CNAME, authoritative DNS
TXT exists but dkim=fail Key or message contents Key pair, raw headers, post-signing processing
DKIM passes through one SMTP server but fails through another Different outbound nodes Private key, selector, and configuration on each node
Direct sending passes but website mail fails Application, filter, or relay What modifies the message between the signer and external MX
The verifier reports a body-hash problem Message body was changed Footer, MIME, antivirus, mailing list, relay

The public and private keys may no longer match

After a server reinstall or DKIM key regeneration, you can easily end up with this configuration: DNS still contains public key A, while OpenDKIM, Exim, Rspamd, or another signer is already using private key B. The control panel looks fine and dig works, but the cryptographic pair no longer matches.

A clustered setup can be even more confusing:

DNS:
mail._domainkey.example.com -> public key A

smtp1:
private key A -> DKIM pass

smtp2:
private key B -> DKIM fail

If a load balancer sends mail through both nodes, the error appears random: one message passes, the next one fails. There is no point continuing to troubleshoot the domain's DNS globally. Compare Received headers and identify which outbound node handled each message.

How to test the key when OpenDKIM is used

With OpenDKIM, you can first check whether the selector's public key can be found and parsed correctly:

opendkim-testkey -d example.com -s mail -vvv

When the DNS lookup succeeds, the output normally indicates that the key was retrieved and accepted, for example with key OK. Exact wording depends on the OpenDKIM build and version. A message such as key not secure may refer to DNSSEC and does not by itself mean the public and private keys do not match.

To verify the pair against a local private key, specify the key file:

opendkim-testkey \
 -d example.com \
 -s mail \
 -k /etc/opendkim/keys/example.com/mail.private \
 -vvv

The path above is only an example. On a real server it depends on the OpenDKIM configuration. Do not copy it blindly: first determine which KeyTable or other configuration entry is actually used for example.com.

If the test cannot find the selector, return to DNS. If the DNS key is readable but the key-pair test fails, look for the wrong private key, an old configuration, or a different signer. The problem area is already much narrower.

The message may have been modified after signing

DKIM calculates a hash of the canonicalized message body and signs the headers listed in h=. If another component changes signed data after the signer has run, the recipient verifies different data from what the sender originally signed.

Possible causes include:

  • adding a footer or disclaimer;
  • rewriting Subject;
  • changing the MIME structure;
  • re-encoding or filtering message content;
  • an antivirus or anti-spam gateway;
  • an SMTP relay that rewrites headers;
  • a mailing list that adds a subject prefix or text to the body.

Not every visible modification necessarily breaks DKIM. It depends on simple/relaxed canonicalization and on which headers are listed in h=. A simple diff can help find changes, but it does not replace a DKIM verifier.

Body-hash errors and signature errors point in different directions

If the verifier explicitly reports a body-hash mismatch, first look for body modifications: footer, MIME processing, re-encoding, or a filter after the signer. If the body hash passes but the cryptographic signature still fails, signed headers, a mismatched public/private key, or a damaged DKIM-Signature become stronger suspects.

This distinction saves time. There is no reason to spend an hour on DNS when the message was already modified later in the delivery chain.

How do you find out what modified the message after DKIM signing?

When a minimal message sent directly through the MTA gets dkim=pass, while a message from the website, CRM, or mailing system gets dkim=fail, the signer has already shown that it can generate a working signature. Look for the difference between the two routes.

Reconstruct the mail flow step by step:

web application
local MTA
content filter
DKIM signer
SMTP relay
recipient MX

If a component after the DKIM signer modifies the message, it becomes the first suspect. A typical example: the server signs the message and a gateway then adds a corporate disclaimer to the body. DNS can be perfect. The message was simply changed after signing.

Signing should happen after predictable modifications

Components that intentionally change a message should ideally run before DKIM signing. If the application builds MIME, a filter adds service headers, and a gateway inserts a footer, the signature should be created after the changes that are expected to be part of the final signed message.

This does not mean the DKIM signer must literally be the last process before the network connection. Headers that are not covered by the signature can still be added afterward without invalidating it. The critical point is not to change signed headers or the canonicalized body in a way that changes the verified data.

Compare two copies of the same message

For a complicated mail chain, comparing a message immediately after signing with the delivered copy is often faster than reviewing the configuration of every filter one by one.

  1. Compare d= and s=.
  2. Check h= and the list of signed headers.
  3. Compare From, Subject, Date, and other headers listed in h=.
  4. Compare the body and MIME parts.
  5. Check whether a footer or disclaimer appeared.
  6. Compare the Received chain.
  7. Repeat the test while temporarily bypassing the suspected filter.

Useful headers:

grep -i '^DKIM-Signature:' message.eml
grep -i '^Authentication-Results:' message.eml
grep -i '^Received:' message.eml

If direct SMTP consistently passes while the PHP application fails through the full route, do not change the selector at random. Compare what happens to the two messages after the signing point.

A strong troubleshooting split is direct SMTP pass + production fail. It usually tells you more about the real problem than another random DNS change.

What should you do if a message has multiple DKIM-Signature headers?

A message source can contain two signatures at the same time, for example one from example.com and another from relay.provider.net. SpamAssassin may still show DKIM_VALID. The question is no longer "is DKIM valid at all?" but "which signature passed?"

Suppose the message contains:

DKIM-Signature: v=1; d=example.com; s=mail; ...
DKIM-Signature: v=1; d=relay.provider.net; s=smtp1; ...

And the receiving system records:

Authentication-Results: mx.example.net;
 dkim=fail header.d=example.com header.s=mail;
 dkim=pass header.d=relay.provider.net header.s=smtp1

A general conclusion that "DKIM is valid" may technically be possible because one signature did pass. But the signature from example.com is still broken.

Signature d= s= Result Relation to From
1 example.com mail fail Sender's own domain
2 relay.provider.net smtp1 pass SMTP provider signature

How to match Authentication-Results to a specific signature

Do not look only at dkim=pass. Check the parameters next to the result, especially the signing domain and selector. Many receiving systems include header.d and header.s, which lets you match the result to a specific DKIM-Signature.

If a message has four signatures, write them down separately:

1. d=example.com          s=mail
2. d=relay.provider.net   s=smtp1
3. d=newsletter.net       s=mta2
4. d=example.org          s=default

Then match each verifier result. Otherwise it is easy to troubleshoot the wrong DKIM signature.

Your own signature fails while the SMTP provider's signature passes

Such a message should not automatically be considered fully fixed. The external relay has validated its own signature, but d=example.com is still failing. If your own domain is supposed to satisfy DMARC alignment, the problem remains.

Check separately:

  • which signature belongs to the visible From: domain;
  • which signature was added first;
  • which server added the second signature;
  • which signature received dkim=pass;
  • which valid signature is aligned for DMARC.

One signature can break while another remains valid

If an external relay signs the final, already-modified version of the message, its signature may pass even though an earlier signature from your own MTA was broken by intermediate processing. That is a useful clue: look for modifications between the two signing points.

Two DKIM signatures are not simply "two backup attempts." They can reflect different stages of the mail route.

Why does DKIM_VALID not guarantee a DMARC pass?

SpamAssassin shows DKIM_VALID, Authentication-Results contains dkim=pass, but DMARC still says dmarc=fail. In that situation, a new DKIM key may not be needed at all. Check alignment between the signing domain and the visible From: domain first.

For example:

From: billing@example.com

DKIM-Signature:
 d=mailer.example.net;
 s=outbound;

The d=mailer.example.net signature may be cryptographically perfect. But DMARC cares not only about DKIM validity, but also about how d= relates to the domain in From:.

How relaxed DKIM alignment works

Suppose you have:

From: user@example.com
DKIM d=mailer.example.com

DMARC:
v=DMARC1; p=quarantine; adkim=r

With relaxed alignment, the domains can be aligned because mailer.example.com and example.com belong to the same organizational domain. adkim=r selects relaxed alignment and is also the default when a stricter mode is not explicitly configured.

What changes with adkim=s

Using the same domains:

From: user@example.com
DKIM d=mailer.example.com

DMARC:
v=DMARC1; p=quarantine; adkim=s

With strict alignment, there is no exact match: mailer.example.com differs from example.com. DKIM itself may still be pass, but that signature does not satisfy strict DKIM alignment for DMARC.

DKIM Alignment What it means for DMARC
pass aligned DKIM can satisfy DMARC
pass not aligned DKIM is cryptographically valid, but this signature does not satisfy the DKIM branch of DMARC
fail not applicable This signature does not help DMARC
Multiple DKIM signatures, one pass and aligned aligned That specific valid signature is the one that matters

After seeing DKIM_VALID, ask one more question: which d= actually passed? Compare it with From:, then check adkim= in the DMARC policy.

SPF can also satisfy DMARC only when its identity is properly aligned. The combination "SPF pass + DKIM pass" alone does not automatically prove dmarc=pass.

What is the right order for troubleshooting DKIM_INVALID on a mail server?

When DKIM_INVALID or dkim=fail is confirmed, the fastest approach is to work outward from the specific message. Do not start by generating a new key. First locate the layer where verification breaks.

  1. Save the delivered message as .eml. You need the copy that actually reached the recipient.
  2. Extract DKIM-Signature. Write down d= and s=.
  3. Check Authentication-Results. Identify pass, fail, temperror, permerror, or none.
  4. Build the selector name. Format: s._domainkey.d.
  5. Check TXT and CNAME. Do not rely only on what the control panel displays.
  6. Check authoritative DNS. This separates the actual zone state from resolver caching.
  7. Verify the key pair. With OpenDKIM, you can use opendkim-testkey.
  8. Send a minimal message directly through the same MTA.
  9. If direct SMTP passes, investigate post-signing processing.
  10. If direct SMTP also fails, investigate the signer, key, and MTA.
  11. With multiple signatures, determine which specific signature fails.
  12. After getting dkim=pass, check DMARC alignment separately.

Quick decision tree

DKIM_SIGNED
|
|-- DKIM_VALID present
|   |
|   |-- DMARC pass
|   |      no DKIM repair needed
|   |
|   `-- DMARC fail
|          check d=, From, and alignment
|
`-- no DKIM_VALID / DKIM_INVALID / dkim=fail
    |
    |-- selector not found
    |      DNS / CNAME / authoritative zone
    |
    |-- key found, testkey fails
    |      public/private key / selector / signer
    |
    |-- direct SMTP pass
    |      post-signing processing / relay / application
    |
    `-- direct SMTP fail
           signer / private key / MTA configuration

This tree does not replace troubleshooting, but it helps avoid the chaotic "let's regenerate DKIM and see what happens" approach.

Useful server-side commands

DNS:

dig +short TXT mail._domainkey.example.com
dig CNAME mail._domainkey.example.com
dig NS example.com

Headers from a saved message:

grep -iE '^(DKIM-Signature|Authentication-Results|Received):' message.eml

SpamAssassin:

spamassassin -D -t < message.eml 2>&1 | grep -i dkim

OpenDKIM:

opendkim-testkey -d example.com -s mail -vvv

With a local private key:

opendkim-testkey \
 -d example.com \
 -s mail \
 -k /etc/opendkim/keys/example.com/mail.private \
 -vvv

Logs for a separate OpenDKIM service under systemd:

journalctl -u opendkim

Or recent events:

journalctl -u opendkim --since "30 minutes ago"

Service names and log locations depend on the system. On one server the relevant events may be in /var/log/mail.log, on another in /var/log/maillog, and on a third only in journald.

What to look for in DKIM component logs

Do not depend on one exact message string: wording varies across versions and implementations. Look for events related to:

  • bad signature or signature verification failure;
  • key retrieval failed — the key could not be retrieved;
  • no key or a missing selector;
  • failure to read the private key;
  • SigningTable/KeyTable mismatch;
  • no signing rule for the required domain.

For example, if the DNS selector exists and opendkim-testkey can retrieve it, while the mail log reports a failure to read the local private key, the problem is no longer in public DNS.

What to do with dkim=temperror

temperror is a separate path. Check whether the selector resolves consistently through multiple resolvers, whether timeouts occur, and whether authoritative DNS is reachable:

dig TXT mail._domainkey.example.com
dig @ns1.example-dns.net TXT mail._domainkey.example.com

If the record is correct and repeatedly resolves normally, while the temporary error happened only once, do not rush to replace the key. A cryptographic failure and a temporary inability to retrieve the DNS key are different problems.

DNS key found, opendkim-testkey OK, but the message still fails

This is an important split. The public key is published, the selector exists, and the local test succeeds. The next suspect is the actual message or the real delivery path.

Check:

  • whether the delivered message contains the same selector you tested;
  • whether it was sent by the expected server;
  • whether another outbound node uses a different private key;
  • whether the body changes after signing;
  • whether headers listed in h= are rewritten;
  • whether a downstream relay performs additional processing.

The key works. Continue down the mail flow.

One outbound node passes, another fails

If one SMTP server signs messages correctly while another does not, there is no need to rebuild DNS for the whole domain. Compare the server shown in Received with the local DKIM configuration on both nodes.

Check whether:

  • the same selector is used;
  • the same private key is installed;
  • SigningTable/KeyTable are identical;
  • the required key file exists on both servers;
  • an old configuration remained after migration.

Direct SMTP passes, but PHP or CRM mail fails

If a message sent directly through the MTA gets dkim=pass, while a message generated by the application gets fail, the signer and DNS are already partly cleared. Compare the two routes: additional filters, relays, MIME changes, footers, subject rewriting, or a second signing stage.

This is one of the most useful DKIM troubleshooting tests because it immediately separates "the server signs incorrectly" from "the message is broken later in the route."

How do you verify that DKIM is really fixed?

After changing DNS or signer configuration, send a new message through the same production route that previously failed. An old .eml file remains an old test sample and does not prove that the server is currently generating messages correctly.

  • A new message was sent through the same website, CRM, application, or SMTP route.
  • The new message contains DKIM-Signature.
  • d= contains the expected signing domain.
  • s= contains the current selector.
  • s._domainkey.d resolves correctly in public DNS or through the expected CNAME.
  • Only one unambiguous active key is published for the selector, and p= is not empty.
  • If the local key pair was tested, testkey passes.
  • The required signature gets dkim=pass at the final recipient.
  • SpamAssassin does not report DKIM_INVALID for the message.
  • DKIM_SIGNED together with DKIM_VALID is recognized as a normal result.
  • With multiple signatures, you know which exact signature passed.
  • If DMARC matters, alignment between d= and the From: domain has been checked.
  • The final dmarc=pass result or the reason for dmarc=fail has been verified.

It is especially useful to test two new messages: one minimal message through the MTA and one real message from the production application. If both get the same dkim=pass, you have verified not only the selector and key but also the production mail flow.

Final criterion: a new message follows the same route as real website mail and the final independent recipient reports dkim=pass for the expected signature.

Even then, DKIM does not guarantee inbox placement. A successful signature solves a specific authentication and integrity problem, while deliverability also depends on SPF, DMARC, sender reputation, message content, and the receiving system's filtering rules. Email spam protection is a separate layer: it does not replace DKIM and should not be confused with signature verification.

So the line Message has a DKIM or DK signature, not necessarily valid does not require a fix by itself. First determine whether there is a real failure. If there is, follow the evidence in the message: d=, s=, Authentication-Results, DNS key, signer, and then post-signing processing. This is usually much faster than regenerating keys and changing DNS in the hope of accidentally hitting the cause.

Frequently asked questions
No. DKIM_SIGNED only means a DKIM or DK signature is present. Check DKIM_VALID, DKIM_INVALID, and Authentication-Results to determine whether it passed.
That is normal. DKIM_SIGNED records the presence of a signature, while DKIM_VALID confirms that at least one signature passed verification.
A signature was found, but a valid DKIM signature was not confirmed. Check d=, s=, the DNS selector, the key pair, and any message changes after signing.
fail is a negative verification result, temperror is a temporary problem such as a DNS failure, and permerror is a persistent data, record, or signature-format error.
Yes. The public key may not match the private key, the wrong selector may be used, or the message may have been modified after DKIM signing.
Yes. One signature can pass while another fails. Match each result to its specific header.d and header.s values.
DMARC requires not only dkim=pass but also alignment between the signing domain in d= and the visible From domain. With adkim=s, an exact domain match is required.
Related articles
"Message has a DKIM or DK signature, not necessarily valid" — Explanation and Fixes
Message has a DKIM or DK signature, not necessarily valid
DKIM=Temperror: No Key for Signature