All posts
Deliverability·By Deepak··10 min read

SPF DKIM DMARC for Automated Email Senders

TL;DR

Automated email senders fail deliverability not because of content, but because of broken authentication. SPF, DKIM, and DMARC work as a layered system — each solves a different problem. Get all three right, or your agent's mail lands in spam regardless of how clean the content is.

TL;DR: Automated email senders fail deliverability not because of content, but because of broken authentication. SPF, DKIM, and DMARC work as a layered system — each solves a different problem. Get all three right, or your agent's mail lands in spam regardless of how clean the content is.

SPF DKIM DMARC for Automated Email Senders

SPF, DKIM, and DMARC for automated email senders aren't optional configuration — they're the foundation that determines whether your agent's mail reaches an inbox or disappears into spam. Human senders can recover from authentication failures by asking recipients to check their spam folder. Automated senders have no fallback. If authentication breaks, mail fails silently and the agent never knows.

This guide covers the mechanics of each protocol, how they interact, and where automated senders most commonly break the chain.


What SPF actually does (and doesn't do)

SPF (Sender Policy Framework) authorizes IP addresses to send mail for a domain. The receiving MTA does a DNS TXT lookup on the envelope sender's domain and checks whether the connecting IP is listed. If it isn't, the check fails.

SPF lives in DNS as a TXT record on your sending domain:

v=spf1 ip4:203.0.113.10 include:_spf.youresp.com -all
  • ip4:203.0.113.10 — explicitly authorize a single IP
  • include:_spf.youresp.com — delegate to a third party's SPF record (e.g., your ESP)
  • -all — hard fail anything not listed (use ~all for soft fail during testing)

The critical distinction: SPF validates the envelope sender (the MAIL FROM address in the SMTP handshake), not the From: header the recipient sees. This matters enormously for automated senders that use separate bounce addresses.

SPF lookup limits

RFC 7208 caps DNS lookups during SPF evaluation at 10. Each include:, a:, mx:, and redirect= mechanism that triggers a DNS lookup counts toward this limit. Large ESPs often chain several include: directives together, and you can unknowingly exceed 10 lookups before you've added your own IP.

Check your current count:


dig TXT yourdomain.com | grep spf

Exceeding 10 lookups causes a permerror, which many receivers treat as a hard SPF failure. For automated senders operating across multiple sending services, SPF flattening — resolving all include: chains into explicit ip4: ranges — is often necessary.


How DKIM works at the protocol level

DKIM (DomainKeys Identified Mail) solves a different problem than SPF. Where SPF validates the sending IP, DKIM validates that message content hasn't been tampered with in transit, using a cryptographic signature.

Your sending server signs outbound messages with an RSA (or Ed25519) private key. The signature is added as a DKIM-Signature header:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  d=yourdomain.com; s=mail2026;
  h=from:to:subject:date:message-id:content-type;
  bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
  b=<base64-encoded-signature>

Key fields:

  • d= — the signing domain (must match or align with your From: domain for DMARC)
  • s= — the selector, which identifies which public key to look up in DNS
  • h= — the list of headers included in the signature
  • bh= — hash of the message body
  • b= — the actual signature

The public key lives at {selector}._domainkey.{domain} as a TXT record:

mail2026._domainkey.yourdomain.com TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."

Canonicalization matters for automated senders

DKIM has two canonicalization modes for headers and body: simple and relaxed. The c=relaxed/relaxed setting is almost always correct for automated senders. simple canonicalization breaks if any MTA in transit modifies whitespace — which mailing list software, spam filters, and some SMTP relays do routinely.

If your DKIM signatures are failing despite correct key configuration, canonicalization mismatch is the first thing to check.

What headers to include in the signature

At minimum, sign: from, to, subject, date, message-id, content-type, and mime-version. For automated senders using custom reply-to addresses for routing, also include reply-to — unsigned headers can be injected by an attacker.

Don't include received headers. They're added by every hop and will always break the signature.

DKIM key rotation

Rotate DKIM keys at least annually, and immediately if a private key is exposed. The rotation process:

  1. Generate a new keypair
  2. Publish the new public key under a new selector (e.g., mail2026b._domainkey.yourdomain.com)
  3. Wait for DNS TTL to propagate (typically 300–3600 seconds)
  4. Switch your sending infrastructure to sign with the new key
  5. Retire the old selector after a few days (old mail in transit may still need verification)

For Ed25519 keys (supported in DNS as k=ed25519), the keys are shorter and signature computation is faster, but receiver support is still patchy. Use RSA-2048 as the primary and Ed25519 as a secondary if you want both.


DMARC: the policy layer

DMARC (Domain-based Message Authentication, Reporting & Conformance) doesn't authenticate messages itself. It reads the results of SPF and DKIM checks and applies a policy when both fail. It also enforces alignment — the requirement that authenticated domains match the visible From: domain.

A DMARC record lives at _dmarc.yourdomain.com:

_dmarc.yourdomain.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; ruf=mailto:dmarc-failures@yourdomain.com; pct=100; adkim=r; aspf=r"
  • p= — policy: none (monitor only), quarantine (route to spam), reject (drop the message)
  • rua= — aggregate report destination (daily XML digests of authentication results)
  • ruf= — forensic report destination (individual failure reports; many receivers don't send these)
  • pct= — percentage of mail the policy applies to (use 100 in production)
  • adkim= — DKIM alignment: r (relaxed, organizational domain match) or s (strict, exact domain match)
  • aspf= — SPF alignment: same options

Alignment is where automated senders break

DMARC passes if at least one of SPF or DKIM passes with alignment. Alignment means the authenticated domain matches the From: header domain.

SPF alignment: the MAIL FROM domain must match the From: domain (relaxed: organizational domain match; strict: exact match).

DKIM alignment: the d= value in the DKIM signature must match the From: domain.

Automated senders routinely break DMARC alignment in two ways:

  1. Bounce address mismatch: the envelope sender (MAIL FROM) is set to a bounce processing address on a different domain, like bounce+hash@mailprovider.com. This fails SPF alignment because the From: domain is yourdomain.com but the envelope sender domain is mailprovider.com. Fix: use DKIM alignment instead — configure the signing domain to match your From: domain.

  2. Subdomain sending: sending from agent@mail.yourdomain.com with SPF records only on yourdomain.com. Relaxed alignment covers this (organizational domain match), but strict alignment (aspf=s) will reject it. Know your alignment mode.

┌──────────────────────────────────────────────────────────┐
│                   DMARC Evaluation                       │
│                                                          │
│  SPF Pass + SPF Alignment  →  DMARC PASS                │
│  OR                                                      │
│  DKIM Pass + DKIM Alignment →  DMARC PASS               │
│                                                          │
│  Both fail alignment       →  Apply p= policy           │
└──────────────────────────────────────────────────────────┘

How the three protocols interact

sequenceDiagram
    participant Agent as Agent Sender
    participant MTA as Your MTA
    participant Receiver as Receiving MTA
    Agent->>MTA: Submit message
    MTA->>MTA: Sign with DKIM private key
    MTA->>Receiver: SMTP delivery
    Receiver->>Receiver: SPF check on MAIL FROM IP
    Receiver->>Receiver: DKIM verify via DNS lookup
    Receiver->>Receiver: DMARC alignment check
    Receiver->>Receiver: Apply policy or deliver

Each check is independent. SPF failing doesn't prevent DKIM from passing. DMARC then decides what to do with the combination of results. For automated senders, DKIM alignment is the most reliable path because it depends on your signing configuration, not on the envelope sender domain matching anything.


Specific failure modes for automated senders

1. Shared IP reputation contamination

When your agent sends from a shared IP pool, other tenants' sending behavior affects your SPF-verified IP's reputation. A burst of spam from another tenant on the same IP degrades inbox placement for every sender on that IP. This is why dedicated IPs matter at volume — you control the IP's reputation history entirely.

2. Forwarding breaks SPF

When a recipient forwards mail, the forwarding server's IP isn't in your SPF record. SPF fails. DKIM survives forwarding as long as the message body isn't modified. This is another reason to prioritize DKIM alignment over SPF alignment in your DMARC configuration.

3. DKIM signature on modified messages

If your sending pipeline modifies message content after signing — adding tracking pixels, rewriting links, appending footers — the DKIM body hash (bh=) will no longer match and the signature fails. Sign after all modifications are complete.

4. Missing DMARC record

No DMARC record means receivers have no policy to apply. Some treat this as implicit p=none; others apply stricter heuristics. Either way, you get no aggregate reports and no visibility into authentication failures across the ecosystem. Publish a DMARC record at p=none with rua= set before you send a single message, then tighten the policy after reviewing reports.

5. Subdomain coverage

DMARC policy inheritance: if _dmarc.yourdomain.com has p=reject but _dmarc.mail.yourdomain.com has no record, receivers fall back to the organizational domain's policy. That's usually correct, but if you want a different policy per subdomain, publish an explicit record. The sp= tag controls subdomain policy directly:

_dmarc.yourdomain.com TXT "v=DMARC1; p=reject; sp=quarantine; rua=mailto:dmarc@yourdomain.com"

Deployment checklist for automated senders

Step Action Verify With
SPF Publish TXT record, stay under 10 lookups dig TXT yourdomain.com, mxtoolbox SPF check
DKIM Generate RSA-2048 keypair, publish public key, configure signing DKIM validator, email header inspection
DMARC Publish p=none + rua= first, tighten after 2 weeks DMARC analyzer, aggregate reports
Alignment Confirm DKIM d= matches From: domain Check Authentication-Results header on delivered mail
IP reputation Warm dedicated IPs before high volume Google Postmaster Tools, MX reputation tools
Reporting Parse aggregate rua reports weekly DMARC report parsers (parsedmarc, dmarcian)

Reading authentication results headers

Every delivered message includes an Authentication-Results header added by the receiving MTA. Read it to debug failures:

Authentication-Results: mx.google.com;
  dkim=pass header.i=@yourdomain.com header.s=mail2026 header.b=AbCdEfGh;
  spf=pass (google.com: domain of bounce@mail.yourdomain.com designates 203.0.113.10 as permitted sender)
      smtp.mailfrom=bounce@mail.yourdomain.com;
  dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=yourdomain.com

dmarc=pass with p=QUARANTINE means the policy would have quarantined this mail if DMARC had failed — but it passed because DKIM aligned. dis=NONE means no disposition action was taken.

If you see dmarc=fail, the dis= value tells you what the receiver actually did: NONE, QUARANTINE, or REJECT.

Platforms like Mails.ai expose sender reputation signals and authentication status per message, cutting out the manual header inspection step when debugging agent sending pipelines at scale.


BIMI: the next layer

BIMI (Brand Indicators for Message Identification) builds on DMARC. If your domain has p=quarantine or p=reject with pct=100, and you have a Verified Mark Certificate (VMC), receivers like Gmail display your brand logo in the inbox. For automated senders operating at scale, this is the last mile of authentication that makes messages visually trustworthy.

The DNS record:

default._bimi.yourdomain.com TXT "v=BIMI1; l=https://yourdomain.com/logo.svg; a=https://yourdomain.com/vmc.pem"

BIMI requires strict DMARC enforcement first. Don't pursue BIMI until your authentication chain is solid.


For agent-driven workloads where each message is programmatically generated and sent, the email infrastructure must have authentication baked into the sending path, not bolted on afterward. Configure DKIM signing at the infrastructure level, publish DMARC before the first send, and monitor aggregate reports continuously. Authentication failures in automated pipelines compound silently. By the time you notice declining deliverability, the reputation damage is already done.


Frequently Asked Questions

Does SPF alone satisfy DMARC requirements?

SPF alone can satisfy DMARC, but only if the MAIL FROM domain aligns with the From: header domain. Most automated senders use a different bounce domain for MAIL FROM, which breaks SPF alignment. In practice, DKIM alignment is more reliable for automated senders because it depends on your signing configuration, not your envelope sender domain.

What happens if I exceed the SPF 10-lookup limit?

The SPF evaluation returns a permerror. Most receiving MTAs treat permerror the same as an SPF failure. Under DMARC, SPF failing due to permerror means the SPF alignment check also fails. If DKIM also fails or isn't configured, DMARC applies your p= policy. Fix by flattening your SPF record to explicit ip4: ranges, eliminating chained include: directives.

Should I use p=reject immediately?

No. Start with p=none and a configured rua= aggregate reporting address. Run for at least two weeks, review the reports to find any legitimate sending sources you've missed, then move to p=quarantine for another cycle, then p=reject. Jumping straight to p=reject without visibility into your sending sources risks dropping legitimate mail from services you forgot to add to SPF or DKIM.

How does DKIM key length affect deliverability?

RSA-1024 bit keys are now considered weak and some receivers reject or downgrade messages signed with them — RFC 8301 recommends at least 2048 bits. RSA-2048 is the safe minimum today. Ed25519 keys are cryptographically stronger but receiver support isn't universal. Use RSA-2048 as your primary signing key.

Can an automated sender use multiple DKIM selectors?

Yes, and it's often useful. Different selectors let you rotate keys independently, attribute signing to different sending services, or experiment with Ed25519 alongside RSA. Each selector is a separate DNS TXT record. Receivers look up the selector specified in the s= tag of each message's DKIM-Signature header, so different messages can be signed with different keys simultaneously.

Do subdomains need their own DMARC records?

Only if you want a policy different from the organizational domain. Receivers fall back to the organizational domain's DMARC record for subdomains that don't have their own. Use the sp= tag on the organizational domain record to set an explicit subdomain policy without publishing individual records for every subdomain.

Start sending with Mails.ai

Live now

Ship agent email in ~6 lines.

Free tier, no card. Mint a key and drop the SDK into your agent.

Get your API key
Live now

Built for agents.
Self-serve in minutes.

The API is live and self-serve. Drop ~6 lines into your agent and ship.

npmpnpmbunnpx
$ npm install @mailsai/sdk
Live on npm today · @mailsai/sdk + @mailsai/mcp-server