Client Area

Email Deliverability Deep-Dive: SPF, DKIM, DMARC, BIMI on Cloudflare DNS

ByDomain India Team·DomainIndia Engineering
6 min read24 Apr 20264 views
# Email Deliverability Deep-Dive: SPF, DKIM, DMARC, BIMI on Cloudflare DNS
TL;DR
Your legitimate emails end up in spam because your DNS records aren't configured correctly. This guide walks through SPF, DKIM, DMARC, BIMI and MTA-STS — the five email authentication layers — with specific Cloudflare DNS steps. Done right, your inbox placement jumps from 60% to 95%+.
## 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=none` at minimum - One-click unsubscribe for bulk mail Apple, Outlook, and major ISPs apply similar rules. Non-compliant = spam folder. ## The five layers
LayerPurposeDNS recordPriority
SPFWho is allowed to sendTXTMust have
DKIMCryptographic signatureTXTMust have
DMARCWhat to do when SPF/DKIM failsTXTMust have
MTA-STSForce TLS on incoming mailTXT + HTTPSNice to have
BIMILogo in inboxTXT + SVGNice 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 ~all ``` Add to Cloudflare DNS:
1
Cloudflare Dashboard → Your Domain → DNS → Records
2
Add record:
3
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-flatten` tools if you exceed. Verify: ```bash dig TXT yourcompany.com +short # should return: "v=spf1 include:_spf.google.com ~all" # Or use mxtoolbox.com/spf.aspx ``` ## Step 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
1
Google Admin Console → Apps → Google Workspace → Gmail → Authenticate Email
2
Click "Generate new record" (2048-bit)
3
Copy the TXT record provided:
4
Add to Cloudflare DNS as TXT record
5
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: ```bash 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](https://domainindia.com/support/kb/category/email-hosting)). Verify: ```bash dig TXT default._domainkey.yourcompany.com +short ``` Send 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 reject - `rua` — 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
Warning

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: 86400 ``` Create `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=quarantine` or `p=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 logo - `a=` — 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
Q Can I skip BIMI and MTA-STS?

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.

Q Does Cloudflare Email Routing help deliverability?

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.

Q What if my domain uses DomainIndia email hosting?

Our webmail setup auto-configures SPF + DKIM. For custom TXT records (DMARC, BIMI, MTA-STS), add via cPanel → Zone Editor.

Q Reports flooding my inbox — help?

Use a tool like Postmark's DMARC Weekly Digest (free) or dmarcly.com. They aggregate XML into weekly summaries.

Q Gmail vs Yahoo vs Outlook — do I tune differently?

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

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket