Skip to content
prod e051e98
Browse

5 · DNS email records

Objective — make transactional email deliverable by authenticating the sending domain: verify the provider, add SPF/DKIM/DMARC (plus MX), defer CAA to Phase 7, and confirm with dig — so password resets, receipts, and notifications don’t land in spam or get rejected.

flowchart LR
App[Laravel mailer] --> ESP[Email provider]
ESP --> DNS[SPF + DKIM + DMARC DNS]
DNS --> Inbox[Recipient inbox]
DNS --> Reject[Reject / spam folder]

1. Verify the email provider and record credentials

Section titled “1. Verify the email provider and record credentials”

Confirm which service sends mail (Postmark, SES, Mailgun, SendGrid, your host’s SMTP) and that the domain is verified there.

Record the SMTP/API credentials into the production .env (MAIL_*) from 3 · Production .env — double-quoted, never committed.

2. Add the three records and understand what each does

Section titled “2. Add the three records and understand what each does”
RecordTypeAnswersWithout it
SPFTXTWhich servers may send for this domainMail flagged as spoofed
DKIMTXTCryptographic signature proving integrityTampering undetectable; spam scoring
DMARCTXTPolicy when SPF/DKIM fail + where to reportNo alignment policy; inconsistent delivery
  1. Publish the SPF record — one TXT at the root, listing every sender. Merge into a single record — multiple SPF records is itself a failure.

    DNS records
    example.com. TXT "v=spf1 include:_spf.provider.com ~all"
    • ✅ A single SPF TXT record exists at the root, listing every sender.
  2. Publish the DKIM record — your provider gives a selector and key; publish it at the selector host they specify.

    DNS records
    selector._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<public-key>"
    • ✅ The DKIM key is published at the provider’s selector host.
  3. Publish the DMARC record — start at p=none (monitor only), collect reports, then tighten to quarantine/reject.

    DNS records
    _dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1"
    • ✅ A DMARC TXT record at _dmarc.<domain> starts at p=none.

3. Add MX records (if the domain receives mail)

Section titled “3. Add MX records (if the domain receives mail)”

If the domain also receives mail, add the provider’s MX records at the documented priorities. If it only sends (transactional-only), MX may point elsewhere or be omitted — match your provider’s guidance.

  1. Publish the MX records at the provider’s priorities.

    DNS records
    example.com. MX 10 mx1.provider.com.
    example.com. MX 20 mx2.provider.com.
    • ✅ MX records are present if the domain receives mail (or correctly omitted if send-only).

Read the resolver output directly, then send a real test message and inspect the headers.

  1. Confirm all records resolve.

    Terminal window
    dig +short TXT example.com | grep spf1 # SPF present, single record
    dig +short TXT selector._domainkey.example.com # DKIM key resolves
    dig +short TXT _dmarc.example.com | grep DMARC1 # DMARC policy present
    dig +short MX example.com # MX (if receiving mail)
    # Expected: one SPF line, the DKIM key, a DMARC1 policy, and MX records (if receiving mail)
    • ✅ SPF (single), DKIM, DMARC, and MX (if receiving) all resolve.
  2. Send a real test email and inspect the headers (or use a deliverability checker) — confirm spf=pass, dkim=pass, and dmarc=pass.

    • ✅ A test email shows spf=pass, dkim=pass, and dmarc=pass.
SymptomCauseFix
spf=softfail/failSender not in SPF includeAdd the provider’s include; keep one SPF record
dkim=noneSelector record missing/typo’dRe-publish exactly as the provider specifies
dmarc ignoredRecord at wrong hostMust be _dmarc.<domain>, not the root
Multiple SPF recordsTwo TXT v=spf1 entriesMerge into one

Do not mark this step done until every box below is checked.

  • 👤 Provider verified — email provider verified; MAIL_* recorded in production .env.
  • 🔀 Records resolve — SPF (single record), DKIM selector, and DMARC (p=none to start) all resolve via dig.
  • 👤 MX correct — MX records correct if the domain receives mail.
  • 🤖 CAA deferred — CAA deliberately not added — deferred to Phase 7.
  • 🔀 Test passes — test email shows spf=pass, dkim=pass, dmarc=pass.