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

Tutorial · 12 min read

The 7 DNS records every self-hosted email sender needs

By AcelleMail Team May 8, 2026 12 min read
tutorial deliverability

A copy-paste DNS reference: SPF, DKIM, DMARC, MX, BIMI, MTA-STS, and a tracking-domain CNAME. Concrete syntax for Cloudflare and Route53, the order to publish, and what each record actually does.

§1

The seven records, in publish order

Email is unusual: a complete sender setup has seven distinct DNS records spread across three or four record types. Miss one and the wire still moves messages, but mailbox providers will quietly demote you to the spam folder. Publish all seven and you cross the "everything Google asks for" threshold from /guide/email-deliverability.

Order matters: SPF and DKIM should land before DMARC starts enforcing alignment, otherwise legitimate mail gets quarantined. The standing rule across vendors is also "wait for DNS to propagate" — allow at least 30 minutes between publishing a record and asking the mailbox provider to re-check.

#RecordPurposeSpec
1MXWhere inbound mail to this domain goesRFC 1035 §3.3.9
2SPF (TXT)Authorised sending IPsRFC 7208
3DKIM (TXT)Public signing keyRFC 6376
4DMARC (TXT)Policy on auth failure + reportingRFC 7489
5Tracking (CNAME)Click and open trackers under your domainRFC 1035
6MTA-STSForce TLS on inbound mailRFC 8461
7BIMI (TXT)Brand logo next to inbox messagesdraft-blank-ietf-bimi

§2

1) MX — even if you do not receive much mail

MX records (RFC 1035 §3.3.9) tell the world where to deliver inbound mail for your domain. Even if your sending domain is "outbound only" (you do not read replies on it), an MX record is still required — many mailbox providers downgrade reputation for domains with no MX, on the theory that legitimate senders accept replies. A single record pointing at any reachable mail server suffices, even if that server only delivers to a postmaster mailbox.

; Cloudflare DNS UI
Type: MX  Name: @  Mail server: mail.yourcompany.com  Priority: 10
# Route53 JSON
{ "Type": "MX", "Name": "yourcompany.com.", "TTL": 3600,
  "ResourceRecords": [{ "Value": "10 mail.yourcompany.com." }] }

§3

2) SPF — one TXT, watch the lookup count

SPF (RFC 7208) is a single TXT record listing which IPs are authorised to send for the domain. The hard rule: total recursive DNS lookups must stay under 10 (RFC 7208 §4.6.4). Each include: consumes one; nested includes count cumulatively. ip4: / ip6: mechanisms cost zero lookups, so collapse old includes into explicit IP ranges if your count creeps up.

# For Amazon SES (recommended pairing)
Type: TXT  Name: @  Value: v=spf1 include:amazonses.com -all
# For self-hosted Postal/Postfix on a single IP
Type: TXT  Name: @  Value: v=spf1 ip4:1.2.3.4 -all

End with -all (hard-fail) once you have verified all legitimate sending sources are covered. If you are not sure yet, start with ~all (soft-fail) and tighten to -all after two weeks of clean DMARC reports.

§4

3) DKIM — vendor-managed for SES, custom for Postal

DKIM (RFC 6376) publishes the public half of a signing keypair as a TXT record at {selector}._domainkey.{domain}. The "selector" is an identifier you choose — vendor-specific or arbitrary. For SES, AWS gives you three CNAMEs that resolve into AWS-managed TXT records (so AWS can rotate keys without you touching DNS):

# SES Easy DKIM — 3 CNAMEs (AWS rotates keys via these)
Type: CNAME  Name: token1._domainkey  Value: token1.dkim.amazonses.com
Type: CNAME  Name: token2._domainkey  Value: token2.dkim.amazonses.com
Type: CNAME  Name: token3._domainkey  Value: token3.dkim.amazonses.com

For self-hosted Postal or Postfix+OpenDKIM, you generate the keypair locally, configure the MTA to sign, and publish the public half as a TXT:

# Generate via openssl, then publish the .txt half
Type: TXT  Name: s1._domainkey  Value: v=DKIM1; k=rsa; p=MIGfMA0G…

Whichever path you take, verify with dig TXT {selector}._domainkey.{domain} before declaring DKIM done.

§5

4) DMARC — start at p=none, end at p=reject

DMARC (RFC 7489) goes at _dmarc.{domain}. Skipping the p=none ramp is the most common mistake — jumping straight to p=reject against a domain whose mail flows you do not yet fully understand will silently bounce legitimate mail (forwarders, mailing lists, third-party CRM senders).

# Stage 1 (weeks 1-3) — monitor only
Type: TXT  Name: _dmarc  Value: v=DMARC1; p=none; rua=mailto:dmarc@yourcompany.com; pct=100; adkim=r; aspf=r
# Stage 2 (weeks 4-5) — partial enforcement
Type: TXT  Name: _dmarc  Value: v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@yourcompany.com
# Stage 3 (week 6+) — full enforcement
Type: TXT  Name: _dmarc  Value: v=DMARC1; p=reject; pct=100; rua=mailto:dmarc@yourcompany.com

Read the daily aggregate XML reports landing in your rua mailbox between stages. Tools like Postmark's DMARC analyzer or self-hosted Parsedmarc visualise them; the bare XML is dense but readable.

§6

5) Tracking domain CNAME — preserve trust

By default, AcelleMail open-pixel and click-tracking URLs come from your install's primary domain. Mailbox providers like to see consistent root domains across the From, the link clicks, and the unsubscribe URL — all on the same registered domain. Branding-wise, links pointing at tracker.yourcompany.com are also more trust-signaling than links pointing at links.acellemail.com.

# Tracking subdomain CNAME → AcelleMail install
Type: CNAME  Name: track  Value: app.yourcompany.com

# Then in AcelleMail admin: Settings → Tracking domain
# Set: track.yourcompany.com

Once the CNAME resolves, AcelleMail rewrites all click-tracking URLs in outgoing messages to use it. The unsubscribe-link domain follows the same rule (and the same CNAME).

§7

6) MTA-STS — force inbound TLS

MTA-STS (RFC 8461) tells other senders "always require TLS when delivering to my MX". Without it, an attacker on the path can downgrade a TLS-capable handshake to cleartext. With it, the sending server refuses to deliver if TLS cannot be established. Implementation is one TXT record pointing at a hosted policy file:

# DNS record
Type: TXT  Name: _mta-sts  Value: v=STSv1; id=20260508T120000;

# Hosted policy file at https://mta-sts.yourcompany.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: mail.yourcompany.com
max_age: 604800

Run the policy in mode: testing for the first week, then flip to mode: enforce. Many bulk senders skip MTA-STS — deploying it is a free trust signal.

§8

7) BIMI — brand logo next to inbox messages

BIMI (Brand Indicators for Message Identification) is the youngest of the seven and the only one not yet a finalised RFC, but it is supported by Gmail, Yahoo, Apple Mail, Fastmail, and other clients in production. The deal: publish a TXT record pointing at an SVG logo and (optionally) a Verified Mark Certificate (VMC), and supporting clients display the logo next to your messages in the inbox list.

# Without VMC (free, lower coverage)
Type: TXT  Name: default._bimi  Value: v=BIMI1; l=https://yourcompany.com/bimi-logo.svg

# With VMC (paid, full Gmail coverage)
Type: TXT  Name: default._bimi  Value: v=BIMI1; l=https://yourcompany.com/bimi-logo.svg; a=https://yourcompany.com/bimi-cert.pem

Preconditions: a DMARC policy of at least p=quarantine (BIMI is not honoured under p=none), and the SVG must be SVG Tiny Portable / Secure (SVG-PS). Acceptance varies: Gmail requires a paid VMC ($1,500/year via DigiCert / Entrust) for full inbox-list display; Yahoo and Apple accept BIMI without VMC. Open-rate lifts of 5-20% are commonly reported in published case studies.

§9

Verify the whole chain in 30 seconds

After publishing, send yourself a test message and check the headers. Gmail web: open the message, click the three-dot menu, "Show original". Look for:

Authentication-Results: mx.google.com;
  dkim=pass header.i=@yourcompany.com header.s=token1
  spf=pass smtp.mailfrom=yourcompany.com
  dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=yourcompany.com

Three pass verdicts is the bar. Anything less — fail, softfail, neutral — means a record is wrong, or DNS has not propagated yet, or the mail body is being modified in transit (rare). Cross-check with the canonical Authentication-Results header (RFC 8601) spec if a verdict is ambiguous.

Run this on your own infrastructure.

AcelleMail is a one-time-license self-hosted email platform. Full source code, no per-subscriber pricing.

Get AcelleMail — $74 Try Live Demo