Skip to content

Complete DNS Setup for Email Sending — The 6 Records You Need

Email deliverability runs on DNS. SPF, DKIM, DMARC, MX, custom-tracking-domain CNAME, BIMI — that's the full setup. This guide walks each in order with the exact records to publish, how AcelleMail verifies them, what each does.

The 6-record full setup

Every robust email-sending domain needs:

Record Purpose Required?
SPF (TXT) Authorize sending IPs Yes — base authentication
DKIM (TXT or CNAME) Cryptographically sign emails Yes — base authentication
DMARC (TXT) Tell receivers what to do if SPF/DKIM fails Yes — base authentication
MX (for return-path / bounce subdomain) Route bounces to AcelleMail If using custom envelope-sender
Tracking domain CNAME (CNAME) Brand the click-redirect Optional (recommended)
BIMI (TXT) Show your logo in inbox Optional (advanced)

This guide walks each.

Open the sending-domain detail

In AcelleMail's sidebar, Sending → Sending domains. The list shows every domain you've registered with status chips (Verified / Pending / Failed) and per-auth indicators:

Sending domains list

Click into your domain row. The detail page surfaces exactly which DNS records to publish (TXT for SPF, CNAMEs for DKIM, TXT for DMARC) with copy-paste-ready values + current verification state per check:

Sending-domain detail — DNS records + auth status

Record 1: SPF (Sender Policy Framework)

Tells receiving servers which IPs are authorized to send from your domain.

Publish at the apex domain (yourdomain.com):

Type:  TXT
Name:  yourdomain.com  (root)
Value: v=spf1 include:amazonses.com include:_spf.mailgun.org -all
TTL:   3600

Includes:

  • include:amazonses.com if using Amazon SES
  • include:_spf.mailgun.org if using Mailgun
  • include:sendgrid.net if using SendGrid
  • include:spf.example.com for any other vendor (check their docs)

-all (hard fail) tells receivers to REJECT messages from any IP not listed. Use ~all (soft fail) if you're still bringing new vendors online; switch to -all once production-stable.

See SPF record deep dive for the full reference + edge cases.

Record 2: DKIM (DomainKeys Identified Mail)

Cryptographically signs your outgoing emails so receivers can verify authenticity.

AcelleMail generates the DKIM keypair when you add a sending domain. Per the verify-domain wizard:

Type:  CNAME
Name:  acellemail._domainkey.yourdomain.com
Value: acellemail._domainkey.acellemail.com  (or your AcelleMail-side selector)
TTL:   3600

The exact CNAME target varies per AcelleMail install — the sending-domain detail page shows yours specifically. Most installs use AcelleMail's auto-generated 1024-bit or 2048-bit keys.

See DKIM key rotation playbook for rotation discipline.

Record 3: DMARC (Domain-based Message Authentication, Reporting & Conformance)

Tells receivers what to do when SPF/DKIM fails for your domain. Plus collects aggregate reports.

Publish at _dmarc subdomain:

Type:  TXT
Name:  _dmarc.yourdomain.com
Value: v=DMARC1; p=quarantine; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1; pct=100
TTL:   3600

Key parameters:

  • p= — what to do with failed messages (none = monitor only, quarantine = junk folder, reject = bounce)
  • rua= — where to send aggregate reports (typically [email protected])
  • ruf= — where to send forensic reports (per-failure detail; some receivers don't send these)
  • fo= — what failure types to report (1 = SPF or DKIM fail; s = SPF fail; d = DKIM fail; 0 = both fail)
  • pct= — what percentage of failed messages to apply the policy to (use 100 for full enforcement; useful for staged rollout)

Staged rollout: start p=none for 30 days. Move to p=quarantine once SPF/DKIM pass rate >99%. Move to p=reject for hardest enforcement.

See DMARC enforcement migration for the staged plan.

Record 4: MX for return-path / bounce subdomain (custom envelope-sender)

If you use a custom envelope-sender (e.g. bounce.yourdomain.com), AcelleMail needs an MX record so bounces route correctly:

Type:  MX
Name:  bounce.yourdomain.com
Value: feedback.acellemail.com  (or your install's bounce processor)
Priority: 10
TTL: 3600

Without this, bounce messages get rejected by the receiving server's MX lookup. AcelleMail's sending-domain detail page tells you the exact MX target.

For default vendor envelope-senders (e.g. SES's [email protected]), the MX is on AWS's side — no action needed.

Record 5: Custom tracking domain CNAME

If using a custom click-tracking domain (recommended for brand consistency):

Type:  CNAME
Name:  click.yourdomain.com
Value: track.acellemail.com  (or your install's tracking endpoint)
TTL:   3600

See Custom tracking domain for click URLs for the full setup.

Record 6: BIMI (show your logo in inbox)

After DMARC enforcement is stable, add BIMI:

Type:  TXT
Name:  default._bimi.yourdomain.com
Value: v=BIMI1; l=https://yourdomain.com/bimi/logo.svg; a=https://yourdomain.com/bimi/vmc.pem
TTL:   3600

Required: DMARC at p=quarantine or p=reject. See BIMI setup walkthrough.

Verify everything in AcelleMail

After all 6 records published, the sending-domain detail in AcelleMail shows green chips per auth check:

The auth chips on the sending-server detail

Open Settings → Sending servers → click your active server. The toolbar shows the live SPF / DKIM / DMARC chip status:

Sending server detail with auth chips

  • Green chips on all three = receiving servers can confirm you're authorized to send from this domain.
  • Any chip red = receiving servers immediately downgrade reputation. Click Verify domain in the toolbar to walk through the DNS-fix wizard.

Click Verify domain to re-check on demand. AcelleMail's dig-check runs against the receiving-server-side perspective (not your local cache), so propagation issues are detected accurately.

Common UI signals + fixes

Symptom Likely cause UI fix
All 4 auth chips Green except DMARC DMARC record published but pass rate <99% Check rua aggregate reports; identify failing source IPs
SPF chip Red after adding a new vendor SPF lookup count exceeded 10 (DNS limit) Combine includes or use SPF flattening (advanced)
DKIM chip Red despite CNAME published DNS propagation pending OR CNAME pointing wrong target dig CNAME acellemail._domainkey.yourdomain.com to verify
MX chip Red on bounce subdomain MX not published or pointing wrong target Check sending-domain detail page for exact MX target
BIMI logo not appearing in Gmail VMC not configured See BIMI VMC cost walkthrough
Different chip states on different campaigns Per-campaign From: domain doesn't match the verified sending domain Use consistent From: domain per sending-server config

Per-vendor SPF includes reference

Vendor SPF include
Amazon SES include:amazonses.com
SendGrid include:sendgrid.net
Mailgun include:_spf.mailgun.org
Postmark include:spf.mtasv.net
Sparkpost include:sparkpostmail.com
Self-hosted Postfix Your sending server IPs (ip4:1.2.3.4)

Combine for multi-vendor:

v=spf1 include:amazonses.com include:_spf.mailgun.org include:sendgrid.net -all

DNS lookup limit: 10. Most senders fit comfortably.

Advanced: SPF flattening, DKIM key length recommendations, DMARC ARC for forwarders

SPF flattening:

If you have many includes (3+ vendors + corporate apps), you can hit the 10-lookup DNS limit. SPF flattening resolves all includes at publish time + republishes as a single record:

# Before:
v=spf1 include:amazonses.com include:_spf.mailgun.org include:sendgrid.net include:spf.mtasv.net -all
# 4 lookups; if any vendor's include has 2-3 sub-includes, you blow the cap

# After (flattened):
v=spf1 ip4:54.240.0.0/18 ip4:13.32.0.0/15 ip4:54.240.36.0/22 ... -all

Tools like ValiMail SPF + Easy SPF auto-flatten + re-publish daily (vendors change their IP ranges). Self-flatten manually = maintenance burden; tool is worth it for 4+ vendor stacks.

DKIM key length:

  • 1024-bit: legacy; still works at all receivers
  • 2048-bit: modern; recommended for new setups
  • 4096-bit: maximum security; some DNS hosts don't allow >2048-bit TXT records

For DKIM-via-CNAME (AcelleMail default), the key length is managed at the AcelleMail side — typically 2048-bit.

DMARC ARC (Authenticated Received Chain):

For forwarding scenarios — when your message is forwarded by a recipient or middleman — the original SPF + DKIM can fail. ARC records the original auth state so the eventual receiver can trust the chain.

ARC-Authentication-Results: i=1; mx.google.com;
       dkim=pass [email protected] header.s=acellemail header.b=...;
       spf=pass [email protected];
       dmarc=pass header.from=yourdomain.com
ARC-Seal: i=1; a=rsa-sha256; t=...; ...
ARC-Message-Signature: ...

AcelleMail handles ARC signing automatically when forwarding scenarios are detected.

Aggregate DMARC report parsing:

DMARC rua= reports arrive at your inbox as XML files (.zip or .gz). Parse via:

  • dmarcian.com (free tier)
  • onDMARC by Red Sift (paid; full visualization)
  • DMARCLY (budget; basic reports)
  • Custom parser (open-source XML libraries)

Reports tell you which IPs sent from your domain and what auth state was — including unauthorized senders trying to spoof your domain.

Multi-tenant DMARC for SaaS:

If your platform sends on behalf of many customers:

Customer A:  _dmarc.customerA.com  → Customer's own DMARC policy
Customer B:  _dmarc.customerB.com  → Customer's own DMARC policy

Each customer manages their own DMARC. Your platform-side SaaS DMARC policy is separate (for emails sent FROM your own platform domain).

Verification automation:

# Daily script: verify all 6 records on all sending domains
domains=$(curl -sH "Authorization: Bearer $TOKEN" \
  "https://acellemail.com/api/v1/admin/sending-domains" | jq -r '.data[].name')

for domain in $domains; do
  spf=$(dig TXT $domain +short | grep -c "v=spf1")
  dkim=$(dig TXT acellemail._domainkey.$domain +short | grep -c "k=rsa")
  dmarc=$(dig TXT _dmarc.$domain +short | grep -c "v=DMARC1")
  bimi=$(dig TXT default._bimi.$domain +short | grep -c "v=BIMI1")

  echo "$domain: SPF=$spf DKIM=$dkim DMARC=$dmarc BIMI=$bimi"
done

Alert if any record drops to 0 (DNS host accidentally removed). DNS-host bugs do happen.

Related articles

18 comments

11 comments

  1. danrey.dev
    How do you handle DNS for clients in white-label setups? The customer would need to add records to their domain — is there a clean way to bulk-verify those?
    1. admin
      Currently a manual step. Theres a feature request tracking it on the repo if you want to +1.
  2. anna.k.pm
    the SPF flattening explanation finally made it click for me. I'd been hitting the 10-lookup limit and didn't understand why nesting includes counted.
    1. admin
      Glad it landed. Drop suggestions in the comments and we'll incorporate them on the next refresh.
  3. hung.nguyen.it
    DNS setup is one of those things where you don't know what you don't know. This article should be required reading for anyone running their own mail.
    1. admin
      thanks. Pass it along if it helps your team.
  4. femi.adeyemi
    Our DKIM rotation broke for 2 days because we updated the active selector first, then waited to delete the old. Should be the other way — publish new, wait 48h for cache, switch sending, THEN remove old.
  5. joel.anders.se
    Worth noting: our DNS provider (Cloudflare) caches negative responses for 1 hour. We added a TXT record, dig showed it, but mail-tester said missing for another 40 minutes. Almost lost our minds. TTL was set to 300 but the parent zone NS cache held.
    1. admin
      Solid case study material here. If youre open to it, we'd love to write this up as a blog post — happy to credit you anonymously or otherwise.
  6. aditi.s.bom
    If you use Vercel or Netlify for the apex, watch out — they sometimes override TXT records via their auto-DNS feature. Bit us once with a stripped SPF record.
    1. admin
      worth adding to the article. pr welcome if you want to author the addition.
  7. sobrien.kw
    Thanks for the explicit cautionary tales. The alignment-vs-pass distinction is exactly where I lost a week last year
  8. lequan.saigon
    quick question: do receivers actually enforce the spf -all hard fail, or do most just downrate? i've heard mixed things and i'm hesitant to switch from ~all.
    1. admin
      Good question. The campaign:rerun audit writes to laravel.log only when the audit decides to force-resume — pure noop runs are silent. We'll add an info-level heartbeat in a future Acelle release to make it easir to monitor.
  9. lucas.bernard.…
    Easy win: set up dmarcian.com (free tier) to receive your DMARC RUA reports. The first 2 weeks of reports tell you everything you didn't know about who's sending as you...
  10. akira.tnk88
    Hit the 10-lookup SPF limit when we tried to layer SES on top of an existing Google Workspace setup. Flattened with a tool (spfwizard.com) and it's been fine since. That tool's worth a mention.
  11. ahmed.hassan.c…
    what's your recommendation for sub-domains? we send from mail.example.com and notifications.example.com. same dkim selector or separate?
    1. admin
      Theres no built-in way today. Two workarounds: (1) cron + custom script polling the API every N minutes, (2) webhook-driven if your event source supports it. Most operators go with #2

More in DNS & Domain Setup