You added the custom sending domain at your email provider an hour ago. The dashboard still says DKIM “pending”. You pasted the records exactly as shown. Your boss wants to know why signup emails aren’t leaving from the company domain yet, and “DNS takes time” is not an answer you can defend without evidence.

Run dig +short TXT <selector>._domainkey.example.com and dig +short CNAME <selector>._domainkey.example.com. An answer shows the name resolves; check the value next. Empty from your own resolver means the name is missing there, so confirm against the authoritative server (below) before changing anything.

What DNS name does a DKIM selector use?

Every DKIM signature carries two tags: d= (the signing domain) and s= (the selector). A verifier takes both and builds one DNS name: the selector, then _domainkey, then the domain. With s=foo.bar and d=example.com, the lookup is for foo.bar._domainkey.example.com. Periods inside a selector are label separators, so a dotted selector is just a deeper name.

Your provider gives you the selector and the record type. Whatever it gives you, the name the world queries is:

<selector>._domainkey.example.com

Publish at any other name and the verifier never sees it.

How do I check a DKIM record with dig?

Check both types. It costs nothing:

dig +short TXT <selector>._domainkey.example.com
dig +short CNAME <selector>._domainkey.example.com
  • A TXT answer starting v=DKIM1; with a p= value: the key is published directly.
  • A CNAME answer pointing at a provider hostname: the provider hosts the key. dig TXT on that name prints the CNAME target line first, then the provider’s TXT.
  • Empty on both: nothing is published at that name.

An empty answer from your own resolver alone proves nothing, so test against the authoritative server before editing anything. Your resolver may still hold an old “does not exist” answer from before you added the record.

dig +short NS example.com
dig +short TXT <selector>._domainkey.example.com @<one-of-those-nameservers>

If the authoritative server answers and your normal resolver does not, the record is fine and you are waiting on caches. If the provider says DKIM is not verified but dig returns the key, compare the p= value with the one the provider shows, then click verify again. If the authoritative server is empty too, fix the record.

Why is my DKIM record still pending or not found?

The DNS host appended your domain twice. Many panels add the zone name for you, so typing the full name publishes <selector>._domainkey.example.com.example.com. Confirm by running dig on that doubled name. If it answers, re-enter only <selector>._domainkey. Some panels treat a trailing dot as a fully qualified name. The pre-launch DKIM checklist walks through the copy-paste side.

The value is mangled. It must start v=DKIM1 and contain the full p= key. A 2048-bit key is longer than one 255-byte DNS string, so dig shows several quoted chunks. That is normal: the verifier concatenates them with no whitespace. Literal quotes pasted into a host that adds its own, or a missing chunk, are not.

CNAME vs TXT. Publish the type your provider specifies. DNS allows a CNAME only on a name that holds no other record types (RFC 2181 §10.1), so a leftover TXT blocks the CNAME your provider wants. Delete the old one first. Keep one TXT record per selector: more than one gives undefined results.

The record is on the wrong domain. If you configured send.example.com at the provider, the record belongs under <selector>._domainkey.send.example.com, not under the root domain. Read the d= your provider will sign with and publish under exactly that domain. Which one to choose in the first place is covered in root domain vs subdomain for app email.

How to confirm DKIM from the email headers

DNS can look right while mail is still unsigned or signed by the wrong domain. Send a test message to a mailbox you control, open the raw source and find two headers.

DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=<selector>; ...
Authentication-Results: mx.example.org;
  dkim=pass header.d=example.com header.s=<selector>;
  dmarc=pass header.from=example.com

d= and s= in the signature are the two halves of the name you queried. In Authentication-Results, header.d is the d= tag from the signature. If the s= in the header differs from the selector in your DNS, the provider signs with a different selector than the one you published.

  • dkim=none: the message carried no signature. RFC 8601 defines it as “The message was not signed.” DNS is not the cause; the provider is not signing this mail yet, for example because the domain is not verified yet.
  • dkim=pass with header.d= your provider’s own domain, and dmarc=fail: the signature is valid but signs for the provider, not you. Under the default relaxed alignment, DMARC requires the signing domain to share an Organizational Domain with the From domain, and a vendor’s d= never does. Custom-domain DKIM is not active yet, even though the mail looks signed. Providers typically sign with your domain once it is verified. The longer story is in what DMARC alignment means.
  • A DKIM failure with d=example.com: the signature names your domain but the key lookup or verification failed. Go back to dig with the s= value from this exact header.

Old messages keep their old headers, so send a fresh test after each DNS change. Once yours passes, every other tool that sends as your domain still needs checking: DMARC Guardian reads the aggregate reports receivers send you, and on trial and paid plans its Senders tab lists each sending source with an alignment status, volume and pass rate over 30 days, and by default shows only the senders that need a decision (failing alignment, or a known provider you haven’t confirmed).

See which senders fail DMARC alignment, without opening headers one by one