Setting Up DKIM: Key Generation, DNS Records and Verification
How DKIM signing works, what selectors are, and the full flow: generate keys, publish DNS, verify.
DKIM (DomainKeys Identified Mail) works on a simple cryptographic bargain: your outgoing mail server signs each message with a private key, and any receiving server can verify that signature using a public key you publish in DNS. A valid signature proves two things at once — the message really came from a server authorized by the domain owner, and the body and key headers were not tampered with in transit. Large receivers such as Gmail and Yahoo now demote or reject bulk mail without DKIM, so if you send anything from your own domain, this is table stakes, not a nice-to-have.
This guide walks the whole path: how the signing and lookup actually work, what selectors are for, concrete setup steps for Google Workspace, Microsoft 365 and self-hosted servers, the anatomy of the DNS record, and how to prove it all works. Once your record is live, you can confirm the public key resolves with the DKIM record lookup tool.
How DKIM works — signing, selectors, and the DNS fetch
Three steps, and every field in every admin console maps onto one of them.
- The sender signs. Just before handing the message off, the outbound server hashes the body and a chosen set of headers (From, Subject, Date, …), signs the hash with its private key, and attaches the result as a
DKIM-Signature:header. - The receiver fetches the public key. It reads the domain (
d=example.com) and selector (s=google) out of that header, then queries the TXT record atgoogle._domainkey.example.com. That record holds the public key. - The receiver verifies. If the signature checks out against the recomputed hash, the result is
dkim=pass. Change one byte of the body, or publish the wrong key, and it fails.
A selector is just a label for a key, and it exists so one domain can hold several keys at the same time. You want several for two reasons. Rotation: publish a fresh key under a new selector, switch signing over, then retire the old one — zero downtime. Per-service keys: Google Workspace signs as google, Microsoft 365 uses selector1/selector2, Mailchimp uses k1 — each sending service publishes under its own selector without stepping on the others.
Record anatomy — v=DKIM1; k=rsa; p=…
The public-key record is a TXT record named selector._domainkey.yourdomain, and its value is a semicolon-separated tag list.
v=DKIM1— version tag; always this value, always first.k=rsa— key algorithm. RSA almost everywhere; modern stacks also supported25519.p=MIIBIjANBg...— the Base64-encoded public key itself. An emptyp=is the official way to say "this key has been revoked".t=y(optional) — test mode; remove it once you go live.
Use a 2048-bit key. 1024-bit RSA is considered too weak a margin today, and Google defaults to 2048 for new keys. One practical wrinkle: a 2048-bit public key pushes the TXT value past the 255-character string limit, so some DNS editors require you to split the value into two quoted strings — most managed DNS providers handle the split for you.
Setup paths by provider — selectors and where to switch it on
| Provider | Selector | DNS record | Where to enable |
|---|---|---|---|
| Google Workspace | google | TXT (key published directly) | Admin console → Apps → Gmail → Authenticate email |
| Microsoft 365 | selector1, selector2 | 2 CNAMEs (Microsoft hosts the keys) | Defender portal → Email authentication settings → DKIM |
| Self-hosted (opendkim) | your choice (e.g. mail2026) | TXT (from opendkim-genkey output) | Hook into Postfix/Exim as a milter |
| Mailchimp | k1, k2, k3 | CNAME | Account → Domain authentication |
| Amazon SES | 3 random tokens | 3 CNAMEs (Easy DKIM) | SES console → Verified identities |
Microsoft 365 is the odd one out: instead of a TXT record you publish two CNAMEs, e.g. selector1._domainkey.yourdomain pointing at selector1-yourdomain-com._domainkey.tenant.onmicrosoft.com. Microsoft hosts the actual keys and rotates them for you by alternating selector1 and selector2. Once both CNAMEs have propagated, flip the "Sign messages" toggle in the Defender portal — nothing is signed until you do.
Self-hosting? opendkim is the standard. Run opendkim-genkey -b 2048 -d example.com -s mail2026 and you get mail2026.private (the private key) plus mail2026.txt — a ready-made TXT record to paste into DNS. Register the domain, selector and key path in the KeyTable/SigningTable, wire opendkim into Postfix as a milter, and restart.
Worked example — Google Workspace, start to finish
Say example.com runs on Google Workspace. The complete flow looks like this.
- Generate the key. In the Admin console (admin.google.com) go to Apps → Google Workspace → Gmail → Authenticate email. Pick your domain, click "Generate new record", and choose 2048-bit with the default selector prefix
google. - Publish the TXT. Copy the displayed value into your DNS zone exactly as shown:
Host:google._domainkey.example.com
Value:v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Fh9K2...IDAQAB(roughly 390 Base64 characters afterp=) - Confirm propagation. Run the DKIM record lookup with domain
example.comand selectorgoogle. Depending on TTLs this takes minutes to about an hour. - Activate signing. Back on the Authenticate email screen, click "Start authentication". This button is what actually turns signing on — publishing the TXT and forgetting this step is the single most common mistake.
- Verify with a real message. Send a test to any Gmail address, open it, and choose ⋮ → Show original. The summary should read
DKIM: 'PASS' with domain example.com, and theAuthentication-Resultsheader should containdkim=pass header.i=@example.com.
Alignment — DKIM alone doesn't finish the job
For DMARC, what matters is whether the signing domain (d=) aligns with the visible From: domain. If an email service signs with its own domain (d=mailer.com) while your From address is you@example.com, DKIM itself passes but DMARC alignment fails. That is exactly why SaaS senders ask you to publish CNAMEs under your domain (the Mailchimp/SES rows above) — it moves d= onto your domain.
With DKIM passing, complete the authentication trio. Audit your list of authorized sending IPs with the SPF record lookup, then declare a policy that ties both results together using the DMARC record generator — start at p=none and tighten from there. SPF + DKIM + DMARC together are what Gmail and Yahoo now require from bulk senders.
Frequently asked questions
Can I pick any selector name I want?
Should I use a 1024-bit or 2048-bit key?
I published the TXT record but my mail still isn't signed. Why?
How often should I rotate DKIM keys?
Does forwarding break DKIM?
Tools to use with this guide
Related guides
- Safely Moving DMARC from p=none to quarantine to rejectA safe, staged process to strengthen DMARC from monitoring (none) to quarantine and reject.
- Fixing SPF 'Too Many DNS Lookups' (permerror)Diagnose and fix SPF permerror caused by exceeding the 10 DNS-lookup limit via flattening.
- Why Email Lands in Spam: SPF, DKIM and DMARC TogetherCommon reasons sent mail goes to spam, and how to align SPF, DKIM and DMARC together.