---
title: "SPF, DKIM, and DMARC Explained: How Email Auth Works"
description: "How SPF, DKIM, and DMARC work together: what each record checks, why alignment decides DMARC, a worked example on Amazon SES, and a safe path to p=reject."
source: "https://www.mailmark.dev/blog/understanding-spf-dkim-and-dmarc"
site: "Mailmark"
---

# SPF, DKIM, and DMARC Explained: How Email Auth Works

SPF, DKIM, and DMARC are three DNS records that let a receiving server check that mail claiming to be from your domain really is. **SPF** lists the servers allowed to send for your domain. **DKIM** adds a cryptographic signature that proves the message came from your domain and wasn't changed. **DMARC** checks that at least one of them passed *for the domain in the From address*, tells the receiver what to do if not, and sends you reports.

> **All three records, generated per domain** Add a domain to Mailmark and it generates SPF, DKIM, DMARC, and MAIL FROM records with your values filled in, then re-checks them twice a day. [Add your domain](https://www.mailmark.dev/?utm_source=guide&utm_medium=seo&utm_campaign=understanding-spf-dkim-and-dmarc&utm_content=top)

## SPF: which servers may send

SPF is a TXT record on your domain:

```text
v=spf1 include:amazonses.com include:_spf.google.com ~all
```

Each `include` pulls in another provider's list of sending servers. The ending decides what happens to everything else. Per [RFC 7208](https://datatracker.ietf.org/doc/html/rfc7208), `~all` is a soft fail (treat with suspicion) and `-all` is a hard fail.

Two things about SPF catch almost everyone:

- **It checks the envelope sender, not the From address.** The envelope sender (also called the MAIL FROM or Return-Path) is where bounces go. Most providers use their own domain for it by default, so SPF passes for *their* domain. That matters for DMARC, below.
- **It has hard limits.** A domain [must have only one SPF record](https://datatracker.ietf.org/doc/html/rfc7208#section-3.2), and evaluating it may take [no more than 10 DNS lookups](https://datatracker.ietf.org/doc/html/rfc7208#section-4.6.4). Break either and SPF returns `permerror`.

## DKIM: a signature on every message

DKIM signs each message with a private key. The signature goes in a `DKIM-Signature` header that names the signing domain (`d=`) and a selector (`s=`). The receiver looks up the public key at `selector._domainkey.domain` in DNS, as defined in [RFC 6376](https://datatracker.ietf.org/doc/html/rfc6376), and checks that the signed headers and body are unchanged.

On Amazon SES you never handle the key yourself. With [Easy DKIM](https://docs.aws.amazon.com/ses/latest/dg/send-email-authentication-dkim-easy.html), AWS manages the key pair and you publish three CNAME records that point at it. SES then signs as your domain with a 2048-bit key by default.

Because the signature travels with the message, DKIM usually survives forwarding, where SPF does not. That makes DKIM the more reliable of the two for DMARC.

## DMARC: alignment, policy, and reports

DMARC is a TXT record at `_dmarc.yourdomain.com`:

```text
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
```

A message passes DMARC when SPF or DKIM passes **and** the domain it passed for is aligned with the From address. By default alignment is relaxed: `mail.example.com` aligns with `example.com` because they share the same organizational domain.

The `p` tag says what receivers should do with mail that fails:

| Policy | Meaning | Use it when |
| --- | --- | --- |
| `p=none` | Take no action, just report | You are starting out and reading reports |
| `p=quarantine` | Treat failing mail as suspicious (usually spam folder) | Reports show your own services all pass |
| `p=reject` | Reject failing mail | Quarantine has run cleanly |

The `rua` tag is where receivers send aggregate reports: XML summaries of which IPs sent mail as your domain and whether it passed. They are how you find a forgotten service before you enforce anything.

DMARC is now defined by [RFC 9989](https://datatracker.ietf.org/doc/html/rfc9989) (May 2026), which replaced RFC 7489. One change worth knowing: the old `pct` tag for applying a policy to a percentage of mail was removed, so roll out with `none`, then `quarantine`, then `reject` instead.

## Worked example: a message sent through Amazon SES

You send from `hello@example.com` through SES. Here is what a receiver checks, with and without a custom MAIL FROM domain:

| Check | Default SES setup | With MAIL FROM `mail.example.com` |
| --- | --- | --- |
| SPF | Passes for an `amazonses.com` subdomain | Passes for `mail.example.com` |
| SPF aligned with `example.com`? | No | Yes (relaxed) |
| DKIM | Passes, `d=example.com` (Easy DKIM) | Passes, `d=example.com` |
| DKIM aligned? | Yes | Yes |
| DMARC | **Pass** (via DKIM) | **Pass** (via SPF and DKIM) |

Both pass, but the right column passes twice. If a mailing list rewrites the body and breaks the DKIM signature, aligned SPF can still carry DMARC. That is why Mailmark sets up a [custom MAIL FROM domain](https://docs.aws.amazon.com/ses/latest/dg/mail-from.html) on every domain. The exact records are in the [DNS records guide](/blog/dns-setup).

> **Stop checking DNS records by hand** Mailmark re-checks SPF, DKIM, and DMARC on every domain twice a day and scans blacklists, so a record deleted during a DNS change shows up on your dashboard. [Monitor your domains](https://www.mailmark.dev/?utm_source=guide&utm_medium=seo&utm_campaign=understanding-spf-dkim-and-dmarc&utm_content=middle)

## Getting to p=reject safely

1. Publish SPF and DKIM for every service that sends as your domain: your app's provider, your helpdesk, your marketing tool, your office suite.
2. Publish DMARC with `p=none` and a `rua` address.
3. Read the aggregate reports for a few weeks. Every IP that sends as your domain should be one of your services and pass in alignment.
4. Fix the stragglers: add the missing `include`, publish the missing DKIM records, or stop the service.
5. Move to `p=quarantine`, keep reading reports, then move to `p=reject`.

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| SPF `permerror` | Two SPF records, or more than 10 lookups | Merge into one record and drop unused includes |
| SPF passes, DMARC fails | SPF passed for your provider's bounce domain, not yours | Set up a custom MAIL FROM, or make sure DKIM signs as your domain |
| DKIM fails only on some messages | A mailing list or gateway changed the signed content | Rely on DKIM for direct mail; list mail is expected to fail sometimes |
| Reports show IPs you don't recognize | A forgotten service, or someone spoofing your domain | Add the service if it's yours; enforcement will block the rest |
| Mail rejected after moving to `p=reject` | A legitimate service that never passed in alignment | Go back to `p=quarantine` and fix that service first |

To test a domain from the outside, the free [deliverability checker](/tools/email-deliverability-checker) reads its SPF, DKIM, and DMARC records. For what else affects inbox placement, see the [email deliverability guide](/blog/email-deliverability).

## Frequently asked questions

### Do I need all three of SPF, DKIM, and DMARC?

Gmail and Yahoo require all three from anyone sending 5,000 or more messages a day, and Outlook.com does too. Smaller senders need SPF or DKIM at minimum, but publishing all three is cheap and protects your domain from spoofing.

### Why does DMARC fail when SPF passes?

SPF checks the envelope sender (the bounce address), not the From address people see. If that envelope domain belongs to your email provider, SPF passes for their domain but isn't aligned with yours, so it doesn't count toward DMARC.

### Does forwarding break SPF or DKIM?

Forwarding usually breaks SPF, because the forwarding server's IP isn't in your SPF record. DKIM usually survives, because the signature travels with the message, unless the forwarder changes the signed content.

### When should I move DMARC from p=none to p=reject?

When your aggregate reports show that every legitimate source of mail for your domain passes SPF or DKIM in alignment. Go through p=quarantine first and watch the reports again.

> **Authenticated mail for every product domain** Mailboxes, campaigns, and sequences on your own domains, with SPF, DKIM, DMARC, and MAIL FROM set up per domain on Amazon SES. [Try Mailmark free](https://www.mailmark.dev/?utm_source=guide&utm_medium=seo&utm_campaign=understanding-spf-dkim-and-dmarc&utm_content=end)


Published 2026-01-20. Updated 2026-10-22. 4 min read.

---

Mailmark - email hosting and campaigns for your own domain. Canonical page: https://www.mailmark.dev/blog/understanding-spf-dkim-and-dmarc | [llms.txt](https://www.mailmark.dev/llms.txt) | [OpenAPI](https://www.mailmark.dev/openapi.json) | [sitemap](https://www.mailmark.dev/sitemap.xml)
