Self-hosted email marketing with full source code. Pay once, own forever. Get AcelleMail — $74 →

Complete DNS Setup for Email Sending: SPF, DKIM, DMARC

A start-to-finish DNS setup walkthrough — register your sending domain, generate SPF + DKIM in AcelleMail, publish DMARC at p=none, verify, and graduate to enforcement.

A new sending domain needs five DNS records configured before AcelleMail can deliver authenticated mail at scale: SPF, DKIM, DMARC, MX (for receiving bounces), and PTR (reverse-DNS, configured at the host provider). This walkthrough takes you from "domain registered, AcelleMail installed" to "first authenticated send" — typically 30 minutes.

This is the first-time-setup companion to the deeper articles: SPF Deep Dive, DKIM Rotation, DMARC Migration. Each goes far deeper; this one gets you working.

Prerequisites

  • AcelleMail installed per the Ubuntu or platform-specific guide.
  • A domain you own (e.g. example.com).
  • DNS access at your registrar (Cloudflare, Route 53, Namecheap, Google/Squarespace Domains, etc.).
  • A sending IP (your own, or via SES/Mailgun/etc.).

Step 1 — Add the sending domain in AcelleMail

Admin → Domains → Sending Domains → New
   Name:     example.com
   DKIM:     "Generate" (AcelleMail creates a 1024-bit RSA keypair)
   DKIM Selector: acelle1   (default; can be customized)

AcelleMail's generateDkimKeys() (per app/Model/SendingDomain.php) generates the keypair locally and stores it in the sending_domains table. The next step shows you the public record to publish.

Step 2 — Publish SPF

The minimum SPF for SES + AcelleMail:

TXT  example.com  "v=spf1 include:amazonses.com -all"

If you're using AcelleMail to send directly (not via SES), use your sending IP:

TXT  example.com  "v=spf1 ip4:1.2.3.4 -all"

Multi-source (SES + something else):

TXT  example.com  "v=spf1 include:amazonses.com include:_spf.google.com -all"

Check the lookup count at mxtoolbox.com/spf.aspx; must be ≤ 9. See SPF Deep Dive for flattening if you exceed.

Step 3 — Publish DKIM

AcelleMail shows the public-key record to publish. Copy it from:

Admin → Domains → Sending Domains → <example.com> → DKIM Record
   Name:  acelle1._domainkey.example.com
   Type:  TXT
   Value: "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4..."

Publish exactly that record at your DNS provider. Wait at least 1 hour for propagation (TTL on most providers' default is 1 hour; some longer).

Step 4 — Publish DMARC at p=none

Start with the monitoring policy:

TXT  _dmarc.example.com  "v=DMARC1; p=none; rua=mailto:dmarc@example.com; aspf=r; adkim=r; pct=100"

The mailto:dmarc@example.com mailbox should exist (or forward to your inbox). Receivers will deliver daily aggregate XML reports here. Don't enable p=quarantine or p=reject yet — that's the DMARC Enforcement Migration playbook.

Step 5 — MX (for bounce handling)

If AcelleMail uses IMAP-based bounce handling (default for non-SES setups), you need an MX record to receive bounce messages:

MX  example.com  10 mail.example.com.
A   mail.example.com  1.2.3.4   (your AcelleMail host's IP)

Configure the AcelleMail bounce handler to poll an inbox at this domain. See Setting up bounce handlers for the AcelleMail config.

If using SES, you don't need MX — SES handles bounce detection via SNS. Skip to step 6.

Step 6 — PTR (reverse DNS)

PTR maps your sending IP back to a hostname:

1.2.3.4 → mail.example.com.

This is configured at your hosting provider's control panel (DigitalOcean, AWS, etc.), NOT in your domain DNS. PTR is critical: Microsoft and some others require it for sender legitimacy. Without PTR, expect immediate yellow/red status at SNDS.

# Verify
dig +short -x 1.2.3.4
# Should return: mail.example.com.

Step 7 — Verify everything

In AcelleMail:

Admin → Domains → Sending Domains → <example.com> → Verify

This runs verify() per app/Model/SendingDomain.php, which checks:

  • DKIM public key matches what's published in DNS
  • SPF resolves correctly + the sending IP is authorized
  • Identity token (a domain-ownership verification step)

All three must pass before the domain is marked Active. If DKIM fails, DNS hasn't propagated yet — wait an hour. If SPF fails, your record is malformed or doesn't include the sending source.

Step 8 — First test send

Customers → Test Customer → Lists → Test List → New Subscriber → your-email@gmail.com
Customers → Test Customer → Campaigns → New → "Test Campaign"
   From: hi@example.com
   Subject: Test send
   Send to: Test List

Send. In Gmail, click "Show original" on the received message. Look for:

SPF: PASS with IP 1.2.3.4
DKIM: 'PASS' with domain example.com
DMARC: 'PASS'

All three should pass. If any fail, that's a setup issue — re-verify the corresponding step.

DNS provider quirks

Cloudflare

  • TXT records: paste the full value including quotes. Cloudflare strips outer quotes automatically.
  • TTL: leave at "Auto" (typically 5 minutes; fast for testing).
  • Proxy: must be DNS only (gray cloud) for MX records — proxied mail records don't work.

AWS Route 53

  • TXT records: paste with double quotes around each segment. Route 53 wants "..." literal in the value field.
  • DKIM keys are long; some keys exceed Route 53's 255-char-per-string limit. Split with "part1" "part2" syntax.

Namecheap / GoDaddy / consumer registrars

  • TTL: lower it to 5-15 minutes during setup; increase to 1 hour after stable.
  • TXT records: some UIs strip quotes; others require them. If verification fails, try with and without surrounding quotes.

Common first-time failures

Symptom Cause Fix
"DKIM verify failed" 6h after publishing DNS still propagating; or registrar UI dropped a character Verify with dig +short TXT acelle1._domainkey.example.com from outside your network
"SPF: SOFTFAIL with IP" You used ~all instead of -all Update to -all once you're confident in the IP list
"DMARC: temperror" _dmarc record not yet propagated, or malformed Wait, then re-verify
First message goes to spam at Gmail Domain reputation = unknown (new domain) Start domain warmup
First message rejected at Microsoft No PTR Configure reverse-DNS at your host provider

Related reading

FAQ

How long should DNS propagation take?

Typically 1-4 hours for new TXT records. Cloudflare's default TTL of 5 min means changes propagate fast within Cloudflare; receivers' resolvers may cache up to 24h depending on TTL of the parent zone delegation.

Can I skip DMARC?

You shouldn't. Even p=none provides reporting that catches abuse and is required by Gmail/Yahoo's 2024 bulk-sender rules. It's a single TXT record; publish it.

Do I need separate DNS for each subdomain I send from?

Each subdomain you send from needs its own SPF, DKIM, DMARC. Inheritance: DMARC's sp= tag in the parent applies to subdomains; SPF and DKIM are per-subdomain.

What about BIMI?

BIMI is bonus once you reach p=quarantine or p=reject and have a trademarked logo + VMC. Skip during initial setup; revisit per BIMI walkthrough.

More in DNS & Domain Setup