~/tools/dossier-dkim
> dossier / dkim
probe common DKIM selectors for a domain and surface the public-key TXT record. part of the drwho.me domain dossier.
## overview
dkim (RFC 6376) signs outgoing mail with a per-sender private key; receivers verify by fetching the matching public key at `<selector>._domainkey.<domain>`. unlike spf or dmarc, dkim has no canonical record location — each sender picks its own `selector` label, and the selector in use is announced per-message via the `DKIM-Signature: s=...` header tag. there is no public-dns api to enumerate a domain's selectors, so this tool probes a fixed list of common defaults in parallel: `default`, `google` (google workspace / gmail), `k1` (mailchimp / mandrill), `selector1` and `selector2` (microsoft 365 rotate between them), and `mxvault` (mxroute). each probe is a TXT doh lookup; a selector is reported as `found` if the record starts with `v=DKIM1` or with a bare `p=` (RFC 8301 minimum marker). supply `selectors=[...]` to the `dossier_dkim` MCP tool to override the defaults.
## how to use
- enter a bare domain — public fqdn only. no schemes, ports, paths.
- run the check — six TXT doh queries fire in parallel, one per default selector at `<selector>._domainkey.<domain>`.
- read the selector table — each probed selector appears as a row: `found` with the record, or `not_found` with a dash. a domain typically publishes one or two selectors.
- find an unlisted selector — inspect a recently received email from the domain. the `DKIM-Signature:` header contains a `s=...` tag naming the selector actually in use — pass it via the MCP tool's `selectors` argument.
## examples
$ in
gmail.com# out
google - v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG... - other probed selectors not_found$ in
mailchimp.com# out
k1 - v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GN... - other probed selectors not_found## common mistakes
no public-dns enumeration— dns cannot list a domain's selectors. this tool probes a fixed common set — if a sender uses a bespoke selector (e.g. `20230601`, `s1024`, `smtpapi`), the default probe will report `not_found` for every slot even though dkim is fully configured. always cross-check against a real message's `DKIM-Signature: s=` tag before concluding dkim is missing.key rotation leaves old selectors behind— senders rotate keys by publishing a new selector and cutting traffic over. the old selector's TXT record often lingers for months so in-flight mail can still verify. seeing two selectors `found` usually means a rotation is in progress, not a misconfiguration.selectors frequently point at CNAMEs— a domain delegating mail to a provider (google workspace, sendgrid, mailchimp) typically publishes the `<selector>._domainkey` label as a CNAME into the provider's zone, not a direct TXT. doh resolvers follow the CNAME transparently, so this tool just sees the final TXT — but the control of the key lives with the provider, not the domain owner.
## faq
why these six selectors?
they cover the largest mail platforms by volume: `default` (generic fallback), `google` (google workspace / gmail), `k1` (mailchimp / mandrill), `selector1` + `selector2` (microsoft 365, which rotates between the two), and `mxvault` (mxroute). a domain that uses any other sender will likely come back all-`not_found` — that's expected.
can i supply a selector?
yes. the `dossier_dkim` MCP tool accepts `selectors=[...]`. pass the exact selector name you want to probe and only those labels are queried. the web ui probes the default set; use the mcp endpoint for custom probes.
what does `found` actually require?
a TXT record at `<selector>._domainkey.<domain>` whose value starts with `v=DKIM1` or contains a `p=` tag (the public-key marker). RFC 8301 permits omitting `v=DKIM1` on records that only carry the key, so we accept a bare `p=` prefix as well.
what does `not_found` mean — no record, or no dkim?
only that this specific selector has no TXT at the expected label. absence across all six common selectors is not proof dkim is missing — see the first gotcha about bespoke selector names.
why is this slower than spf/dmarc?
it fires six doh queries instead of one. they run in parallel under a single 5-second abort controller, so the wall-clock cost is close to a single query when the resolver is responsive.
## related tools
dns lookup— resolve A, AAAA, MX, TXT, NS, or CNAME records via Cloudflare DoH.dossier / dns— resolve A, AAAA, NS, SOA, CAA, and TXT records for a domain in one go.dossier / spf— find and parse a domain's SPF (sender policy framework) record.dossier / dmarc— find and parse a domain's DMARC policy record at _dmarc.<domain>.