Configure DKIM for AWS SES (Step-by-Step Guide)
Enable Easy DKIM on AWS SES in about five minutes: three CNAME records, one CLI flag, and a dig check to confirm the keys propagated.
By SESMetric Editorial
DKIM signs every outbound message with a private key tied to your domain, and receivers verify the signature against a public key published in DNS. Without it, Gmail and Outlook downgrade your mail, throttle delivery, or drop it into spam outright. With it, your sending domain accumulates a reputation that survives IP rotation and shared infrastructure.
This guide walks through the fastest reliable way to configure DKIM AWS SES uses by default: Easy DKIM. You provide a domain, SES generates a 2048-bit key pair, and you publish three CNAME records pointing at Amazon-hosted public keys. AWS rotates the underlying keys on its side; your DNS never changes again.
What you need before you start
- An AWS account with SES access in the region you actually send from. SES is regional, and DKIM records are per-region — a verified identity in
us-east-1does not authenticate mail sent througheu-west-1. - A verified sending domain (not just a single address). If you have not done that yet, finish domain verification first, then return to this guide.
- DNS access at your registrar or DNS provider (Route 53, Cloudflare, Namecheap, etc.) with permission to add CNAME records under the domain you want to sign.
- Optional but recommended: the AWS CLI v2, configured with credentials that include
ses:PutEmailIdentityDkimAttributesandses:GetEmailIdentity.
How DKIM works on SES in one paragraph
When SES signs a message, it adds a DKIM-Signature header that names a selector (for example, abcd1234) and your domain. The receiver looks up abcd1234._domainkey.example.com in DNS, follows the CNAME to an Amazon-hosted TXT record containing the public key, and uses that key to verify the signature against the message body and headers. Easy DKIM creates three selectors so AWS can rotate keys without breaking signing. You publish three CNAMEs once; AWS swaps the targets transparently.
Configure DKIM AWS SES setup in the console
- Open the SES console in the region you send from.
- Go to Verified identities and click the row for your domain.
- Open the Authentication tab and find the DKIM section.
- Click Edit, choose Easy DKIM, select RSA_2048_BIT, and tick Enabled under DKIM signatures. Save.
SES now shows three CNAME records under Publish DNS records. They look like this:
selector1._domainkey.example.com. CNAME selector1.dkim.amazonses.com.
selector2._domainkey.example.com. CNAME selector2.dkim.amazonses.com.
selector3._domainkey.example.com. CNAME selector3.dkim.amazonses.com.
The selector names in your account will be random hex strings rather than selector1/2/3 — copy them verbatim from the console. Each record name uses the _domainkey subdomain, which is required by RFC 6376.
Add the three records exactly as shown at your DNS provider. Most providers strip a trailing dot or auto-append the zone — paste the host as the SES console displays it, then preview the final FQDN before saving. A common mistake is to paste selector1._domainkey.example.com.example.com because the provider already scoped the input to the zone.
Enable signing via the AWS CLI
If you scripted identity creation, or the console toggle is greyed out because the identity was created by a Terraform run, enable signing with the CLI:
aws sesv2 put-email-identity-dkim-attributes \
--email-identity example.com \
--signing-enabled \
--region us-east-1
Verify the identity reports both DkimEnabled: true and Status: SUCCESS for tokens:
aws sesv2 get-email-identity \
--email-identity example.com \
--region us-east-1 \
--query 'DkimAttributes'
The response includes Tokens, an array of three selector strings. Confirm those are the same selectors you just published in DNS. If you accidentally published an older identity's tokens (this happens when you delete and recreate the identity), Status stays stuck on PENDING until you swap the records.
Verify DNS propagation
Until every DNS resolver in the world sees your CNAMEs, SES marks DKIM as PENDING. Confirm propagation from your own machine with dig:
dig CNAME selector1._domainkey.example.com +short
dig CNAME selector2._domainkey.example.com +short
dig CNAME selector3._domainkey.example.com +short
Each should return the matching *.dkim.amazonses.com. target. If you get an empty response, the record has not propagated yet or the host name is wrong. Cross-check with a public resolver to rule out a stale local cache:
dig CNAME selector1._domainkey.example.com @1.1.1.1 +short
dig CNAME selector1._domainkey.example.com @8.8.8.8 +short
Once all three resolve, SES typically flips the identity to Verified and DkimEnabled: true within a few minutes. Send a test message to a Gmail address, open Show original, and confirm DKIM: PASS with domain example.com.
Common problems
DKIM failures on SES almost always come from one of four sources. Walk through each before opening a support ticket.
Apex CNAME unsupported
You cannot place a CNAME on the zone apex (example.com itself), but you can — and must — place CNAMEs on _domainkey.example.com. The records SES generates are all under the _domainkey subdomain, so this only bites teams that try to "tidy up" the records by flattening them into the apex with a provider-specific ALIAS or ANAME. Do not do that. Publish the literal CNAMEs SES gave you.
DNS propagation is slower than the console suggests
The SES console may keep reporting Verification status: Pending for up to 72 hours even when dig already resolves your records. The bottleneck is usually a long TTL on a parent zone or a slow secondary nameserver. Set TTL to 300 seconds before adding the records if you anticipate iterating, and re-check with dig +trace selector1._domainkey.example.com to see which nameserver is lagging. SES does not re-poll on demand; it polls on its own schedule.
Wrong region
A verified identity in us-east-1 does not sign mail sent from a client pointed at email-smtp.eu-west-1.amazonaws.com. Either re-verify the identity in the second region (you will get a fresh set of three CNAMEs — publish those too, with different selectors, alongside the originals) or route all sending through the original region. If your CI uses AWS_REGION from environment, double-check the value on the production host.
Identity recreated, tokens not updated
If Terraform, CloudFormation, or a manual delete-and-recreate replaced the identity, the new identity has new selector tokens. The old CNAMEs at your DNS provider now point at orphaned keys. Pull the current tokens with aws sesv2 get-email-identity --email-identity example.com --query 'DkimAttributes.Tokens', then update the three CNAME records to match. Until you do, DkimStatus stays PENDING and signed mail starts failing verification at the receiver.
TXT records instead of CNAMEs
Some teams discover an older AWS guide that uses TXT records under _domainkey with the raw public key inline. That mode is called BYODKIM (Bring Your Own DKIM) and only applies when you generate the key pair yourself outside SES. With Easy DKIM, only CNAMEs work; AWS rejects DKIM verification if you publish a TXT record at selectorN._domainkey.example.com because the resolver chain expects to follow a CNAME to the Amazon-hosted zone. Pick one mode and stick with it.
Confirming end-to-end on a real message
A quick way to prove DKIM is working in production, not just in dig, is to send a message to an inbox you control and inspect the raw headers. In Gmail, open the message, click the three-dot menu, and choose Show original. Look for these two lines near the top:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=abcd1234; t=1747629012; ...
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=abcd1234
The s= selector must match one of the three selectors you published. The d= domain must match the address in your From header — if it does not, you are looking at relaxed alignment failure, which DMARC will eventually reject even if DKIM technically passes. For raw SMTP you can grep the same headers from a Postfix log or any test tool that prints the full envelope.
Where to go next
DKIM on its own protects against spoofing of the message body and most headers, but receivers want a full authentication stack. After SES reports Verified, publish an SPF record listing amazonses.com and a DMARC policy aligned to your DKIM domain. Then point your application at SMTP or the SES API and start sending — every message will be signed automatically, with no further code changes.
If you also need application-level credentials for SMTP delivery, see the SESMetric guide on configuring SMTP credentials, and the domain verification walkthrough if you skipped that step earlier.