DKIM no key for signature means the selector is missing
DKIM no key for signature means the selector is missing
“No key for signature” means a receiver took the d= and s= tags from your DKIM signature, built the DNS name s._domainkey.d, asked for the public key at that name, and got nothing back. The signature is on the message; the record it points to isn’t in your zone. Either it was never published, or someone removed it while mail signed with it was still moving. The fix is one DNS record, and the exact name of that record is sitting in the header of any message the affected system sends.
A signature that can’t be verified counts as no DKIM at all. DMARC then falls back to SPF alone, and SPF breaks the moment a message is forwarded, so mail that passed for years starts failing on paths you can’t see. Full authentication is rarer than it looks: 7,862,126 of the 316,600,902 graded domains in the September 2026 census complete SPF, DKIM and DMARC together. The DKIM pillar explains how the signature and the record fit together; this page is about the record that isn’t there.
Temperror or permerror: which one you have
The wording lands in Authentication-Results headers and in DMARC aggregate reports. Receivers phrase it slightly differently, and two strings matter.
dkim=temperror (no key for signature) means the DNS query failed or timed out. The receiver couldn’t get an answer at all, so it can’t say whether the record exists. A later retry can pass.
dkim=permerror (no key for signature) means DNS answered, and the answer was that no such record exists. The selector is absent, and it stays absent until you publish it.
Read the label with some scepticism. A temperror that repeats across days and across several receivers is treated as a missing record whatever the string says, because a resolver that can’t find the name will sometimes report a lookup failure instead of an empty answer. Run the dig below and trust what the zone serves.
If the record exists and the signature still fails, with a body hash mismatch or a mangled key, that’s a different problem with a different fix. This page covers the missing record only.
Read the selector off a real message
The header tells you which selector the signer uses today, and that can differ from what the provider’s documentation or the runbook from the last migration says.
- Send a message from the affected system to a mailbox you control.
- Open the raw source: “Show original” in Gmail, “View message source” in Outlook.
- Find the
DKIM-Signature:header and read two tags.s=is the selector andd=is the signing domain. A typical line looks likeDKIM-Signature: v=1; a=rsa-sha256; d=yourdomain.com; s=mail2026; ... - Put them together as
s._domainkey.d. For that header, the record the receiver asks for ismail2026._domainkey.yourdomain.com. - Repeat for each sending system. One message can carry several DKIM signatures, from the mailbox provider, a newsletter tool and a helpdesk, each with its own
s=/d=pair and its own record. Fix the one that’s failing, and note itsd=: only a signature whosed=matches the From domain helps DMARC.
Now query the name yourself. For a selector published as a TXT record, run dig TXT selector._domainkey.yourdomain.com +short. For one delegated through a CNAME, run dig CNAME selector._domainkey.yourdomain.com +short, replacing selector with the s= value you read.
Run both from a machine off your own network; a phone on mobile data will do. The DNS panel showing a record proves nothing about what the zone serves, because the panel is a database view and the authoritative servers are what receivers ask. An empty answer from outside means the error is real for every receiver.
If you can’t send a test message from the affected system, or the header carries a selector you don’t recognise, find your DKIM selector walks through the other ways to recover it.
Why the record is missing
There are four causes. Check them in this order.
It was never published
The signer was switched on, or defaulted on, with a selector nobody added to DNS. New tools and mail gateways start signing the moment they’re enabled, and the setup screen that showed the record to publish got closed before anyone copied it. A permerror on the first day a system sends is this cause.
It was deleted mid-rotation
Someone tidied away the old selector while messages signed with it were still in transit. That mail already carries s=old, and a signature is verified again whenever the message moves: a retry queue picks it up hours later, a forwarding rule sends a copy on days later, and each of those verifications queries old._domainkey and finds nothing. Removing the record breaks that mail retroactively, and the errors arrive after the change looked finished.
The DNS UI mangled a CNAME target
Many providers delegate DKIM through a CNAME, so s1._domainkey.yourdomain.com points at s1.domainkey.u123.esp.com. Some DNS panels append your zone to a target entered without a trailing dot, and the record gets stored as s1.domainkey.u123.esp.com.yourdomain.com, which resolves to nothing. The dig CNAME output shows the stored target verbatim; compare it character by character with what the provider asked for. This is the cause when the provider’s own checker says DKIM is configured and receivers still report no key.
The provider rotated and your zone didn’t
A provider key pasted into DNS as a static TXT record is orphaned the first time the provider rotates. The signer moves to a new selector on their schedule, and nobody published it on yours, so the error appears weeks or months after a setup that worked. Across the 75,823,110 domains where the September 2026 census could run the DKIM check, 37,999,462 (50.1%) presented a discoverable key at scan time.
Publish the selector the signer uses
Publish the s= value from the header, taken from the provider’s admin console, at exactly s._domainkey.yourdomain.com. If an old runbook names a different selector, the runbook is out of date; the header is what receivers see.
Where the provider offers CNAME delegation, use it instead of pasting a TXT key. The key then lives in the provider’s zone and they rotate it there, so the fourth cause can’t reach you again and the rotation runbook below runs on their side without you touching DNS. Enter the CNAME target with care and check the stored value afterwards, because the mangled-target cause lives on exactly this step.
Verify from outside with dig before you tell anyone it’s fixed. Resolvers that cached the empty answer keep it until its TTL runs out, so a query that returns the key from one place and nothing from another is normal for a short while.
Then re-send the test message and open its source. Authentication-Results should now read dkim=pass for your selector. A passing signature whose d= doesn’t match the From domain still fails DMARC, so check alignment while the header is open; the DMARC pillar covers alignment and how to read the aggregate reports you’ll need for the next section.
Rotate without producing the error again
Rotation is where working setups break, because the natural tidy-up, removing the old key once the new one works, is the second cause above. A selector is retired by draining. Each step below has a gate, and you move on only when the gate is met.
| Step | What you do | Move on when |
|---|---|---|
| 1. Add | Publish the new selector (s2._domainkey...) alongside the old one | dig from outside confirms it resolves |
| 2. Switch | Point the signer at the new selector | A test message shows s=s2 and dkim=pass |
| 3. Wait | Leave the old selector published while in-flight, queued and forwarded traffic drains | At least 7 days have passed, and the old selector has stopped appearing in your DMARC aggregate reports |
| 4. Retire | Remove the old key or, better, republish it with an empty p= tag | The old selector stays absent from the reports afterwards |
The empty p= tag is the better ending. A receiver that still meets an old signature gets a definite answer, a withdrawn key, instead of finding no record at the name, and the difference shows up in how it reports the result back to you.
With CNAME delegation the provider runs this same runbook inside their own zone, on their own schedule, and you don’t see it happen. That is the strongest practical reason to delegate wherever a provider allows it.
Once the selector resolves and the test message passes, run the free scan: it reads your zone the way a receiver does and shows whether the selector answers, whether a CNAME target got mangled, and what else in your SPF and DMARC still needs attention.
Figures as of 5 September 2026, from the September 2026 edition of the defaults.exposed census. Census numbers move every month; the current values are on the census data page.