SPF, DKIM, DMARC: a one-shot setup guide done right
Step-by-step setup for the three pillars of email authentication. DNS examples, alignment checks, and a gradual move from monitoring to enforcement.
The three foundations of email authentication — SPF, DKIM, and DMARC — are no longer optional for corporate sending. Since February 2024, major consumer mailbox providers have required all three for senders pushing 5,000+ mails/day. This guide walks through each from scratch, with DNS examples.
1. SPF — sending server authorization
SPF (Sender Policy Framework, RFC 7208) lists in a DNS TXT record which servers are authorized to send mail on behalf of your domain. The receiving server checks whether the inbound mail’s IP appears in this list.
DNS record
example.com. TXT "v=spf1 include:_spf.your-esp.com ~all"
Key points:
include:— use your ESP’s (including Sendnomi) recommended include. You can chain multiple, but watch the 10 DNS lookup limit.~all(softfail) — start here. Once confident, move to-all(hardfail).- Subdomains may need their own SPF; especially if you send through a different ESP on
mail.example.com.
Common pitfalls
- DNS lookup limit: SPF allows a maximum of 10 mechanism resolutions. Multiple
include:calls can blow past this limit. Check current SPF withdig +short example.com TXT, flatten if needed. - Multiple SPF records: Two SPF TXT records on the same domain produce permerror per RFC. Merge into one.
2. DKIM — message signing
DKIM (DomainKeys Identified Mail, RFC 6376) adds a digital signature to each outbound mail’s header using your private key. The receiving server verifies it against your public key in DNS.
Key generation (skip if your ESP handles it)
# When sending from your own server
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -outform DER | openssl base64 -A > public.txt
DNS record
selector1._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
Selector choice:
- Use a short, readable selector like
selector1,mail, ors1. - Keep a second selector (
selector2._domainkey) ready for rotation; rotate every 6-12 months.
Modern hardening — dual-sign
RSA + Ed25519 dual signing balances backward compatibility with modern security:
selector1._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=..." # RSA 2048
selector2._domainkey.example.com. TXT "v=DKIM1; k=ed25519; p=..." # Ed25519
The mail carries two separate DKIM-Signature headers; receivers prefer the strongest.
3. DMARC — alignment + policy
DMARC (RFC 7489) combines SPF and DKIM results, checks alignment, and decides what receivers do when both fail (none, quarantine, reject).
What is alignment?
SPF/DKIM may technically pass but if not aligned with the From: domain, DMARC fails. This closes the largest door for email forgery.
DNS record — gradual approach
Step 1 — Monitoring (p=none):
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:[email protected]; pct=100"
Watch rua reports for 2-4 weeks. Which 3rd-party services send from your domain? Which fail SPF/DKIM verification?
Step 2 — Quarantine (p=quarantine):
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; pct=10; rua=mailto:[email protected]"
Start with pct=10 — only 10% of failing mail goes to spam. Ramp up weekly (25 → 50 → 100).
Step 3 — Reject (p=reject):
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; adkim=s; aspf=s"
adkim=s; aspf=s enforces strict alignment — From: and DKIM/SPF domain must match exactly (subdomain is extra protection). ruf= for forensic reports (actual mail samples); not every receiver sends them.
DMARC report analysis
Reading raw XML reports at rua= is painful. Sendnomi’s panel auto-parses + visualizes them (Marketing → DMARC Reports). Open-source alternatives: dmarc-analyzer, parsedmarc.
Common mistakes
- Starting DMARC at p=reject — legitimate 3rd-party services (CRM, ATS, billing software) will silently break. Start at monitoring, ramp gradually.
- Chaining SPF includes past the 10-lookup limit — use flatten to avoid permerror.
- Not rotating DKIM selectors — 6-12 month rotation is best practice. Keep the old selector active for 30 extra days, then remove from DNS.
- No separate DMARC for subdomains —
sp=(subdomain policy) lets the parent have a different stance. Empty falls back top=.
Checklist
- SPF record: single line, < 10 mechanisms
- DKIM: at least one 2048-bit RSA selector active
- DKIM dual-sign (RSA + Ed25519) — optional but recommended
- DMARC monitoring (p=none) for at least 2 weeks
- Tool that parses DMARC reports (panel or 3rd-party)
- Gradual move: none → quarantine pct=10 → 100 → reject
- Subdomain coverage via
sp=or separate_dmarc.sub.example.com
The first 3 of our mail-score test’s 26 checks measure exactly these three standards. Run the test →
— Yazılım Koçu