Deliverability
DKIM Explained: How Email Signing Works
DKIM (DomainKeys Identified Mail) is an email authentication method where the sending server signs each message with a private key, and the receiving server checks that signature against a public key published in the sender’s DNS. A valid signature proves two things: a domain took responsibility for the message, and the signed parts weren’t changed in transit. It’s defined in RFC 6376, and Gmail, Yahoo, and Outlook.com all require it for bulk senders.
Below is how the signing actually works, how to read a DKIM-Signature header, what the DNS record looks like, and why DKIM fails.
What DKIM proves, in plain terms
Think of DKIM as a tamper-evident seal stamped with a domain name.
- It proves responsibility. The
d=domain in the signature says “we sent or approved this.” Receivers build reputation on that domain. - It proves integrity. If someone edits the signed headers or body after signing, the signature no longer verifies.
- It survives forwarding in most cases, because the signature travels with the message instead of depending on the connecting IP address. That’s the big advantage over SPF.
What DKIM does not do on its own: it doesn’t require the signing domain to match the From address. A message from ceo@example.com can carry a perfectly valid signature from d=example.net. Connecting the two is DMARC’s job, through alignment. See DMARC explained.
How DKIM signing works, step by step
- Key pair. You (or your email provider) generate a public/private key pair. The private key stays on the sending server. The public key goes into DNS.
- Canonicalize. When a message is sent, the signer normalizes the headers and body using an agreed method (more on that below) so harmless changes like whitespace don’t break the signature.
- Hash the body. The signer hashes the canonicalized body and stores the result in the
bh=tag. - Sign the headers. The signer hashes the selected headers (always including From) plus the DKIM-Signature header itself, then encrypts that hash with the private key. The result goes into
b=. - Publish and look up. The receiver reads
d=ands=from the signature, queries DNS fors._domainkey.d, gets the public key, and verifies. - Result. The receiver records
dkim=passordkim=failin the Authentication-Results header, along with the domain that signed.
Anatomy of a DKIM-Signature header
Here’s a realistic signature, wrapped for readability:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=mail2026;
h=from:to:subject:date:message-id:mime-version:content-type;
bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB
4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut...
| Tag | Meaning |
|---|---|
v=1 | DKIM version. Always 1. |
a=rsa-sha256 | Signing algorithm. |
c=relaxed/relaxed | Canonicalization for headers/body. The default is simple/simple. |
d=example.com | The signing domain. This is the identity receivers evaluate. |
s=mail2026 | The selector, which tells the receiver which key to fetch. |
h= | The list of signed headers. RFC 6376 requires From to be included. |
bh= | Hash of the body. |
b= | The signature itself. |
t= / x= | Optional signing time and expiration (Unix timestamps). |
l= | Optional body length limit. Avoid it; see below. |
The DKIM DNS record and selectors
The public key lives in a TXT record at <selector>._domainkey.<domain>. RFC 6376 section 3.6.2 gives the lookup pattern. For the signature above, the receiver queries:
mail2026._domainkey.example.com
And finds something like:
mail2026._domainkey.example.com. 3600 IN TXT (
"v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5y0j..." )
Key record tags:
v=DKIM1(optional, but must come first if present)k=rsakey type (default rsa;ed25519is defined in RFC 8463)p=the base64 public key. An emptyp=means the key is revoked, per RFC 6376.t=ymarks the domain as testing DKIM;t=srestricts subdomain use.
Why selectors exist
Selectors let one domain publish many keys at once. That’s how you can have Google Workspace, a marketing platform, and a billing system all signing as example.com with separate keys, and how you rotate keys without downtime. Common selector names you’ll see: google, selector1/selector2 (Microsoft 365), s1/s2, or random strings from Amazon SES.
Many providers don’t ask you to paste a key at all. They give you CNAME records that point to keys they host and rotate:
- Microsoft 365 uses two CNAMEs at
selector1._domainkeyandselector2._domainkey. - Amazon SES Easy DKIM signs with a 2048-bit key by default and has you publish three CNAME records.
For the rotation process itself, see the existing guide on rotating a DKIM key without breaking mail in flight.
DKIM key length: 1024 or 2048?
RFC 8301 updated DKIM’s crypto requirements:
- Signers must use RSA keys of at least 1024 bits and should use at least 2048 bits.
- Verifiers must treat signatures with keys under 1024 bits as invalid.
rsa-sha1must not be used for signing or verifying.
Gmail’s sender guidelines match this: a key of 1024 bits or longer is required, and 2048 bits is recommended. Use 2048 unless your DNS host can’t store the longer key. Amazon notes that some DNS providers only support 1024-bit keys, which is the main reason to choose the shorter one.
A 2048-bit public key is longer than the 255-character limit for a single TXT string, so it must be split into multiple quoted strings in one record. Most DNS dashboards do this automatically; if yours doesn’t, split it yourself like the example above.
Canonicalization: simple vs relaxed
Mail servers make small changes in transit: rewrapping long header lines, changing the case of header names, trimming trailing spaces. Canonicalization decides whether those changes break your signature.
| Mode | Headers | Body |
|---|---|---|
simple | No changes tolerated | Only trailing empty lines ignored |
relaxed | Lowercases names, unfolds lines, collapses whitespace | Collapses whitespace, ignores trailing whitespace |
Use relaxed/relaxed. It’s what most major senders choose, and it tolerates the routine reformatting that simple does not.
Why DKIM fails: common causes
When you see dkim=fail or dkim=neutral (body hash did not verify), check these in order:
- No DNS record at the selector. The selector in
s=doesn’t exist in DNS, often because a CNAME was never added or was added at the wrong host name. Some DNS panels append your domain automatically, so enteringselector1._domainkey.example.comcreatesselector1._domainkey.example.com.example.com. - Truncated or broken key. The public key was pasted with a line break, a missing character, or extra quotes.
- Body modified after signing. Mailing lists that add footers, security gateways that rewrite links, and “disclaimer” appenders all change the body. The body hash then fails.
- Headers modified after signing. A gateway that rewrites the Subject (for example, prefixing
[EXTERNAL]) breaks the signature if Subject was signed. - Wrong domain signing. Your platform is signing with its own domain (
d=sendingplatform.example.net) instead of yours. DKIM passes, but it won’t align with your From domain, so DMARC still fails. Fix it by setting up custom DKIM for your domain in that platform. - Revoked or rotated key. The old key was removed from DNS before messages signed with it finished delivering.
Gmail spells out the consequences in its SMTP error reference: 4.7.30 means mail was rate limited because DKIM didn’t pass, and 5.7.30 means it was blocked.
About the l= tag
The l= tag tells receivers to verify only the first N bytes of the body. It was meant to survive mailing-list footers, but it also lets an attacker append content after the signed portion while the signature still verifies. Don’t use it.
How to check DKIM
Look up the key:
dig +short TXT mail2026._domainkey.example.com
Resolve-DnsName -Type TXT mail2026._domainkey.example.com
You need the selector to look up a key; there is no way to list every selector for a domain from DNS. Find it in the s= tag of a message you’ve sent.
Check a real message. Send to a Gmail address, open “Show original,” and look for:
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=mail2026 header.b=AuUoFEfD;
The header.i domain should be your domain, not your email platform’s. Or use the DKIM checker on this site to validate the record and key length. If you need a new key pair for a self-hosted server, the DKIM generator creates one.
DKIM in the bigger picture
DKIM is required by mailbox providers but it’s only one layer. Here’s how the pieces fit:
- SPF authorizes sending IPs for the bounce domain.
- DKIM signs the message with a domain’s key.
- DMARC requires one of them to pass and align with the visible From domain, and tells receivers what to do if neither does.
If you’re starting fresh, the SPF, DKIM, and DMARC setup guide walks through all three in order. For alignment edge cases, see DMARC alignment: strict vs relaxed.
Authentication tells receivers who you are. It can’t help if you’re mailing addresses that don’t exist. Before a campaign, run your list through our free email verifier to remove bad syntax, dead domains without MX records, disposable addresses, and typo domains. It doesn’t connect to mailboxes, but it filters out the failures that are visible from DNS alone.
FAQ
Is DKIM required for sending email?
Not technically, but practically yes. Google and Yahoo require both SPF and DKIM for bulk senders, and Microsoft requires DKIM to pass for domains sending more than 5,000 messages a day to Outlook.com. Unsigned mail from smaller senders is accepted but gets less trust.
Can a message have more than one DKIM signature?
Yes. It’s common for a message to carry one signature from your domain and another from the sending platform. Receivers evaluate each one, and DMARC passes if any valid signature aligns with the From domain.
What does “dkim=neutral (body hash did not verify)” mean?
The body hash in bh= doesn’t match the message body the receiver got, so something changed the body after signing. Footers, link rewriting, and content filters are the usual causes.
How often should I rotate DKIM keys?
There’s no number in the RFC. Rotate on a regular schedule and immediately if a private key may have been exposed. When a provider hosts the key behind CNAME records, as Amazon SES Easy DKIM and Microsoft 365 do, the provider manages the key itself, so check its documentation before rotating anything on your side. Our rotation guide covers the self-managed case.
Free email verifier: syntax, MX, disposable and role-based addresses, typos. Paste up to 100 at once.