To add email authentication in AWS Route 53, you create three record types in your hosted zone: a TXT record for SPF at the zone root, CNAME records for DKIM (Amazon SES publishes these for you when Route 53 hosts your domain), and a TXT record for DMARC at the _dmarc subdomain. Route 53 uses a Create Record flow where the record name, type, and value each go in their own field, and the quoting rules for TXT values are stricter than most DNS hosts.
This guide covers the exact fields, the two quoting mistakes that break Route 53 TXT records, and why you should start DMARC at p=none before moving to enforcement.
Reads public DNS only. Nothing is stored unless you save the domain to an account.
Before you start: know what you are publishing
SPF, DKIM, and DMARC are three separate DNS records that do three different jobs. SPF lists which servers may send mail using your domain in the envelope. DKIM adds a cryptographic signature that survives the trip to the inbox. DMARC tells receivers what to do when a message fails both checks and, just as important, it turns on the reporting that shows you who is sending as you. If you want the full mental model first, read SPF, DKIM, and DMARC explained.
You will need access to the Route 53 console and the sending values from your email provider. If you send through Amazon SES, most of this is close to automatic. If you send through Google Workspace, Microsoft 365, or an ESP like SendGrid or Mailchimp, you paste values those providers give you.
Step 1: Add the SPF record (TXT at the zone root)
In the Route 53 console, open Hosted zones, click your domain, then Create record.
- Record name: leave this field blank. An empty name in Route 53 means the zone apex, which is your root domain. Do not type
@here. Route 53 does not use@notation, and typing it creates a literal@subdomain that does nothing. - Record type: TXT
- Value: your SPF string, wrapped in double quotes.
A minimal SPF record for a domain that sends only through Amazon SES looks like this:
"v=spf1 include:amazonses.com -all"
If you send through more than one provider, add each include on the same line. For example, SES plus Google Workspace:
"v=spf1 include:amazonses.com include:_spf.google.com -all"
Two rules matter in Route 53. First, the whole value must sit inside double quotes, because Route 53 stores the raw TXT value and does not add quotes for you. Second, you publish exactly one SPF record per domain. Two separate v=spf1 records is a permanent error (PermError) and receivers will treat SPF as broken. If you already have an SPF record, edit it and add the new include rather than creating a second record.
Watch your DNS lookup count. SPF allows a maximum of 10 DNS-querying mechanisms, and each include can trigger several. If you stack many providers you can blow past the limit, which also causes a PermError. See fix SPF too many DNS lookups if you are close to the ceiling.
Use -all (hard fail) once you are confident every legitimate sender is listed. If you are still discovering senders, ~all (soft fail) is a safer temporary choice. Avoid +all, which authorizes the entire internet to send as you and is covered in why +all is dangerous.
Step 2: Add DKIM (SES auto-publishes CNAMEs into your zone)
DKIM is where Route 53 hosting pays off. When your domain's zone is hosted in Route 53 and you verify that domain identity in Amazon SES, SES offers to publish the DKIM records for you. With Easy DKIM, SES generates three CNAME records that point to keys SES manages, and if you approve the write, they land in your hosted zone automatically. You do not hand-type anything.
The three records look like this pattern, one per selector:
selector1._domainkey.example.com CNAME selector1.dkim.amazonses.com
A few things to know:
- SES DKIM uses CNAME records, not TXT records. The CNAME points at an SES-hosted key so SES can rotate it without you touching DNS. If you want the reasoning behind CNAME delegation versus a raw TXT key, read DKIM CNAME vs TXT record.
- Leave the three CNAMEs in place permanently. Deleting them breaks DKIM and, over time, breaks alignment for DMARC.
- If SES does not auto-publish (for example, you verified the identity before delegating the zone, or you are using BYODKIM), copy the three CNAME name/value pairs from the SES console into Route 53 by hand using Create record, type CNAME.
Other providers behave differently. Google Workspace and Microsoft 365 give you a single TXT record at a selector like google._domainkey or a CNAME, which you add the same way. General DKIM setup across providers is in how to set up DKIM.
Step 3: Add the DMARC record (TXT at _dmarc)
DMARC lives at a fixed subdomain: _dmarc. In Route 53, click Create record again.
- Record name:
_dmarc - Record type: TXT
- Value: your DMARC policy in quotes.
Start here, at monitoring only:
"v=DMARC1; p=none; rua=mailto:dmarc@example.com"
The p=none policy tells receivers to enforce nothing yet, but the rua tag asks them to send aggregate reports to the mailbox you name. Those reports are how you learn which sources are sending as your domain and whether they pass SPF and DKIM alignment. Do not skip this stage. Publishing p=reject on day one, before you have seen the reports, is the fastest way to silently block your own invoices, ticketing system, or marketing platform.
Once reports confirm that every legitimate source authenticates and aligns, tighten to p=quarantine and then p=reject. The staged path is laid out in how to move DMARC from none to reject, and the difference between the three policies is in DMARC policy: none, quarantine, or reject.
The record name field is the single most common DMARC mistake in Route 53. If you leave it blank, you publish DMARC at the root, where no receiver looks for it. It must be _dmarc. When you enter it, Route 53 will show the full name as _dmarc.example.com, which is correct.
Step 4: Verify before you trust it
Route 53 propagation is usually fast, often under a minute inside the AWS resolvers, though public resolvers can lag by the record's TTL. Give it a few minutes, then confirm all three records resolve and parse correctly. Run your domain through the SPFWise checker at the top of this page. It reads your live SPF, DKIM, and DMARC records, flags quoting errors, counts your SPF lookups, checks DKIM alignment, and returns a grade with specific fixes.
Send one real test message to an external inbox you control and open the raw headers. You want to see spf=pass, dkim=pass, and dmarc=pass. Reading those lines is covered in how to read the Authentication-Results header. If SPF passes but DKIM fails, or the reverse, that is usually an alignment problem rather than a broken record, and why DKIM can fail when SPF passes walks through it.
Frequently asked questions
Do I use @ for the root domain in Route 53?
No. Route 53 does not use @ notation. To publish a record at the zone apex (your root domain), leave the Record name field blank. Typing @ creates a useless @ subdomain and your SPF record will not be found.
Does Route 53 add quotes to TXT records automatically?
No. You must wrap the entire TXT value in double quotes yourself, for example "v=spf1 include:amazonses.com -all". Route 53 stores the value literally. A missing quote is the most common reason a Route 53 SPF or DMARC record fails to parse.
How does Amazon SES publish DKIM into Route 53?
When your domain's zone is hosted in Route 53 and you verify the domain in SES with Easy DKIM, SES offers to write three CNAME records directly into your hosted zone. Approve it and the DKIM CNAMEs appear automatically. Leave them in place, since SES rotates the underlying keys behind those CNAMEs without any further DNS work from you. See Amazon SES SPF, DKIM, and DMARC setup for the full SES walkthrough.
Should I start DMARC at p=reject in Route 53?
No. Start at p=none with a rua address so you receive aggregate reports without blocking any mail. Once the reports confirm every legitimate sender authenticates and aligns, move to p=quarantine, then p=reject.