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 (DomainKeys Identified Mail) signature, built the DNS (Domain Name System) 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 (Domain-based Message Authentication, Reporting and Conformance) then falls back to SPF (Sender Policy Framework) 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: 8,262,372 of the 332,492,319 graded domains in the October 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 (Text) record, run dig TXT selector._domainkey.yourdomain.com +short. For one delegated through a CNAME (Canonical Name), 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 trailing dot is why the same pasted value works in one panel and breaks in the next. A trailing dot marks a name as absolute, which tells the panel to stop appending your zone. Some panels require it, some add it for you, and some reject it as invalid and handle absoluteness on their own. If the stored target came back with your zone on the end, re-enter the value with the dot. If the panel rejects the dot, re-enter it without one and read the stored value again. Test with dig after saving; the panel’s own display of the record doesn’t count as a test.
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 76,563,365 domains where the census could run the DKIM check, 38,666,798 (50.5%) 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 happens at 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 (Time to Live) 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.
Switching email tools without breaking DKIM
Moving company sending from one tool to another is a rotation across two providers, and it breaks in the same two ways: the panel stores a mangled target for the new tool’s selector, or the old tool’s selectors come down while mail it signed is still draining. Both tools’ selectors can stay published together, because each selector is its own DNS name under _domainkey and a receiver reads whichever one the signature names. Keeping the old ones up through the overlap costs nothing.
If the move also changed nameservers, the corrected records can exist at the new set while receivers are still querying the old one. Run dig +short NS yourdomain.com, then repeat each check with @<nameserver> on the end, once for each server listed, against the old set and the new one. A nameserver change at the registrar can take a day or two to reach every resolver.
Run the cutover in this order, so the checks that matter happen before any real message moves.
- Add the new tool’s DKIM CNAMEs from its admin console, and its bounce-domain records at the same time, since the bounce domain is what the tool’s SPF is judged on. Move on when
digfrom outside shows each stored target exactly as the tool asked for it, with no zone on the end. - Complete the tool’s own verification step. Move on when the tool reports verified and
dig TXTon each selector returns a key. A correct CNAME with an empty TXT answer means the delegation is unfinished on the provider’s side, and your DNS needs no change. - Wait out the TTL of any record you replaced before you believe a test result, and allow a day or two on top if nameservers changed.
- Send a test through the new tool to a mailbox you control. Move on when
Authentication-Resultsshowsdkim=passwithheader.d=your domain. A pass under the tool’s default signing domain does nothing for DMARC alignment. Until that line appears, no real mail goes through the new tool. - On switch day, move real traffic and touch nothing belonging to the old tool: leave its selectors, its CNAMEs and its account alive. Move on when the new tool’s mail passes at real receivers and the old tool keeps passing for anything still flowing through it.
- Watch your DMARC aggregate reports. Move on when the old tool’s selectors have been absent from them for at least 7 days.
- Retire the old tool’s records and account deliberately, then run the free scan.
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 from the defaults.exposed census, data as of 12 October 2026. Census numbers move every month; the current values are on the census data page.