DKIM. How to Sign Your Email Properly
The cryptographic signature that proves your email came from you. Selectors, key rotation, and the gotchas no one tells you about.
<selector>._domainkey.<domain>. Your sending service signs with the matching private key. Get the selector right, use a 2048-bit key, and rotate twice a year.What DKIM actually is
DKIM (DomainKeys Identified Mail) is a public-key signature scheme bolted onto email. When you send a message, your sending server:
- Computes a hash of the message body and selected headers.
- Signs that hash with a private key it holds.
- Attaches a
DKIM-Signatureheader that includes the signature, the selector, and the domain.
On the receiving side, the mail server fetches your public key from DNS, recomputes the hash, and verifies the signature. If the signature is valid, two things are proven: the message claims to be from your domain are credible, and the signed content hasn't been altered since signing.
Why mailbox providers care
DKIM, unlike SPF, survives forwarding. If a user forwards your transactional email to their personal Gmail, SPF will fail (the forwarding server's IP isn't on your SPF list) but DKIM still validates because the signature is in the message itself. That makes DKIM the more reliable authentication signal for receivers.
DMARC enforcement requires either SPF or DKIM to pass and align. In practice, almost every well-configured sender relies primarily on DKIM alignment because it survives more scenarios than SPF does.
How signing works in practice
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=google;
h=from:to:subject:date;
bh=47DEQpj8HBSa+/TImW+5JC...=;
b=Zv5kKbZ...=;The key tags:
d=the signing domain (must match or be a parent of the From: domain for DMARC alignment).s=the selector. Receivers will look up<s>._domainkey.<d>.h=which headers were included in the signed hash.bh=the body hash.b=the signature itself.c=canonicalization, how whitespace and case are normalized before hashing.
The DNS record
The public key lives at <selector>._domainkey.<your-domain> as a TXT record:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...Tags you'll see:
v=DKIM1, version. Always this.k=rsa, key algorithm.p=, the base64-encoded public key. This is the only required tag.s=, service type (rare, usually omitted).h=, hash algorithms permitted.t=, flags.t=ymeans "test mode", never deploy with this in production.
p= is empty, that selector is revoked. Some sending platforms automatically revoke keys after a customer leaves; receivers will treat any future message signed with that selector as failed. Don't repurpose an old selector, use a new one.Picking a selector strategy
Selectors are just labels you choose. Useful conventions:
- One per service. Google Workspace's selector is typically
google. SendGrid usess1,s2. Postmark usespm-bounces. Resend usesresend. Don't try to consolidate, each service controls its own private key, so each needs its own published public key. - Date-stamped for rotation. If you manage your own keys,
2026-01,2026-07is a clean pattern. The selector itself tells you when to rotate. - Never reuse a selector across services. Selector
defaultat SendGrid and selectordefaultat Mailgun would collide in your DNS.
Key size and TXT-record gotchas
Use 2048-bit RSA. 1024-bit is acceptable at most receivers but flagged as weak by some auditors, and 1024 is technically breakable by well-resourced adversaries.
A 2048-bit RSA public key, base64-encoded, is around 250 characters, which collides with the 255-character per-string limit in DNS TXT records. Modern DNS providers handle this automatically by splitting the value into multiple quoted strings: "v=DKIM1; k=rsa; p=AAA..." "BBB...". Some receivers concatenate these correctly; some require the split to be in a specific position. If your record refuses to validate, check whether your DNS provider mangled the split.
dig +short TXT selector._domainkey.example.com from a different network than your DNS provider.Rotating DKIM keys without downtime
- Generate a new private key at your sending service (or your own keygen if you manage it).
- Publish the new public key at a new selector, e.g.
2026-07._domainkey.example.com. - Switch the sending service to sign with the new selector.
- Wait at least a week. Any mail signed with the old selector and still in transit (delayed retries, mailing lists, archived messages re-routed) will keep validating.
- Delete the old DNS record.
Twice a year is industry standard. Annually is fine for low-volume domains. Don't rotate more often than quarterly, the DNS churn isn't worth it.
Common mistakes
- Selector mismatch. The sending service signs with
s=googlebut the record is published atdefault._domainkey. Every message fails. Fix: read the actualDKIM-Signatureheader from a sent message, publish at exactly that selector. - Test flag left enabled.
t=yin the published record. Some receivers ignore signatures from test-mode keys. Remove it before going live. - Body modified after signing. Mailing lists that rewrite subjects, footer-injecting gateways, antivirus appliances that "clean" attachments, all break the body hash. The signature was valid when sent; it's invalid by the time the receiver checks. Use
l=body length tags carefully, or accept that DKIM + mailing-list is a known-broken combo (this is part of why ARC exists). - Forgetting to verify after rotation. Always send a test message to
check-auth@verifier.port25.comor use a tool to confirm a real message validates against the new selector before deleting the old one.
Monitoring DKIM over time
Unlike SPF, DKIM records don't usually change day to day. The failure modes are:
- Your sending provider rotates their selector and the public key you published goes stale.
- A DNS migration drops the
_domainkeyrecord. - You add a new sending service but forget to publish its DKIM record.
- Someone clicks "revoke" in your sending platform and the
p=tag empties.
Continuous monitoring catches all four. DomainsDoc checks the DKIM record for every selector you specify (default set covers the common ones: default, google, selector1, selector2, k1, s1, s2, mail, dkim) and alerts you the moment any of them stop resolving or change keys unexpectedly.
Frequently asked questions
What is a DKIM selector?
How do I find my DKIM selector?
What key size should I use for DKIM?
How often should I rotate DKIM keys?
My DKIM record shows up but mail still fails authentication. Why?
Can I have multiple DKIM records?
Continuous SPF, DKIM, DMARC, blacklist, SSL, and uptime checks. Alerts the moment something breaks.