OneWebDesk

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.

  1. 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.
  2. 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 at google._domainkey.example.com. That record holds the public key.
  3. 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 support ed25519.
  • p=MIIBIjANBg... — the Base64-encoded public key itself. An empty p= 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

ProviderSelectorDNS recordWhere to enable
Google WorkspacegoogleTXT (key published directly)Admin console → Apps → Gmail → Authenticate email
Microsoft 365selector1, selector22 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
Mailchimpk1, k2, k3CNAMEAccount → Domain authentication
Amazon SES3 random tokens3 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.

  1. 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.
  2. 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 after p=)
  3. Confirm propagation. Run the DKIM record lookup with domain example.com and selector google. Depending on TTLs this takes minutes to about an hour.
  4. 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.
  5. 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 the Authentication-Results header should contain dkim=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?
On a self-hosted server, yes — any alphanumeric label works, and dating them (mail2026) makes rotation easier to track. Managed services fix the selector for you: Google Workspace uses google, Microsoft 365 uses selector1 and selector2, so use exactly what the provider specifies.
Should I use a 1024-bit or 2048-bit key?
Use 2048-bit. 1024-bit RSA no longer offers a comfortable security margin, and major providers default to 2048 for new keys. Note that a 2048-bit public key exceeds the 255-character TXT string limit, so some DNS editors need the value split into two quoted strings.
I published the TXT record but my mail still isn't signed. Why?
Publishing the key and enabling signing are separate steps. Google Workspace needs the 'Start authentication' button clicked in the Admin console, and Microsoft 365 needs the signing toggle enabled in the Defender portal. Also make sure the record has actually propagated before you activate — check it with a lookup tool first.
How often should I rotate DKIM keys?
Every 6 to 12 months is the common recommendation. Publish a new key under a new selector, switch signing to it, wait a few days for retry queues to drain, then blank the old key's p= value or delete the record. Microsoft 365's CNAME delegation rotates keys automatically by alternating selector1 and selector2.
Does forwarding break DKIM?
Plain forwarding that leaves the body and signed headers untouched preserves the DKIM signature, so it still passes (unlike SPF, which breaks because the sending IP changes). Mailing lists are the exception: adding a subject tag or a footer changes the body hash and invalidates the signature.

Tools to use with this guide

Related guides