SPF, DKIM & DMARC for Amazon SES.
Amazon SES is a "per-account" sender: there is no shared SPF line to paste onto your root domain and no domain-authentication wizard that manages your DNS for you. You verify your domain and turn on Easy DKIM — three per-account CNAME records SES generates — and, because SES's default envelope sender lives on amazonses.com, you optionally add a custom MAIL FROM subdomain to get SPF aligned to your own domain too. Once the DKIM CNAMEs resolve, SES signs every message with d=yourdomain.com, so DMARC passes on DKIM alignment even before you touch SPF.
Why authenticate Amazon SES?
SES hands you raw, high-deliverability sending infrastructure, but it deliberately does not publish authentication on your behalf the way a Mailchimp or SendGrid wizard does — that burden is yours, and skipping it is why SES mail so often lands in spam. Since February 2024, Gmail and Yahoo have required every bulk sender (roughly 5,000+ messages a day) to pass SPF, DKIM, and DMARC with alignment, and Microsoft began rejecting non-compliant mail in 2025. If you send through SES without enabling Easy DKIM, your messages are signed only with the shared amazonses.com key, nothing aligns to your domain, DMARC fails, and your reputation is pooled with every other unauthenticated SES tenant. Enabling Easy DKIM fixes the core of this in one move: SES signs as d=yourdomain.com, DKIM aligns, DMARC passes, and the sending reputation you build accrues to your own domain. A custom MAIL FROM domain then layers SPF alignment on top for the receivers that weight it.
The SPF reality for Amazon SES
Amazon SES is a per-account provider, not an "include" provider — for most people there is NO include:amazonses.com to add to your ROOT SPF record, and you should not add one there. By default SES sets the envelope MAIL FROM (the Return-Path / bounce address) to a subdomain of amazonses.com. SPF is therefore checked against amazonses.com's own published record and PASSES automatically — but it passes for amazonses.com, not for your domain, so it is not "aligned" and does nothing for DMARC on its own. That is by design and it is fine, because Easy DKIM carries DMARC through DKIM alignment (SES signs with d=yourdomain.com). If you also want SPF aligned to your domain — belt-and-suspenders, and useful because some receivers weight SPF alignment — you set up a custom MAIL FROM subdomain (for example mail.yourdomain.com) and publish v=spf1 include:amazonses.com ~all plus one MX record pointing at feedback-smtp.{region}.amazonses.com. Crucially, those two records go on the MAIL FROM SUBDOMAIN, never on your root SPF. Your root SPF stays untouched, SES adds zero DNS lookups to it, and include:amazonses.com appears only on that dedicated subdomain.
Two ways to set it up
Easy DKIM — 3 CNAMEs (recommended)
- SES generates a 2048-bit RSA key pair and you publish three CNAME tokens that delegate the key back to SES
- SES holds and rotates the private key — nothing for you to generate, store, back up, or rotate
- Publishing the three CNAMEs both verifies the domain identity and turns on DKIM signing in one step
- Works out of the box with d=yourdomain.com alignment, so DMARC passes on DKIM with no SPF changes
BYODKIM — 1 TXT (bring your own key)
- You generate the RSA key yourself (1024–2048 bit, PKCS#1 or PKCS#8, base64/PEM) and publish one selector._domainkey TXT with the public key
- Useful when policy requires you to own key custody, or you want to reuse one key across providers/regions
- You are responsible for key storage and rotation — SES never sees the private key
- A single DNS record instead of three, but no automatic key rotation
Step by step
- 1
Create (or open) the domain identity
Open the SES console at console.aws.amazon.com/ses, and under Configuration choose Identities → Create identity → Domain. Enter yourdomain.com. If the domain already exists, open it and use the Authentication tab instead.
- 2
Keep Easy DKIM at RSA_2048
In Advanced DKIM settings leave Identity type = Easy DKIM and DKIM signing key length = RSA_2048_BIT (the default and the stronger choice; RSA_1024_BIT is only a weaker legacy setting). Make sure DKIM signatures = Enabled. Choose BYODKIM only if you must supply your own key.
- 3
(Optional) Set a custom MAIL FROM domain
On the identity page, open the Custom MAIL FROM domain pane → Edit → tick "Use a custom MAIL FROM domain" and enter a dedicated subdomain like mail.yourdomain.com (used for nothing else). Set Behavior on MX failure to "Use default MAIL FROM domain" while DNS propagates.
- 4
Add the three DKIM CNAME records
SES shows three records shaped token1._domainkey → token1.dkim.amazonses.com (token2, token3 similarly). Add each as a CNAME exactly as shown. Publishing these both verifies the domain and enables DKIM — there is no TXT to paste for Easy DKIM.
- 5
Add the MAIL FROM MX and SPF (only if you enabled custom MAIL FROM)
On the MAIL FROM subdomain add one MX record, priority 10, value feedback-smtp.{region}.amazonses.com (region-specific, e.g. us-east-1), and one TXT record v=spf1 include:amazonses.com ~all. Both live on mail.yourdomain.com, not your root domain.
- 6
Publish or keep one DMARC record
Add a TXT record at _dmarc.yourdomain.com starting v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com. Keep exactly one _dmarc record for the whole domain — don't add a second one for SES.
- 7
Turn off the Cloudflare proxy on the CNAMEs
If your DNS is on Cloudflare, set each DKIM CNAME to "DNS only" (grey cloud). An orange-cloud proxied CNAME won't resolve to *.dkim.amazonses.com and DKIM verification will hang in pending.
- 8
Wait for SES to detect the records
Back in the console, the DKIM status moves to Verified/Successful and, if you set one, the custom MAIL FROM state moves to Success. Detection is usually minutes but SES allows up to 72 hours; SES emails you when each completes.
- 9
Request production access (leave the sandbox)
New accounts start in the SES sandbox — you can only send to verified addresses, capped at 200 messages/day and 1/second. In Account dashboard, choose Request production access, or your real mail never leaves no matter how perfect your DNS is.
- 10
Send a test and read the headers
Send a real message from an address on the domain and open it in Gmail → Show original. Confirm DKIM: PASS with d=yourdomain.com, SPF: PASS, and DMARC: PASS.
Records to add
Amazon SES generates the exact values in its setup wizard — these show the shape of what you'll add at your DNS host.
| Type | Host | Value |
|---|---|---|
| CNAME | token1._domainkey | token1.dkim.amazonses.comEasy DKIM key 1 — the token is unique to your account/region and SES rotates the key behind it |
| CNAME | token2._domainkey | token2.dkim.amazonses.comEasy DKIM key 2 (per-account token) |
| CNAME | token3._domainkey | token3.dkim.amazonses.comEasy DKIM key 3 (per-account token) |
| MX | feedback-smtp.us-east-1.amazonses.comCustom MAIL FROM only — priority 10, region-specific host; exactly one MX on this subdomain | |
| TXT | v=spf1 include:amazonses.com ~allCustom MAIL FROM only — goes on the MAIL FROM subdomain, NOT your root SPF | |
| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.comYour DMARC policy — one per domain, start at p=none |
Keep exactly one SPF (v=spf1) TXT record on your root domain — merge every sender into it. Two SPF records is itself an error.
The 10-lookup budget
SPF is capped at a hard 10 DNS lookups — go over and it returns a permerror and stops validating everywhere. Here's what Amazon SES's setup costs against that budget.
Amazon SES's recommended setup adds 0 lookups — all 10 stay free for the senders that do need an include.
DKIM
DKIM is the load-bearing record for SES, and Easy DKIM makes it hands-off. When you enable it, SES generates a 2048-bit RSA key pair (RSA_2048 is the console default; 1024-bit is only a weaker legacy option) and gives you three tokens. You publish them as CNAMEs — token1._domainkey.yourdomain.com → token1.dkim.amazonses.com, and the same for token2 and token3. Note the key length doesn't change what you store: Easy DKIM always publishes three short CNAMEs whether you pick 1024 or 2048, because the actual public key lives on SES's side of the CNAME, not in your zone. Because these are CNAMEs delegated to SES rather than TXT records you paste, SES holds the private key and can rotate the published keys behind those selectors without you ever editing DNS again. Every message is then signed with d=yourdomain.com, which is what aligns for DMARC. In the current SES console this same CNAME publication is also what verifies the domain identity (DKIM-based verification), so there's usually no separate _amazonses TXT token to add. Two caveats: on Cloudflare the CNAMEs must be DNS-only (grey cloud), and SES identities are per-AWS-region — sending from a second region generates its own three tokens that you must also publish. If you can't use CNAMEs, BYODKIM is the alternative: you generate the key and publish a single selector._domainkey TXT with the public key (and there the 2048-bit key does make a longer TXT value that some DNS hosts split into multiple strings), but then you own rotation.
DMARC
DMARC is a separate policy record on your root domain, not something SES publishes for you. Add one TXT record at _dmarc.yourdomain.com beginning v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com — p=none is monitor-only, so it won't affect delivery while you confirm SES mail passes aligned. The SES-specific nuance: because SES's default envelope MAIL FROM is a subdomain of amazonses.com, SPF passes but is not aligned to your domain, so on a default SES setup DMARC passes entirely on DKIM alignment. That means you must have Easy DKIM (or BYODKIM) enabled and verified before you tighten policy — with DKIM off, a default-MAIL-FROM SES setup fails DMARC outright. Once aggregate (rua) reports confirm SES is a consistent, aligned source over a week or two, move from p=none to p=quarantine and eventually p=reject. If you also set a custom MAIL FROM domain you'll get SPF alignment on top, giving you two independent ways to pass. Keep exactly one _dmarc record for the whole domain no matter how many senders you run — never add a second one for SES.
Check it actually worked
Don't trust the console badges alone — confirm on a real message. In SES, the identity's DKIM status should read Verified/Successful and, if you configured one, the custom MAIL FROM state should read Success. Then send yourself a test from an address on the domain, open it in Gmail, and choose ⋮ → Show original: you want DKIM: PASS showing d=yourdomain.com (not amazonses.com), plus DMARC: PASS. SPF will show PASS for your MAIL FROM subdomain if you set a custom one, or for amazonses.com if you didn't — the amazonses.com case is expected and DMARC still passes because DKIM carries it, so don't treat it as a failure. Run your domain through Qualisend's domain health check to confirm all three DKIM CNAMEs (and the MAIL FROM MX/SPF, if used) resolve, and once DMARC aggregate reports start arriving, drop one into the DMARC report analyzer — SES should appear as an aligned, passing source.
Common gotchas
- DNS setup
SES is per-region. Identities, the three DKIM tokens, and the feedback-smtp MX host are all scoped to one AWS Region. If you send from both us-east-1 and eu-west-1, each region issues its own three DKIM CNAMEs and its own regional MX — publish every region's records or mail from the unconfigured region won't authenticate.
- Coverage
New accounts start in the sandbox. Until you Request production access, SES only delivers to verified recipients, capped at 200 messages/day and 1/second — perfect DNS won't matter if you're still sandboxed.
- Coverage
SPF alignment is opt-in, not automatic. By default the envelope is a amazonses.com subdomain, so SPF passes but doesn't align and DMARC rides entirely on DKIM. Seeing "SPF: amazonses.com" is normal — only set a custom MAIL FROM if you specifically want SPF aligned too.
- Breaks auth
Never add include:amazonses.com to your ROOT SPF. It belongs only on the custom MAIL FROM subdomain. On the root it does nothing useful and needlessly burns one of your 10 SPF lookups.
- Coverage
Exactly one MX on the MAIL FROM subdomain. SES fails the custom MAIL FROM setup if that subdomain has more than one MX record, so use a dedicated subdomain (mail. or bounce.) that isn't used to send or receive anything else.
- DNS setup
Cloudflare proxy breaks DKIM. Set all three CNAMEs to "DNS only" (grey cloud); an orange-cloud proxied CNAME won't resolve to *.dkim.amazonses.com and the identity stays in pending.
- Breaks auth
Registrar host-doubling and trailing dots. Enter just the label (token1._domainkey, mail), not the full FQDN, if your panel auto-appends the domain; and where a host wants an FQDN for the MX/CNAME value, use a trailing dot so feedback-smtp.us-east-1.amazonses.com isn't mangled into ...amazonses.com.yourdomain.com.
- Coverage
"Behavior on MX failure = Reject message" is risky early. While DNS is propagating (or if the MX ever fails to resolve), Reject will bounce all your mail — leave it on "Use default MAIL FROM domain" until the state shows Success.
Build your SPF record
Amazon SES doesn't need an SPF include: on your root domain — use the generator to assemble one clean record for your other senders, and keep it to a single line.
Sending sources
Search for each platform you send email through and tick it.
Search for your email platform above, or .
This domain's own servers
Authorize the domain itself, if it sends mail directly (not through a platform above).
Other senders & IPs
Anything not in the list — another provider's SPF host, or specific IP addresses.
We add the include: prefix — enter the hostname your provider documents.
Policy for everyone else
What receivers should do with mail from any server not listed above (the all mechanism).
No senders yet, so every message would hit the ~all policy. Add the platforms you send through in step 1.
- Publish it as a TXT record at your root domain — host @ (the bare domain), value the full string above.
- Keep only one SPF record per domain. Merge every sending source into this single line — a second TXT record starting v=spf1 makes both invalid.
- Stay at or under 10 DNS lookups. Each include:, a and mx counts, and an include can trigger more lookups inside itself — ip4: and ip6: are free.
Authentication published? The next step is sending to a clean, verified list.
Verify a listAmazon SES SPF — FAQ
Related reading
Once it's published, confirm everything resolves with the domain health check, then read who's sending as you with the DMARC report analyzer. Browse all sending sources in the generator. Authentication is only half of deliverability, though — a listed sending IP or domain still lands you in spam no matter how clean your SPF is, so it's worth watching the blacklists with blacklist monitoring.
Authenticated — now keep the list clean
Passing SPF, DKIM, and DMARC gets you to the inbox; a clean list keeps you there. Verify yours — start free with 100 credits, no card required.