SendOps

Guide

How to set up Amazon SES, properly, from scratch.

The complete Amazon SES tutorial: verify your domain, get DKIM, SPF, and DMARC right, wire up event destinations, and escape the sandbox — with the exact DNS records and a production-access request template that gets approved.

Updated July 14, 2026 · 15 min read

Getting Started

What you're setting up, and why it matters

Amazon SES is the cheapest serious way to send email — see our SES pricing breakdown — but it hands you raw infrastructure, not a finished product. Getting started with Amazon SES means doing the work an email provider would normally hide from you: proving to the world's inbox providers that you own your domain, publishing the DNS records that authenticate your mail, building your own visibility into bounces and complaints, and convincing AWS to let you send to real people at all.

This guide walks the whole path in order. Each step builds on the last, and skipping any of them is how SES setups end up in spam folders or suspended accounts. Follow it top to bottom and you'll finish with a fully authenticated, observable, production-ready sending setup.

What you'll need

  • An AWS account with permission to use SES and IAM
  • Access to your domain's DNS (Route 53, Cloudflare, your registrar — anywhere you can add records)
  • A decision about which AWS region you'll send from — SES identities and quotas are per-region, so pick the region your application runs in and stay consistent
  • 30–60 minutes of hands-on time, plus DNS propagation and roughly a day for AWS to review production access

Step 1

Verify your domain and enable DKIM

Everything in SES starts with an identity — a domain or email address you've proven you control. Verify a domain, not just an email address: a domain identity covers every address at that domain, enables DKIM signing, and is what inbox providers actually evaluate. You can additionally verify individual addresses later if you need to send from a domain you don't fully control, but the domain identity is the foundation.

  1. Open the SES console in your chosen region and go to Identities → Create identity.
  2. Choose Domain and enter your sending domain (e.g. yourdomain.com).
  3. Leave Easy DKIM enabled with a 2048-bit key — this is the default and the right choice for almost everyone.
  4. SES generates three CNAME records. Add all three at your DNS provider exactly as shown.
  5. Wait for the identity status to change to Verified. This usually takes minutes once DNS propagates, but can take up to 72 hours.

The three CNAMEs look like this (values are unique to your domain — copy yours from the console, don't copy these):

abc123token._domainkey.yourdomain.com  CNAME  abc123token.dkim.amazonses.com
def456token._domainkey.yourdomain.com  CNAME  def456token.dkim.amazonses.com
ghi789token._domainkey.yourdomain.com  CNAME  ghi789token.dkim.amazonses.com

DKIM (DomainKeys Identified Mail) cryptographically signs every message so receivers can verify it wasn't forged or tampered with. With Easy DKIM, AWS manages the signing keys and rotates them automatically — the CNAMEs delegate key publication to Amazon, which is why you never handle the keys yourself. If your DNS provider auto-appends your domain name to record hosts, enter only the abc123token._domainkey part; a doubled domain (...yourdomain.com.yourdomain.com) is the most common reason verification stalls.

Step 2

Set a custom MAIL FROM domain for SPF alignment

By default, SES sends your mail with a MAIL FROM (envelope sender) on amazonses.com. SPF technically passes — but it passes for Amazon's domain, not yours. That means SPF doesn't align with your From address, and DMARC (step 3) then depends entirely on DKIM. A custom MAIL FROM domain fixes this and makes your authentication fully redundant.

  1. Open your domain identity in the SES console and find the Custom MAIL FROM domain section under Authentication.
  2. Choose a subdomain of your sending domain — mail.yourdomain.com is the convention. It must not be a domain you use for anything else.
  3. Publish the two records SES gives you.

As of July 2026 the records look like this, with the MX host varying by region (the console shows your exact values):

mail.yourdomain.com  MX   10 feedback-smtp.us-east-1.amazonses.com
mail.yourdomain.com  TXT  "v=spf1 include:amazonses.com ~all"

The MX record lets SES receive bounce feedback at your MAIL FROM domain; the TXT record is the SPF policy authorizing Amazon's servers to send for it. Once both resolve, SES automatically starts using the custom MAIL FROM, and SPF now passes and aligns with your domain. This step is optional in the sense that SES will work without it — and skipping it is one of the most common reasons otherwise-correct SES setups underperform in deliverability.

Step 3

Publish a DMARC record

DMARC ties DKIM and SPF together: it tells receiving servers what to do with mail claiming to be from your domain that fails authentication, and it gets you aggregate reports about who is sending as you. Gmail, Yahoo, and Microsoft increasingly expect a DMARC record from anyone sending meaningful volume — as of 2026, bulk senders to Gmail and Yahoo are required to have one. SES will happily send without it; your deliverability will quietly suffer.

Add a TXT record at _dmarc.yourdomain.com:

_dmarc.yourdomain.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com"

Start with p=none — monitor-only mode. It satisfies the "has DMARC" requirement, generates reports, and blocks nothing while you confirm all your legitimate mail passes. After a few weeks of clean reports, tighten to p=quarantine (failures go to spam) and eventually p=reject (failures are refused outright). A domain sitting at p=none forever is protected on paper only — put the graduation on your calendar.

Because you completed steps 1 and 2, your mail now passes DMARC two independent ways: DKIM-aligned and SPF-aligned. Either one alone is enough for a pass, so a transient DNS hiccup on one mechanism no longer tanks delivery.

Step 4

Create a configuration set and wire event destinations

Out of the box, SES tells you almost nothing about what happens after you call the API. Did the message deliver? Bounce? Get marked as spam? Without event destinations you're flying blind — and blind is dangerous, because AWS reviews accounts whose bounce rate approaches roughly 5% or whose complaint rate approaches roughly 0.1%, and can pause sending entirely. Wire up visibility before you send your first real email, not after your first incident.

  1. In the SES console, go to Configuration sets → Create set. Name it something like default or transactional.
  2. Inside the set, add an event destination and select the event types: at minimum send, delivery, bounce, complaint — and add open and click if you want engagement data.
  3. Pick where events go: SNS (simple, fan out to email/webhook/queue), EventBridge (route to Lambda, archive, or third-party tools — the most flexible choice for new setups), or Kinesis Data Firehose (stream to S3/Redshift for analytics at volume).
  4. Pass the configuration set name on every send (the ConfigurationSetName parameter), or set it as the identity's default configuration set so it applies automatically.

Then act on the events. At minimum: when an address hard-bounces or complains, stop sending to it. SES maintains an account-level suppression list that catches hard bounces and complaints automatically (verify it's enabled for both in your account settings) — but it only protects your SES account, not your sender reputation with addresses you keep trying elsewhere. Your application should record these events in its own database too. If you'd rather have dashboards, per-message search, and automatic suppression handled for you, that's exactly what SendOps observability builds on top of these same events.

Step 5

Leave the sandbox: request production access

Every new SES account starts in the Amazon SES sandbox, per region. In the sandbox you can only send to verified addresses, at most 200 messages per 24 hours, and at most 1 message per second. It exists so spammers can't spin up throwaway AWS accounts and blast the world — but it also means your integration will appear to work perfectly in testing and then fail in production the moment you email a real customer. Plan your exit before launch, not during it.

To request production access: SES console → Account dashboard → Request production access. You'll fill in your mail type, website, and a use-case description. AWS Trust & Safety reviews the request — typically within about 24 hours as of July 2026. The single biggest factor in approval is specificity. Reviewers want evidence you understand consent, bounces, and complaints. Vague requests get denied; detailed, honest ones get approved.

A production-access request that gets approved

Adapt this template with your real details — reviewers can tell when numbers and processes are invented.

Use case:
We operate [product name] ([https://yourdomain.com]), a [one-line
description]. We will use SES to send transactional email:
account confirmations, password resets, receipts, and billing
notifications. All email is triggered by a user's own action in
our product.

How recipients opt in:
Every recipient is a registered user who created an account and
confirmed their email address via double opt-in. We do not send
to purchased, rented, or scraped lists, and we do not send cold
outreach.

Expected volume:
Approximately [X] emails/day at launch, growing to an estimated
[Y]/day within 6 months as our user base grows.

Bounce and complaint handling:
We use an SES configuration set with an event destination that
delivers bounce and complaint events to [EventBridge/SNS]. Hard
bounces and complaints are written to our database and the
address is suppressed from all future sending automatically. We
also rely on the SES account-level suppression list. We monitor
bounce and complaint rates and alert if they approach 2% and
0.05% respectively — well under AWS's review thresholds.

Unsubscribes:
Every non-essential email includes a one-click unsubscribe link
(List-Unsubscribe header and footer link). Unsubscribes take
effect immediately.

If you're denied, don't panic and don't argue — rewrite with more specifics and resubmit. The most common gaps are missing detail on opt-in ("how did these people agree to receive email from you?") and no concrete bounce/complaint process. If you'd rather not write this at all, SendOps composes, submits, and tracks the production-access request for you as part of setup.

Once approved, you'll get a starting sending quota — commonly 50,000 emails per 24 hours, though it varies by region and account — and it grows automatically as you send consistently with low bounce and complaint rates. For how quotas work and how to raise them, see our guide to SES sending limits.

Step 6

Send your first email and verify everything

Time to prove the whole chain works. While still in the sandbox you can test by verifying your own address as a recipient identity, or use the SES mailbox simulator addresses (like success@simulator.amazonses.com and bounce@simulator.amazonses.com) which work without verification and don't count against your reputation — the bounce simulator is the easiest way to confirm your event pipeline fires.

From the AWS CLI, with your configuration set attached:

aws sesv2 send-email \
  --region us-east-1 \
  --from-email-address "hello@yourdomain.com" \
  --destination "ToAddresses=you@yourdomain.com" \
  --configuration-set-name "default" \
  --content 'Simple={Subject={Data="SES is live"},Body={Text={Data="First email through our own SES."}}}'

Then verify three things:

  1. Authentication. Open the received message in Gmail and choose "Show original" (or inspect the raw headers elsewhere). You want dkim=pass, spf=pass, and dmarc=pass — with SPF passing on your mail.yourdomain.com MAIL FROM, not amazonses.com.
  2. Events. Confirm the send and delivery events arrived at your event destination. Then send to bounce@simulator.amazonses.com and confirm the bounce event shows up too.
  3. Credentials. Check how your application authenticates to SES. Prefer IAM roles (instance profiles, ECS/EKS task roles, Lambda execution roles) over long-lived access keys. If you must use keys — for SMTP, or apps outside AWS — scope them to ses:SendEmail on your identities only, and rotate them.

Step 7

The gotchas checklist

These are the failure modes that account for nearly every "SES suddenly stopped working" story. Run through the list before you ship.

  • Region matches. Your identity, quota, and production access are all per-region. Sending from eu-west-1 when you verified in us-east-1 fails — and an SDK silently defaulting to another region produces exactly that.
  • You're actually out of the sandbox. The classic launch-day incident: everything worked in testing (verified addresses), then production emails to real users bounce with "Email address is not verified." Check the Account dashboard shows production access in your sending region.
  • DMARC exists and has a graduation plan. No _dmarc record means degraded treatment at major mailbox providers; a permanent p=none means no spoofing protection.
  • Event destinations are wired and consumed. If bounces and complaints go nowhere, your first warning of a reputation problem is an AWS review notice. Confirm events flow and that something suppresses bad addresses.
  • The configuration set is actually attached. Creating a config set does nothing unless every send references it or it's set as the identity's default. A perfect pipeline receiving zero events usually means this.
  • No IAM key sprawl. One set of long-lived keys copied into five services becomes unrotatable. Use roles wherever the code runs in AWS; keep keys scoped and few elsewhere.
  • Bounce and complaint rates have alarms. AWS reviews around 5% bounces / 0.1% complaints. Alert yourself well below that — 2% and 0.05% are sensible tripwires.

The Shortcut

Or: two minutes with CloudFormation

Everything above is real work the first time and tedious work every time after. SendOps compresses steps 1–6 into a single CloudFormation stack deployed in your own AWS account — nothing routes through shared infrastructure, and there are no stored AWS keys.

Identities and DNS, prepared

Your domain identity is created with Easy DKIM, and SendOps hands you every DNS record — DKIM CNAMEs, MAIL FROM MX and SPF, DMARC — ready to copy into your provider, then confirms when they resolve.

Config sets and events, wired

Configuration sets and EventBridge destinations are provisioned by the stack, so delivery, bounce, and complaint visibility exists from the first email — feeding dashboards and per-message search with automatic suppression.

Production access, handled

SendOps composes your production-access request from your actual setup, submits it, and tracks it until AWS approves — no blank text box, no guessing what reviewers want.

A marketing platform on top

Broadcasts, workflows, segmentation, and templates that send through your SES account — email marketing on Amazon SES without gluing tools together yourself.

The infrastructure setup is available on the free plan. If you enjoyed doing it by hand, everything SendOps provisions is visible and yours — it's your AWS account, after all.

FAQ

Amazon SES setup, answered

How long does Amazon SES setup take?

The hands-on work takes 30–60 minutes: creating identities, adding DNS records, and wiring event destinations. The waiting is what stretches it out — DNS propagation usually completes within an hour but can take up to 72 hours, and AWS typically reviews production access requests within about 24 hours. Plan for a working setup in one sitting and a production-ready account within a day or two.

How do I get out of the SES sandbox?

Open the SES console, go to Account dashboard, and choose Request production access. Describe what you send, how recipients opted in, and how you handle bounces, complaints, and unsubscribes. AWS Trust & Safety reviews the request, typically within about 24 hours. Specific, honest answers get approved; vague ones get denied. SendOps can compose, submit, and track the request for you.

What DNS records does SES need?

Three CNAME records for Easy DKIM (created when you verify your domain), plus an MX and a TXT record if you set up a custom MAIL FROM domain for SPF alignment, plus a TXT record at _dmarc.yourdomain.com for DMARC. That's six records for a fully authenticated setup. SES itself only requires the DKIM CNAMEs to verify the domain — the rest is what makes your mail actually land in inboxes.

Why was my production access request denied?

Almost always because the request was vague. AWS wants specifics: what kind of email you send, exactly how recipients opted in, expected volume, and how you process bounces, complaints, and unsubscribes. "We send emails to our users" is not enough. Rewrite the request with concrete details — including that you have event destinations wired for bounce and complaint handling — and resubmit. Denials are not permanent.

Do I need a dedicated IP to start?

No. Shared IPs are the right choice for almost everyone starting out — Amazon manages their reputation, and they perform well for senders with good list hygiene. Dedicated IPs cost extra, require weeks of warm-up, and only make sense at sustained high volume, typically hundreds of thousands of emails per month. Start on shared IPs and revisit the question later if your volume justifies it.

Get Started

Set up SES the fast way

One CloudFormation stack: identities, DKIM records, configuration sets, EventBridge, and a production-access request that gets approved. Free plan, your AWS account, your reputation.