SPF, DKIM, and DMARC: the 2026 setup guide

Published on February 18, 2026

A concrete 2026 setup for email authentication — what Gmail and Yahoo now require, what's changed from 2024, and the DNS records you actually need.

Since Gmail and Yahoo's February 2024 bulk-sender requirements went into effect, "authentication is optional" stopped being a defensible position. In 2026 the bar rises further. Here's what you need live today if you send any meaningful volume to consumer mailboxes.

If you're setting this up to send through a vendor, our Transactional Email API configures SPF, DKIM rotation, and DMARC reporting alignment automatically — you'll still want to know what the records below actually do.

The three records, in one paragraph

SPF tells receivers which servers are authorized to send mail from your domain. DKIM lets receivers verify a message hasn't been tampered with and was really sent by you (or someone with your key). DMARC tells receivers what to do when SPF and DKIM don't align with the domain in the From: header — and where to send reports about it.

You need all three. SPF or DKIM alone isn't enough.

SPF — getting it right

Your SPF record is one TXT record at your apex. If you're new to TXT records in general, DNScale's primer on TXT records covers the format and common pitfalls.

yourapp.com.  TXT  "v=spf1 include:_spf.postscale.io ~all"

The ~all at the end is "soft fail" — receivers treat unauthorized senders as suspicious but don't outright reject. Move to -all (hard fail) once you're confident all your senders are included.

Gotchas:

  • 10 DNS lookup limit. SPF resolves recursively. include:, a, mx, ptr, exists, and redirect all count. Hit 11 and every receiver fails your SPF. Audit with dig +short txt yourapp.com and a tool like dmarcian's SPF surveyor.
  • One SPF record per domain. Not two. If you have include:_spf.google.com for Workspace and include:_spf.postscale.io for transactional, they go in the same record:
    v=spf1 include:_spf.google.com include:_spf.postscale.io ~all
    
  • Subdomain vs apex. spf1 on mail.yourapp.com is separate from yourapp.com. If you send From: noreply@yourapp.com, the apex is what matters.

DKIM — what actually happens

DKIM signs outgoing messages with a private key. The corresponding public key sits in DNS under a selector:

<selector>._domainkey.yourapp.com.  TXT  "v=DKIM1; k=rsa; p=MIGfMA0G..."

With Postscale you don't generate keys — we rotate them and publish selectors automatically. You add two CNAMEs pointing at our key hosts (CNAME vs A records explained if you're deciding when to use each):

ps1._domainkey.yourapp.com.  CNAME  ps1._domainkey.postscale.io.
ps2._domainkey.yourapp.com.  CNAME  ps2._domainkey.postscale.io.

Two selectors means rotation doesn't interrupt delivery. We sign with one while the other is pre-published for the next rotation.

If you're manually managing keys, use RSA-2048 or Ed25519. Never publish a key shorter than 1024 bits — Gmail rejects messages signed with weaker keys. Rotate every 6–12 months.

DMARC — the 2026 settings

The minimum viable DMARC record:

_dmarc.yourapp.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@yourapp.com; fo=1"

Three fields to understand:

  • p= — policy. none = monitor only; quarantine = send suspicious mail to spam; reject = bounce at SMTP time.
  • rua= — where to send aggregate reports. Required to do anything useful with DMARC.
  • fo=1 — send forensic-fail reports when any check fails (not just total failure). Useful during setup.

For 2026 you want to reach p=reject if you send to consumer mailboxes in any volume. Gmail has been sending visible "Unverified sender" warnings in Inbox for p=none senders since late 2024. Go straight to p=reject only after at least 30 days at p=none with clean aggregate reports.

See our separate post on parsing DMARC aggregate reports for the monitoring side.

The Gmail/Yahoo 2024 requirements (still apply)

For bulk senders (> 5,000 messages/day to Gmail users):

  1. SPF AND DKIM both pass. Not either.
  2. DMARC policy at least p=none with valid rua=.
  3. One-click unsubscribe via List-Unsubscribe header with the List-Unsubscribe-Post: List-Unsubscribe=One-Click header.
  4. Spam complaint rate < 0.3%. Sustained violation = throttled or blocked.
  5. PTR record for your sending IP matching the HELO name.
  6. TLS on SMTP. Not optional anymore.

Postscale configures 1, 5, 6 automatically. You need 2 (add the DMARC record), 3 (emit the right headers in your templates — our API does if you set the list_unsubscribe field), and 4 (keep your list clean).

What to set for a new domain in 2026

For a fresh domain sending transactional email:

; Apex SPF
yourapp.com.  TXT  "v=spf1 include:_spf.postscale.io ~all"

; DKIM (two selectors for rotation)
ps1._domainkey.yourapp.com.  CNAME  ps1._domainkey.postscale.io.
ps2._domainkey.yourapp.com.  CNAME  ps2._domainkey.postscale.io.

; DMARC
_dmarc.yourapp.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@yourapp.com; fo=1; pct=100"

; MTA-STS (optional but recommended)
_mta-sts.yourapp.com.  TXT  "v=STSv1; id=20260101"

Then send your first message and immediately do:

# Verify SPF, DKIM, DMARC all pass
swaks --to check-auth@verifier.port25.com \
      --from you@yourapp.com \
      --server smtp.postscale.io \
      --auth LOGIN --auth-user YOUR_KEY

port25's responder emails back with a full authentication report. Shows pass/fail for every check.

Common failure modes

  • DKIM signature includes headers that change in transit. Your signing policy should exclude Received: and Return-Path: — they're rewritten by relays.
  • From domain vs envelope domain mismatch. DMARC alignment requires the visible From: domain to match either the DKIM d= domain or the SPF MAIL FROM. A common mistake is sending From: hello@yourapp.com but MAIL FROM: bounces@sendgrid.net — no SPF alignment, DKIM has to cover.
  • Wildcard DNS hiding the problem. Some providers resolve *.yourapp.com to an A record. Test with dig +short txt _dmarc.yourapp.com and confirm you get the TXT, not a web page IP.
  • DKIM key too long for DNS. Some DNS providers split a 2048-bit key into multiple strings. Joining them correctly requires quoted concatenation:
    "v=DKIM1; k=rsa; p=MIIBIj...ANBgkqhkiG9w0BAQEFAA" "OCAQ8AMIIBCgKCAQEAz..."
    
    DNS clients concatenate the strings; if you forget the quotes the key is truncated and DKIM silently breaks.

Next steps

  • If you haven't set up DMARC yet, start today with p=none and a parsing service. You'll be at p=reject within 45 days.
  • If you run SPF without DKIM, add DKIM. SPF breaks on forwarding; DKIM survives.
  • If you have all three but don't parse reports, set up DMARC reporting — otherwise you have authentication without observability.

Further reading