How to Set Up DKIM Email Authentication

DKIM cryptographically signs your outbound mail so receivers can verify it really came from your domain and wasn't tampered with. This guide walks through generating a key, publishing the DNS record, and turning on signing.


DKIM (DomainKeys Identified Mail) adds a digital signature to every message your domain sends. The receiving server looks up your public key in DNS and verifies the signature, proving the message really came from you and wasn't altered in transit. DKIM is one of the three pillars of email authentication alongside SPF and DMARC — and DMARC enforcement requires DKIM (or SPF) to pass with alignment.

How DKIM WorksYour mail server signs each message with a private key and adds a DKIM-Signature header naming a selector. The receiver fetches the matching public key from <selector>._domainkey.yourdomain.com and checks the signature. The private key never leaves your server; only the public key lives in DNS.

Step 1 — Generate or Obtain a Key Pair

Most managed email providers (Google Workspace, Microsoft 365, and ESPs like SendGrid, Mailgun, Amazon SES) generate the key for you and give you the DNS record to publish — skip to Step 3 in that case. If you run your own mail server, generate a 2048-bit RSA key pair:

bash
# Generate a 2048-bit private key and its public key openssl genrsa -out dkim-private.key 2048 openssl rsa -in dkim-private.key -pubout -out dkim-public.key # Show the public key as a single line (strip the PEM header/footer) grep -v '^-----' dkim-public.key | tr -d '\n'
Choose a SelectorA selector is a label that lets you publish multiple keys and rotate them. Use something descriptive with a date, e.g. s2026a or mail2026. The selector goes in both the DNS record name and the DKIM-Signature header.

Step 2 — Build the DNS Record

Publish the public key as a TXT record. The host/name is <selector>._domainkey and the value contains the DKIM version, key type, and the base64 public key:

Command
; Name / Host s2026a._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...IDAQAB"
TagMeaning
v=DKIM1DKIM version — always DKIM1
k=rsaKey type (rsa is universally supported; ed25519 is newer)
p=…The base64-encoded public key
t=yOptional — testing mode; remove once verified
Watch the 255-Character LimitA 2048-bit key is longer than the 255-character limit for a single DNS string. Split the value into multiple quoted strings (most DNS panels do this automatically) — for example "v=DKIM1; k=rsa; p=MIIBI..." "...IDAQAB". They are concatenated on lookup.

Step 3 — Publish the Record for Common Providers

Managed providers give you a ready-made record. Typical selectors:

ProviderSelector(s)Record type
Google WorkspacegoogleTXT (generated in Admin console)
Microsoft 365selector1, selector2CNAME to Microsoft
SendGrids1, s2CNAME
Amazon SES3 CNAMEs (Easy DKIM)CNAME
Mailchimp / Mandrillk1CNAME
CNAME vs TXTMany ESPs use CNAME records that point at keys they host, so they can rotate the key for you without you touching DNS again. Publish exactly what the provider shows — don't convert their CNAME into a TXT.

Step 4 — Enable Signing on Your Server

For a self-hosted Postfix server, OpenDKIM is the usual choice:

bash
# /etc/opendkim.conf Domain example.com Selector s2026a KeyFile /etc/opendkim/keys/example.com/s2026a.private Socket inet:8891@localhost # Then in Postfix main.cf smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891 milter_default_action = accept
bash
sudo systemctl restart opendkim && sudo systemctl restart postfix

Step 5 — Verify DKIM Is Working

Confirm the public key resolves in DNS:

bash
dig TXT s2026a._domainkey.example.com +short # Expected: "v=DKIM1; k=rsa; p=MIIBIjAN..."

Then send a test message to a mailbox you control and inspect the headers — a passing check shows dkim=pass in the Authentication-Results header. You can also confirm the record with the ShowDNS TXT Lookup or run a full Domain Health Report to check SPF, DKIM and DMARC together.

DKIM Alone Isn't EnoughDKIM proves a message wasn't altered, but on its own it doesn't tell receivers what to do with unauthenticated mail. Pair it with SPF and a DMARC policy at p=quarantine or p=reject so spoofed mail is actually stopped.

Related Articles