Skip to content

DKIM Record Checker

How the checker finds every DKIM key a domain publishes without asking for a selector, every rule it applies to a key record, what each finding means for mail delivery, and how to fix and verify each one.

Open Markdown

The tool page is tamperbox.dev/dkim-checker. It opens on a live check of tamperbox.dev; replace that domain to inspect your own. This page is the long version: how discovery works, every rule applied to a key record, what each finding means, and how to fix and verify each one.

Where processing happens: a domain or a message header is sent to the Tamperbox server, which asks public DNS once per selector and returns the records. A pasted key record is decoded and measured in your browser and never uploaded. Nothing is stored.

DKIM lets a receiver check that a message was signed by the domain that claims to have sent it. The signature is in the message; the public key that verifies it is in DNS, under a name called a selector: <selector>._domainkey.<domain>. The tool answers:

  1. Which keys does this domain publish? Under the selectors mail services commonly use.
  2. Is the inspected key usable? Readable, not revoked, not in testing mode, strong enough.
  3. Which key signed this message? When you paste the message’s DKIM-Signature header.
  4. Does DNS hold the key my mail service thinks it does? By comparing the SHA-256 fingerprint.

It does not verify a message. For that you need the signature, the signed headers and the body: use the email header analyzer.

example.com. When you stop typing, the server probes the 24 common selectors, five lookups at a time. The page inspects the strongest key it finds and lists the rest under “Keys this domain publishes”; click any of them to inspect it.

The DKIM-Signature header of a sent message

Section titled “The DKIM-Signature header of a sent message”

Paste the header line from a message the domain sent. The page reads its d= tag (the signing domain) and s= tag (the selector), looks up exactly that key, and still probes the common selectors so you see the rest. This is the only way to be sure which key a message used.

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

Where to find it: Gmail, open the message, the three-dot menu, “Show original”; Outlook on the web, the three-dot menu, “View message source”; Apple Mail, View, Message, All Headers. Copy the DKIM-Signature: line, including its continuation lines.

selector1._domainkey.example.com inspects that one key, for people who already know the selector.

Paste the TXT record itself, v=DKIM1; k=rsa; p=…, with or without the quotes DNS tools print. It is read in the browser and shown as “Pasted record”: the tool cannot know which selector it belongs to, so the verdict is about the key alone.

Drop a .txt file anywhere on the page, or use Open file. It is read in the browser.

The verdict is about the inspected key: its type and length, and whether it is valid, revoked, in testing mode or broken. The line under it says where the key was published and, for a pasted header, that it is the key named in the message. The chips repeat the key’s state, then one chip per other key found, each a button that scrolls to the list.

Everything found on the inspected key, worst first, and one entry per other key the domain publishes, so a weak or testing-mode second key is never hidden by a strong first one. The finding reference lists them all.

The inspected key as rows: type, length measured from the key bytes, public exponent, allowed hashes, and the SHA-256 fingerprint of the key bytes in groups of eight hex characters. Compare the fingerprint with the one your mail service shows to confirm that DNS holds the key you expect.

One row per selector that answered, with the key’s status and length; the inspected one is marked. Under the rows, the selectors with no key, and the count probed. “Probe again” repeats the lookups, for a temporary DNS failure or a record you just published.

Every tag in the inspected record with its meaning: v, k, p, h, t, s, n. Unknown tags are listed and marked as ignored by receivers.

History logs every Break it and Heal it change with Revert and Reset input. Heal it offers the repairs the tool found: remove the testing flag, allow sha256, set the key type to RSA, correct the version tag, or restore the input before a break. Take it further carries the domain to the DMARC checker, the DANE checker and the DNSSEC checker.

The server only answers DNS questions. Every rule below runs in your browser on the TXT text that comes back, or on the record you pasted, so a looked-up key and a pasted key are judged by the same code.

DNS has no way to list a domain’s selectors. A key lives at <selector>._domainkey.<domain> (RFC 6376, Section 3.6.2.1), and selectors are free-form names chosen by the signer (Section 3.1). The probe list is a Tamperbox choice, not an RFC rule. The tool probes these 24 names, which cover the common mail services:

Selector Used by
google Google Workspace
20230601, 20221208, 20210112 Google’s own domains, rotated by date
selector1, selector2 Microsoft 365 (published as CNAME aliases)
k1, k2, k3 Mailchimp, Mandrill
s1, s2 SendGrid
default, dkim, mail, smtp Self-hosted servers, OpenDKIM defaults
mandrill Mandrill
mxvault MXroute and similar
zendesk1, zendesk2 Zendesk
pm Postmark
fm1, fm2 Fastmail
protonmail Proton
everlytickey1 Everlytic

Lookups run five at a time. Each selector found gets a row with its key type, length and flags. A selector whose lookup failed (not “no record”, but no answer) is counted separately, so a temporary DNS error is never reported as a missing key. This follows the split in RFC 6376, Section 6.1.2, where a query that “fails to respond” is a TEMPFAIL and a missing record is a PERMFAIL. When every lookup fails the page reports an error, not a domain without keys.

The server queries public DNS and follows CNAME aliases, so keys that a mail service hosts on its own zone through a CNAME (Microsoft 365, Amazon SES) are found. A TXT record split into several quoted strings is joined before it is read, as Section 3.6.2.2 requires: “Strings in a TXT RR MUST be concatenated together before use with no intervening whitespace.”

With no selector named, the page inspects the best key found: a passing key before a key to check, a non-revoked key before a revoked one, a longer key before a shorter one. With a pasted header or a key by name, it inspects that key. Clicking a row in the list inspects that key instead. This ordering is a Tamperbox choice; no RFC ranks keys.

  • When five or more selectors answer and every answer is the same text, the page reports a wildcard, *._domainkey.example.com, as one key, not 24. A wildcard with an empty p= is the usual way to say “this domain signs no mail”: a CHECK, with the explanation. The five-answer threshold is a Tamperbox heuristic.
  • A selector with two or more TXT records is FAIL, “Two or more records”. RFC 6376, Section 3.6.2.2: “TXT RRs MUST be unique for a particular selector name; that is, if there are multiple records in an RRset, the results are undefined.” The usual cause is a rotated key added without removing the old one. The tool counts every TXT record at the name, DKIM or not.

The record is split on semicolons into name=value tags, following the tag-list syntax of RFC 6376, Section 3.2.

  • A part without name=value is FAIL, “Malformed tag”.
  • A tag that appears twice is FAIL. Section 3.2: “Tags with duplicate names MUST NOT occur within a single tag-list; if a tag name does occur more than once, the entire tag-list is invalid.”
  • Unknown tags are listed and marked as ignored. Section 3.2: “Unrecognized tags MUST be ignored.”
  • v, when present, must be the first tag and exactly DKIM1; otherwise FAIL, and Heal it can correct the value. Section 3.6.1: “This tag MUST be the first tag in the record. Records beginning with a “v=” tag with any other value MUST be discarded.”
  • k must be rsa or ed25519, in lower case. k=RSA is reported as an unsupported key type (FAIL) with a correction hint, and no key assessment is made. Section 3.2: “Values MUST be processed as case sensitive unless the specific tag description of semantics specifies case insensitivity.” The ed25519 value comes from RFC 8463, Section 4.2.
  • s, when present, must include email or *; otherwise FAIL, “Key is not enabled for email”. Section 3.6.1: “Verifiers for a given service type MUST ignore this record if the appropriate type is not listed.”
  • A record without p is FAIL: no signature could ever verify. Section 3.6.1 marks p= “REQUIRED”.
  • An empty p= is CHECK, “Key revoked”. Section 3.6.1: “An empty value means that this public key has been revoked.” It is CHECK, not FAIL, because revoking is a deliberate act.
  • t=y is CHECK, “Testing mode”. Section 3.6.1: “Verifiers MUST NOT treat messages from Signers in testing mode differently from unsigned email, even should the signature fail to verify.” The key protects less than it could. Heal it removes the flag.
  • t=s is INFO. Section 3.6.1: the “i=” domain “MUST NOT be a subdomain of “d=”“. The tool has no message identity to compare, so it reports the flag without verifying it. Whitespace around the colon-separated flags is allowed.

An h= list naming sha1 without sha256 is FAIL, “Only sha1 allowed”. RFC 8301, Section 3.1: “rsa-sha1 MUST NOT be used for signing or verifying.” With sha1 the only hash the key accepts, RFC 6376, Section 6.1.2 step 6 makes every rsa-sha256 signature a PERMFAIL. Heal it removes h= so the default applies.

Key length is never estimated from the length of the text. The p value is base64-decoded after whitespace is removed, which RFC 6376, Section 3.6.1 allows (“A base64string is permitted to include whitespace”). Characters outside the base64 alphabet, or a length that cannot be valid base64, fail with “The key is not valid base64”. RFC 4648, Section 3.3: “Implementations MUST reject the encoded data if it contains characters outside the base alphabet”.

For RSA, the bytes are read as DER. Both a SubjectPublicKeyInfo structure (with the rsaEncryption identifier) and a bare PKCS#1 RSAPublicKey (RFC 8017, Appendix A.1.1) are accepted. The modulus is measured to the exact bit, leading zero bytes ignored, and the public exponent is shown. Structural errors are reported directly: “The key data is truncated”, “Invalid DER length”, or “The key is not an RSA key; set k= to its type” when the algorithm identifier is something else. RFC 6376, Section 6.1.2 step 5: a record that “does not adhere to the format defined in this specification” MUST be ignored with PERMFAIL.

For k=ed25519 the decoded key must be exactly 32 bytes. RFC 8463, Section 4.2: “The p= value in the key record is the Ed25519 public key encoded in base64.”

Truncated keys are the most common real-world failure. They come from a control panel that cut a long value at 255 characters, or dropped one of the quoted strings a long TXT record is split into. Another frequent cause is k=ed25519 on a key that is really RSA: when the key text starts with MI, the usual opening of DER, Heal it offers k=rsa.

The thresholds come from RFC 8301, Section 3.2: “Signers MUST use RSA keys of at least 1024 bits for all keys. Signers SHOULD use RSA keys of at least 2048 bits.” and “Verifiers MUST NOT consider signatures using RSA keys of less than 1024 bits as valid signatures.”

Key Severity Title
RSA under 1024 bits FAIL N-bit RSA key: receivers ignore it
RSA 1024 to 2047 bits CHECK N-bit RSA key: accepted, but 2048 is the recommendation
RSA 2048 bits or more PASS N-bit RSA key
Ed25519 PASS Ed25519 key, with a note to sign with RSA as well, because not every receiver verifies Ed25519 yet

The Ed25519 note is a Tamperbox recommendation. RFC 8463, Section 5 says “verifiers MUST implement the Ed25519-SHA256 algorithm”, and Section 6 describes signing twice, under two selectors, for backward compatibility.

The page computes a SHA-256 digest of the decoded key bytes in the browser and shows it in groups of eight hex characters. Compare it with the fingerprint your mail service shows to confirm that DNS holds the key you expect. It says nothing about whether outgoing mail is signed with it. No RFC defines a DKIM key fingerprint; this is a Tamperbox convenience.

The checker implements the key record half of DKIM: the record a verifier fetches in step 1 of RFC 6376, Section 6.1.2 and the checks of steps 3, 5 and 7 on it. It never sees a message body or a signature value, so hash computation (Section 3.7) and signature verification (Section 6.1.3) are out of scope. Lookups go to our server, which asks public DNS and returns the TXT text; every rule then runs in the browser. A pasted record never leaves the browser.

RFC 6376 is an Internet Standard (STD 76), updated by RFC 8301, RFC 8463, RFC 8553 and RFC 8616. RFC 8553 (underscored DNS names) and RFC 8616 (internationalized addresses) do not change the key record, so the tool has nothing to apply from them.

Section Requirement What the tool does
3.2 Tag-list syntax, no duplicates, unknown tags ignored Parsed locally; malformed or duplicate tags FAIL, unknown tags listed as ignored
3.6.1 v= First tag, exactly DKIM1 FAIL when not first or not DKIM1
3.6.1 k= Default rsa; unknown types ignored Accepts rsa and ed25519 only, case-sensitive; anything else FAIL
3.6.1 h= Colon-separated list; default all algorithms FAIL when sha1 is listed without sha256
3.6.1 p= Required; empty means revoked Missing FAIL; empty CHECK; otherwise decoded and measured
3.6.1 s= Must list email or * for mail FAIL when neither is listed
3.6.1 t= Flags y and s y CHECK, s INFO (not verified)
3.6.1 n= Notes for people Shown, not judged
Section Requirement What the tool does
3.6.2.1 Key at selector._domainkey.domain Looked up on our server for 24 common selectors, plus the one named
3.6.2.2 Strings concatenated; one TXT record per selector Strings joined; two or more records FAIL
6.1.2 step 2 No answer is TEMPFAIL Counted as “could not be checked”, never as a missing key
6.1.2 step 3 No record is PERMFAIL FAIL “No record at the selector” when a selector was named
6.1.2 step 7 Empty p= is PERMFAIL (key revoked) CHECK, because revoking is deliberate

From a pasted DKIM-Signature header the tool reads only d= and s= (Section 3.5). It does not compare the header’s a= with the key’s h= and k= (steps 6 and 8), does not read q=, and does not check i= against t=s.

RFC 8301 updates RFC 6376 Sections 3.3 and 3.3.3. The tool applies Section 3.1 through the sha1-only rule and Section 3.2 through the RSA thresholds: under 1024 bits FAIL, 1024 to 2047 CHECK (the SHOULD), 2048 and more PASS. The older floor in RFC 6376, Section 3.3.3, where verifiers had to accept 512-bit keys, is not used. RFC 8301 only obliges verifiers to handle keys up to 4096 bits; the tool still reports a longer key as PASS and does not warn that some receivers may refuse it.

RFC 8463 adds k=ed25519 (Section 4.2). The tool checks that p= decodes to 32 bytes, the public key size of RFC 8032, Section 5.1.5. It does not decode the bytes as a curve point (RFC 8032, Section 5.1.3), so 32 random bytes pass.

RFC 6376 Section 3.6.1 says the rsa type carries an RSAPublicKey and cites RFC 3447, which RFC 8017 obsoletes. Its own example in Appendix C publishes a SubjectPublicKeyInfo, which is what mail services issue. The tool accepts both forms. It reads the modulus and exponent (RFC 8017, Section 3.1) but does not check that the exponent lies between 3 and n - 1.

Base64 follows RFC 4648, Section 4. Non-alphabet characters are rejected (Section 3.3). Missing = padding is added before decoding, which is more lenient than Section 3.2 (“Implementations MUST include appropriate pad characters”); a receiver with a strict decoder may refuse such a key.

  • Tag names are case-insensitive in the tool. V=DKIM1; P=… is read as v and p, while RFC 6376, Section 3.2 says “Tags MUST be interpreted in a case-sensitive manner.” A receiver would see no p= tag. Values, including k=, stay case-sensitive.
  • Flags are exact colon-separated tokens. t=x-y is ignored, while t=y and t=s:y activate testing mode under section 3.6.1.
  • Multiple records are FAIL, not “undefined”. Section 3.6.2.2 leaves the result undefined, and Section 6.1.2 step 4 lets a verifier pick one or try each. The tool is stricter, because the outcome then depends on the receiver.
  • Unknown k= is FAIL. The RFC says unknown key types “MUST be ignored”; for mail, that means no usable key, so FAIL reflects the outcome.
  • Malformed RSA structures receive readable key errors, including missing BIT STRING and missing exponent, rather than a JavaScript exception title.

DMARC itself is not evaluated. Only the “No key under the common selectors” finding mentions it: without a key, the domain has no DKIM-Authenticated Identifier (RFC 9989, Section 4.4.1), so DMARC can pass only through SPF (Section 5.3.5). RFC 9989 obsoletes RFC 7489. Use the DMARC checker for the policy.

Each finding the checker can emit, grouped by what it judges, with what it means for mail signed with the key. “none” in the RFC section column marks a Tamperbox recommendation or method, not an RFC rule.

What receivers do with the published key, by its type, size and flags.

Finding Severity RFC section What it means for mail delivery Fix
N-bit RSA key (2048 or more) PASS RFC 8301, 3.2 Receivers can verify signatures made with it
Ed25519 key PASS RFC 8463, 4.2; the dual-signing note is none (Tamperbox) Strong; some receivers cannot verify it yet Also sign with RSA under a second selector
N-bit RSA key (1024 to 2047) CHECK RFC 8301, 3.2 Still accepted; scored down by some receivers Rotate to a 2048-bit key under a new selector
N-bit RSA key (under 1024) FAIL RFC 8301, 3.2 Receivers ignore the key; mail is treated as unsigned Rotate to a 2048-bit key
Key revoked (empty p=) CHECK RFC 6376, 3.6.1 Signatures with this selector fail on purpose Fine if retired; republish the key if mail still uses it
Testing mode (t=y) CHECK RFC 6376, 3.6.1 Failures may be treated as unsigned; weaker protection Remove t=y once signing works
Strict DKIM identity domain (t=s) INFO RFC 6376, 3.6.1 The signing identity must match the signing domain exactly Nothing, unless subdomains sign with this key

Problems that stop a receiver from loading the key at all.

Finding Severity RFC section What it means for mail delivery Fix
Malformed tag FAIL RFC 6376, 3.2 The record is not a valid tag list Write each part as name=value
Tag appears twice FAIL RFC 6376, 3.2 The whole record is invalid Keep one copy of the tag
Only sha1 allowed FAIL RFC 8301, 3.1 Receivers reject sha1 signatures Allow sha256, or remove h=
No p= key FAIL RFC 6376, 3.6.1 No signature can verify Publish the public key
Unsupported key type FAIL RFC 6376, 3.6.1 Case-sensitive: k=RSA is not k=rsa Use rsa or ed25519 in lower case
v=DKIM1 must be first FAIL RFC 6376, 3.6.1 Receivers ignore the record Move v= to the front
v= other than DKIM1 FAIL RFC 6376, 3.6.1 Only DKIM1 is defined Set v=DKIM1
Key is not enabled for email FAIL RFC 6376, 3.6.1 s= excludes email Set s=email, or remove s=
Finding Severity RFC section What it means for mail delivery Fix
The key is not valid base64 FAIL RFC 4648, 3.3 Receivers cannot load the key Re-copy the record from your mail service
The key data is truncated FAIL RFC 8017, A.1.1 Receivers cannot load the key Publish the full value; split it into quoted strings if your DNS panel limits a string to 255 characters
The key is not an RSA key; set k= to its type FAIL RFC 6376, 6.1.2 The k= tag and the bytes disagree Set k= to the real type
An Ed25519 key is 32 bytes FAIL RFC 8463, 4.2 The bytes are not an Ed25519 key Set k=rsa, or publish the right key

Findings about where the key lives and which selectors answer.

Finding Severity RFC section What it means for mail delivery Fix
Two or more records at the selector FAIL RFC 6376, 3.6.2.2 Results are undefined; receivers may pick either record Remove the old record
No record at the selector FAIL RFC 6376, 6.1.2 Mail signed with this selector fails at every receiver Publish the key, or sign with the right selector
No key under the common selectors FAIL none (Tamperbox probe list) The domain sends unsigned mail, or signs under its own selector Paste a message header to check the exact key
selector: key (another key found) INFO, CHECK or FAIL none (Tamperbox) Another service signs for the domain with this key Inspect it; each key needs the same attention

When someone says “your mail fails DKIM”, the key that matters is the one named in that message.

  1. Open the message’s source (Gmail: Show original; Outlook: View message source; Apple Mail: All Headers).
  2. Copy the DKIM-Signature: line with its continuation lines and paste it into the box. The page inspects exactly that key.
  3. If the verdict is “No DKIM key”, the selector in the message has no record: the service is signing with a key that is not in DNS. Publish the record your service gave you under that exact selector.
  4. If the key is there but weak, revoked or in testing mode, follow the section for that finding below.

Never replace a key in place: mail signed with the old key is still in transit.

  1. In your mail service, generate a new 2048-bit key. It gives you a new selector and a TXT record.
  2. Publish the record. Check the domain here: the new selector appears in the list with a PASS.
  3. Switch signing to the new selector in the service.
  4. After a few days, revoke the old selector by publishing v=DKIM1; p= under it. Check: the old key shows “Key revoked”.
  5. After a few weeks, delete the old record.

Confirm the switch by pasting the header of a freshly sent message: the s= tag should be the new selector.

An empty p= means someone retired this selector on purpose. If no mail uses it, nothing to do: delete the record when convenient. If mail still uses it, your service is signing with a key receivers refuse: republish the current public key under that selector, or switch the service to a selector that has one.

t=y belongs to the first days of a rollout. Once a few messages verify (paste their headers to see the key inspected, then confirm with your receiver’s reports), remove the flag. Heal it shows the corrected record; publish it in DNS.

Remove the h= tag, or make it h=sha256 or h=sha1:sha256. Heal it shows the corrected record. Nothing changes in the mail service; the record only declares what receivers may accept.

  1. Copy the record again from your mail service and compare it character by character with what DNS returns (The record, tag by tag shows the published p=).
  2. If your DNS panel limits a TXT string to 255 characters, split the value into two quoted strings: "v=DKIM1; k=rsa; p=MIIBIjAN…" "…IDAQAB". Receivers join them.
  3. If k=ed25519 and the key starts with MI, the key is RSA: set k=rsa (Heal it offers it).
  4. Publish, then Probe again.

A rotated key was added without removing the old one. Delete the old record so exactly one remains, then Probe again.

Either the domain sends no mail, or it signs under a selector the probe does not try.

  • If the domain sends mail, paste the header of a message it sent: the exact selector is in it. Many services use dated or random selectors.
  • If it sends no mail, publish *._domainkey.example.com TXT "v=DKIM1; p=" and a DMARC policy with p=reject, so nobody can sign as the domain.

Google Workspace, Microsoft 365, and the rest

Section titled “Google Workspace, Microsoft 365, and the rest”
Service Selector How the record is published
Google Workspace google TXT record the admin console gives you
Microsoft 365 selector1, selector2 Two CNAME records pointing into onmicrosoft.com; the key lives there
Mailchimp k1, k2, k3 CNAME to Mailchimp
SendGrid s1, s2 CNAME to SendGrid
Postmark pm TXT
Fastmail fm1, fm2 CNAME to Fastmail
Proton protonmail CNAME to Proton
Amazon SES three random selectors CNAME to SES; not in the common list, so paste a header

Because the probe follows CNAME aliases, a CNAME-published key appears like any other.

DKIM protects the message; the connection that carries it is protected by the mail server’s TLS certificate, which fails in its own ways. Check it with the SSL Certificate Checker on a mail port, and the TLSA records that pin it with the DANE checker.

Each case is built from the key you entered or looked up, so the finding looks the way it would for you.

Case What it does to your record Heal it offers
1024-bit key Loads a 1024-bit sample key Restore input before this break
Revoked key Empties p= Restore
Testing flag Adds t=y Remove testing mode (t=y)
Truncated key Cuts the key in half Restore
Only sha1 Adds h=sha1 Allow sha256
Wrong key type Sets k=ed25519 on an RSA key Set k=rsa (the key is RSA)

The page opens on a live check of tamperbox.dev. Its published records and findings can change over time.

For the deterministic walkthrough below, enter harbor-supply.example. This reserved .example domain is answered from synthetic data in your browser; it sends no live lookup. It publishes:

  • google: a 2048-bit RSA key, inspected. 2048-bit RSA key: valid and strong enough.
  • s1: a 1024-bit RSA key in testing mode, listed beside it and reported as a CHECK finding (“s1: 1024-bit RSA, testing”), because a second service signs for the domain with a weaker key.

Click s1 to inspect it: the verdict becomes “1024-bit RSA key: rotate when you can”, with Testing mode as a second finding and Heal it offering to remove the flag. Replace the sample with your own domain and every section, card and link is rewritten for it.

The Tamperbox MCP server runs the same checks. Search its catalog for the DKIM operation, inspect the input schema, and call it with the domain and, when known, the selector. Keep the warning block with any conclusion:

  • A valid key does not prove that any message is signed with it. Message verification needs the signature and the signed content.
  • Discovery tries the 24 common selectors; a domain can publish others.
  • DNS evidence is one answer from one public resolver at one moment.

See Connect an MCP client and Code mode for the calling pattern, and Security and privacy for where the domain travels.

  • Selectors are not discoverable from DNS; discovery finds the common ones only.
  • A valid key does not prove that mail is signed with it, or that a message passes.
  • A pasted record is measured in the browser and says nothing about what DNS serves.
  • One DNS answer, from one public resolver, at one moment.
  • Nothing is stored.