Email Deliverability Deep-Dive: SPF, DKIM, DMARC, BIMI on Cloudflare DNS
Why emails land in spam
Since 2024, Gmail and Yahoo require senders sending >5,000 messages/day to have:
- SPF record published
- DKIM signature (aligned)
- DMARC policy with
p=noneat minimum - One-click unsubscribe for bulk mail
Apple, Outlook, and major ISPs apply similar rules. Non-compliant = spam folder.
The five layers
| Layer | Purpose | DNS record | Priority |
|---|---|---|---|
| SPF | Who is allowed to send | TXT | Must have |
| DKIM | Cryptographic signature | TXT | Must have |
| DMARC | What to do when SPF/DKIM fails | TXT | Must have |
| MTA-STS | Force TLS on incoming mail | TXT + HTTPS | Nice to have |
| BIMI | Logo in inbox | TXT + SVG | Nice to have |
Step 1 — SPF (Sender Policy Framework)
Declares which servers can send email as you.
Example for a domain using Google Workspace + Razorpay for transactional + Mailgun:
v=spf1 include:_spf.google.com include:spf.razorpay.com include:mailgun.org ~allAdd to Cloudflare DNS:
- Cloudflare Dashboard → Your Domain → DNS → Records
- Add record:
- Type: TXT
- Name: @ (or your apex like yourcompany.com)
- Content: v=spf1 include:_spf.google.com ~all (customise includes for YOUR senders)
- TTL: Auto
- Save
Key rules:
- Only one SPF record per domain. Multiple = broken. Merge includes into one.
~all(soft-fail) is standard.-all(hard-fail) is strict but can cause legit mail to bounce.- Max 10 DNS lookups (includes count). Use
spf-flattentools if you exceed.
Verify:
dig TXT yourcompany.com +short
# should return: "v=spf1 include:_spf.google.com ~all"
# Or use mxtoolbox.com/spf.aspxStep 2 — DKIM (DomainKeys Identified Mail)
Every outgoing email gets signed with a private key. Recipient verifies via your public key in DNS.
For Google Workspace
- Google Admin Console → Apps → Google Workspace → Gmail → Authenticate Email
- Click "Generate new record" (2048-bit)
- Copy the TXT record provided:
- Name: google._domainkey
- Value: v=DKIM1; k=rsa; p=MIIBIj... (long string)
- Add to Cloudflare DNS as TXT record
- Wait 10 minutes, click "Start authentication" in Google Admin
For Mailgun / SendGrid / AWS SES
Each gives you similar instructions. Typically 3 TXT records — add all three to Cloudflare.
For Postfix/Exim (self-hosted)
On your VPS:
sudo apt install opendkim opendkim-tools
sudo mkdir -p /etc/opendkim/keys/yourcompany.com
cd /etc/opendkim/keys/yourcompany.com
sudo opendkim-genkey -s default -d yourcompany.com
sudo cat default.txt
# Output: "default._domainkey IN TXT (..."Add the value as TXT record in Cloudflare. Configure Postfix to sign outbound mail (see DomainIndia SMTP tutorial).
Verify:
dig TXT default._domainkey.yourcompany.com +shortSend a test email to your Gmail, check Show original: should say "DKIM: PASS".
Step 3 — DMARC (Domain-based Message Authentication)
The policy that tells recipient what to do when SPF or DKIM fails.
Start in monitor mode:
_dmarc.yourcompany.com TXT "v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]; pct=100"Meaning:
p=none— just monitor, don't rejectrua— send aggregate reports here (daily summaries from receivers)ruf— send forensic reports (individual failures)pct=100— apply to all mail
Run p=none for 2-4 weeks. Reports tell you which senders are passing/failing. Use tools like [Valimail, Postmark, dmarcly.com] (many have free tiers) to parse XML reports.
Once all legit senders pass, upgrade:
_dmarc.yourcompany.com TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:[email protected]"p=quarantine— send to spam folder on fail- Eventually →
p=reject— bounce the mail
Don't start at p=reject. If your SPF/DKIM isn't perfect, legit emails bounce. Walk through none → quarantine → reject over weeks, monitoring reports.
Step 4 — MTA-STS (Mail Transfer Agent Strict Transport Security)
Forces TLS on incoming mail. Prevents downgrade attacks.
Two DNS records + one HTTPS file:
TXT record:
_mta-sts.yourcompany.com TXT "v=STSv1; id=20260424000000"MTA-STS policy TXT:
_smtp._tls.yourcompany.com TXT "v=TLSRPTv1; rua=mailto:[email protected]"Policy file at `https://mta-sts.yourcompany.com/.well-known/mta-sts.txt`:
version: STSv1
mode: enforce
mx: *.google.com
mx: *.googlemail.com
max_age: 86400Create mta-sts.yourcompany.com as a Cloudflare CNAME pointing to your web server serving this file. Or use Cloudflare Workers to serve it statically.
Step 5 — BIMI (Brand Indicators for Message Identification)
Display your logo next to emails in Gmail / Yahoo / Apple Mail inbox.
Requirements:
- DMARC with
p=quarantineorp=reject(minimum) - SVG logo following BIMI SVG Tiny PS spec
- (Optional but recommended) VMC (Verified Mark Certificate) from DigiCert or Entrust — paid ($1,000+/yr)
default._bimi.yourcompany.com TXT "v=BIMI1; l=https://yourcompany.com/bimi/logo.svg; a=https://yourcompany.com/bimi/vmc.pem"l=— URL to SVG logoa=— VMC certificate (only if you have one)
Without VMC, Gmail shows only verified brands. Small businesses: BIMI works in Yahoo/Apple but not Gmail (without VMC).
Practical configuration — real example
A small SaaS on DomainIndia + Google Workspace + Razorpay + Cloudflare DNS:
# SPF — apex
@ TXT "v=spf1 include:_spf.google.com include:spf.razorpay.com ~all"
# DKIM — from Google Workspace
google._domainkey TXT "v=DKIM1; k=rsa; p=MIIBIjAN..."
# DKIM — from Razorpay
razorpay._domainkey TXT "v=DKIM1; k=rsa; p=MIIBI..."
# DMARC
_dmarc TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:[email protected]"Monitoring deliverability
Tools:
- Google Postmaster Tools (postmaster.google.com) — daily inbox placement, spam rate, DMARC authentication rate for Gmail
- MXToolbox (mxtoolbox.com) — health check of all DNS records
- Mail-Tester (mail-tester.com) — send an email to their unique address, get a 0-10 score with detailed report
- Valimail / Dmarcly — parse DMARC reports for you
Target metrics:
- Spam rate (Postmaster) < 0.10% (hard cap is 0.30% in 2024 Google rules)
- DMARC authentication rate > 98%
- Mail-Tester score ≥ 9/10
Transactional vs marketing — keep them separate
Send transactional mail (order receipts) from [email protected] or [email protected]. Marketing mail (newsletters) from [email protected]. Using a subdomain (mail.yourcompany.com) for marketing isolates reputation so marketing problems don't hurt transactional delivery.
Handling bounces + complaints
Log bounces from your email provider's webhook. Unsubscribe + suppress hard-bounced addresses. Respect complaint feedback (List-Unsubscribe, spam reports).
Bounce > 5% = reputation damage fast. Clean your list regularly.
Common pitfalls
FAQ
Yes — SPF + DKIM + DMARC are the mandatory 3. BIMI is cosmetic (logo in inbox). MTA-STS helps but only matters if you're worried about state-level TLS downgrades.
Cloudflare forwards email to your actual provider. Deliverability depends on the provider's SPF/DKIM, not Cloudflare's. But Cloudflare does let you easily add MX records and workers for auto-replies.
Our webmail setup auto-configures SPF + DKIM. For custom TXT records (DMARC, BIMI, MTA-STS), add via cPanel → Zone Editor.
Use a tool like Postmark's DMARC Weekly Digest (free) or dmarcly.com. They aggregate XML into weekly summaries.
SPF/DKIM/DMARC are universal. Gmail applies stricter volume rules (if you send >5K/day). Outlook cares more about IP reputation. Test across all three.
Cloudflare DNS + DomainIndia hosting = reliable email delivery. Start with DomainIndia