How to Set Up DKIM for Your Domain (Step-by-Step)
DomainKeys Identified Mail is the second pillar of email authentication. It uses public-key cryptography to prove that a message was sent with permission from the domain owner and that the body wasn't tampered with on the way. Here is exactly how to set it up.
What DKIM does
DKIM (RFC 6376) attaches a cryptographic signature to every outbound message. The signature is computed over the headers and the body using a private key that lives on the sending server. The corresponding public key is published in DNS. When a receiver gets the message it fetches the public key, verifies the signature and concludes one of two things:
- Pass — the message was sent by someone in possession of the private key, and the body has not been altered since signing.
- Fail — the signature is invalid (wrong key, modified body, missing header) or no key was found at the published location.
Unlike SPF, DKIM survives forwarding because the signature is part of the message itself. That makes it the more reliable of the two authentication methods in practice.
Step 1: Generate a key pair
You need an RSA key pair. 2048 bits is the modern standard; 1024-bit keys are still legal but flagged as weak by Google. On any Linux box with OpenSSL:
# Generate a 2048-bit private key
openssl genrsa -out dkim_private.pem 2048
# Extract the public key in DNS-friendly format
openssl rsa -in dkim_private.pem -pubout -outform DER 2>/dev/null \
| openssl base64 -A
The second command outputs a long base64 string. Save it — you will paste it into your DNS record in a moment.
Step 2: Choose a selector
A selector is a short label that identifies which DKIM key is being used. Common conventions include default, mail, s1, or a date stamp like 2026may. Date-based selectors make key rotation easier — you can publish a new key under a new selector and switch to signing with it without breaking in-flight mail.
For this guide we'll use s1.
Step 3: Publish the DNS record
The DKIM public key lives at {selector}._domainkey.{domain}. For our example, that would be s1._domainkey.example.com. Create a TXT record at that name with this content:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
Where the long string after p= is the base64 public key from step 1. Many DNS providers (Cloudflare, Route 53, OVH) handle the 255-character TXT segment limit automatically; if yours doesn't, split the value into multiple quoted strings.
The record's tag list explained
v=DKIM1— the version, always this.k=rsa— the key type.ed25519is also defined but barely supported by receivers in 2026.p=...— the public key in base64.t=y— (optional) testing mode; receivers should not act on a verification failure. Useful while you're rolling out, but remove it for production.s=email— (optional) restrict the key to email use only.
Step 4: Configure your MTA to sign
The MTA needs the private key file and the selector to start signing outbound mail. Here's how it looks in the most common setups.
Postfix + OpenDKIM
# /etc/opendkim.conf
Domain example.com
Selector s1
KeyFile /etc/opendkim/keys/s1.private
Socket inet:8891@localhost
Canonicalization relaxed/simple
SignatureAlgorithm rsa-sha256
# /etc/postfix/main.cf
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Exim
Exim has DKIM signing built in. In your transport definition:
remote_smtp:
driver = smtp
dkim_domain = example.com
dkim_selector = s1
dkim_private_key = /etc/exim/dkim/s1.private
dkim_canon = relaxed
dkim_strict = false
Hosted providers (Google, Microsoft, Mailchimp, etc.)
If you're using a third-party sender, you typically don't generate the key yourself — the provider gives you a CNAME to publish, and the actual public key lives at the destination of that CNAME on their side. The advantage is that they can rotate keys on your behalf. The downside is that you have to trust them to do it.
Step 5: Verify the signature
Send a test message to a Gmail account and open it. Click the three-dot menu → "Show original." You should see something like:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
d=example.com; s=s1; t=1714500000;
bh=2YfHK5Vqj9...; b=H8Lkz6bN...
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=s1
If you see dkim=pass you are done. Common failure modes:
dkim=neutral (no key)— DNS not propagated yet, or the selector path is wrong.dkim=fail (body hash did not verify)— something is modifying the message after signing. Usually a mailing-list footer appender or a misconfigured signing milter.dkim=fail (signature did not verify)— the published public key doesn't match the private key being used to sign. Re-export the public key and re-publish.
Testing tools
- MXToolbox DKIM Lookup — pulls the record at
{selector}._domainkey.{domain}and confirms it parses. - mail-tester.com — gives you a one-time address to send to and returns a deliverability scorecard, including DKIM result.
opendkim-testkey— the OpenDKIM package ships with a CLI that confirms the published key matches the local private key. Runopendkim-testkey -d example.com -s s1 -vvv.
Key rotation
Best practice is to rotate DKIM keys at least every six months. Because selectors are part of the lookup, rotation is painless: publish the new key under a new selector, configure the MTA to start signing with the new selector, wait a few days for any in-flight mail to clear, then remove the old key. We've published a separate guide on the full authentication stack that walks through this in more detail.
What can still go wrong
Even a correctly configured DKIM setup can fail in production. The most common pitfalls:
- Mailing lists that strip or rewrite headers will break DKIM unless they re-sign with their own domain (this is what ARC was invented to mitigate).
- Anti-virus scanners that append a "scanned by..." footer modify the body after the signature is computed.
- Key length below 1024 bits is now treated as no signature by Google and Microsoft.
- If you publish the public key with line breaks left in, some DNS providers will store them literally and the verification will fail.
With those caveats, DKIM is the most robust authentication signal you can publish. Pair it with SPF and DMARC and you have a complete authentication posture.