A message can pass SPF and still be spoofed at the part recipients actually read. SPF authenticates the SMTP envelope; it says nothing about whether the body or the visible From: header was tampered with in flight. DKIM closes that gap by signing the message itself, and that signature is what allows DMARC to survive forwarding and prove authorship.
What DKIM actually is
DKIM (DomainKeys Identified Mail, RFC 6376) is a cryptographic signature attached to every outbound message as a DKIM-Signature header. The signer holds a private key. The corresponding public key is published in DNS at a well-known location. Any receiving server can verify the signature by fetching the public key and recomputing the hash.
DKIM proves two things and nothing more: that the domain in the d= tag authorised this message, and that the signed portions of the message have not been modified since signing. It does not prove the human sender is honest and it does not encrypt anything.
How DKIM works at the protocol level
The signing flow:
1. Sender's MTA selects which headers to sign (h= tag) and how to
canonicalise them (c= tag). It hashes the body and stores the
hash in bh=.
2. It builds a string from those headers + the DKIM-Signature header
(with b= empty), canonicalises it, and signs it with the domain's
private key.
3. The resulting signature is written into b=. The full header is
prepended to the message:
DKIM-Signature: v=1; a=rsa-sha256; d=yourdomain.com; s=mm2026;
c=relaxed/relaxed; h=From:To:Subject:Date;
bh=<body-hash>; b=<signature>
4. The receiver reads d= and s=, fetches the public key from DNS at
s._domainkey.d (e.g. mm2026._domainkey.yourdomain.com), recomputes
the body hash and the header hash, and verifies the signature.The tags that matter when you're debugging:
d=— the signing domain. DMARC alignment is checked against this.s=— the selector, which picks the DNS record to fetch.h=— the list of headers that were signed. Any change to a signed header breaks verification.bh=— the body hash. Any change to the signed portion of the body breaks verification.c=— canonicalisation.relaxed/relaxedtolerates whitespace normalisation;simple/simpleis strict.l=— body length limit. Generally avoid this; it lets attackers append content below the signed portion.
Selectors: what they're for
A selector is a label. Its only job is to namespace which public key to use, so a single domain can publish many keys at the same time. That gives you two useful capabilities.
First, key rotation without downtime. You publish a second selector with a new key, switch the signer to use it, leave the old selector live for a couple of weeks so messages still in transit verify, then retire the old record. Receivers continue to verify throughout.
Second, multiple signers. Your transactional ESP signs with their selector under your domain (often via a CNAME they instruct you to publish), your marketing ESP signs with theirs, and an internal MTA signs with its own. Each maintains its own private key and rotates it on its own schedule.
Why DKIM fails in production
1. Header or body modification in transit
Anything that rewrites a signed header invalidates the signature. Mailing lists that prepend [list-name] to the Subject, anti-virus appliances that inject a footer, transparent proxies that re-wrap the body — all of these are common DKIM killers. This is exactly why DMARC requires either aligned SPF or aligned DKIM, not both. See the DMARC lesson for how alignment is evaluated.
2. Key rotation gaps
When you rotate a key, two things must overlap: the new public key must be live in DNS before the signer starts using it, and the old public key must stay in DNS until the last in-flight message signed with it has been delivered. Skipping either window produces intermittent failures that look like flapping deliverability and are extremely hard to diagnose without DMARC reports.
3. Truncated 2048-bit keys
A 2048-bit public key is longer than the 255-character limit on a single TXT string. DNS handles this by allowing multiple quoted strings in one record, which servers concatenate. Some DNS UIs silently truncate, breaking the key. The DKIM checker will tell you if the published key parses.
4. Missing key after a CNAME chain
ESPs often publish DKIM as a chain of CNAMEs pointing into their infrastructure. If any link in the chain is misconfigured, the resolver returns NXDOMAIN and DKIM evaluates to none. Walk the chain with dig +trace TXT mm2026._domainkey.yourdomain.com to see where it stops.
5. DKIM passes but doesn't align
Default ESP signing often uses the ESP's own domain in d=. The signature verifies, but DMARC requires d= to align with your header From domain. Configure the ESP for "branded" or "custom domain" DKIM so the signature is anchored at your domain.
How to check your DKIM signature
The fast path is the DKIM checker: give it your domain and selector, and it resolves the public key, validates the format, and flags weak key sizes. The thorough path is to send a message to yourself at Gmail, open the original, and read the Authentication-Results header. You want dkim=pass with d= equal to your domain.
If you only see dkim=none, the record isn't published or the selector in the signature header doesn't match what's in DNS. If you see dkim=fail, the key is published but the signature didn't verify — usually a body modification or a truncated key.
When you're ready to deploy
The per-ESP DKIM setup pages have the literal selectors and public-key records:
DKIM and SPF are the two authentication signals. DMARC is what tells receivers what to do when either of them fails — and what to do with mail that pretends to be from your domain but isn't authenticated at all.
Looking for the short definition? See DKIM in the glossary.
