Send transactional and bulk email from your app with SES: verify identities, prove ownership with DKIM, move out of the sandbox, send messages, manage bounces and complaints with configuration sets, and protect your sender reputation.
SES (Simple Email Service) sends email from your application — password resets, receipts, newsletters. Why use it over a raw mail server: deliverability. Email providers distrust unknown senders; SES gives you the authentication and reputation tooling that gets your mail into inboxes instead of spam folders.
Check your current sending quota and how much you've used today
aws ses get-send-quotaBefore SES will send "from" an address or domain, you must prove you own it ("verify" it). Why: it stops people sending mail pretending to be you. Verify a whole domain (so you can send from any address on it) or a single email for quick tests.
Verify a single email address (you'll get a confirmation email)
aws ses verify-email-identity --email-address you@example.comVerify a whole domain
aws sesv2 create-email-identity --email-identity example.comList what's verified
aws ses list-identitiesDKIM signs each message with a cryptographic key, and receivers check it against a record in your DNS. Why: it proves the mail genuinely came from your domain and wasn't altered — a major factor in not being marked as spam. SES can manage the keys for you ("Easy DKIM").
Turn on Easy DKIM and get the DNS records to publish
aws sesv2 put-email-identity-dkim-attributes \
--email-identity example.com --signing-enabledaws sesv2 get-email-identity --email-identity example.com \
--query 'DkimAttributes.Tokens'Add the returned CNAME records to your domain's DNS (Route 53) to finish.
New SES accounts start in a "sandbox": you can only send TO verified addresses, at a low rate. Why: it stops spammers abusing fresh accounts. Once your app is ready, you request production access; AWS then raises your quota and lets you email anyone.
Request to leave the sandbox (raises limits, allows any recipient)
aws sesv2 put-account-details \
--production-access-enabled \
--mail-type TRANSACTIONAL \
--website-url https://example.com \
--use-case-description "Password resets and order receipts for our app."With a verified identity you can send. Why start simple: this single call proves the whole pipeline works end to end before you wire it into your app. Real apps usually call the SES API from their backend with the AWS SDK rather than the CLI.
aws ses send-email \
--from you@example.com \
--destination 'ToAddresses=friend@example.com' \
--message 'Subject={Data=Hello from SES},Body={Text={Data=It works!}}'A configuration set is a profile attached to your sends that captures what happens to them — deliveries, bounces, complaints, opens. Why: you MUST handle bounces (bad addresses) and complaints (spam reports) or your reputation tanks. SES publishes these events so you can stop mailing bad addresses automatically.
Create a configuration set
aws sesv2 create-configuration-set --configuration-set-name app-mailSend bounce/complaint events to an SNS topic your app subscribes to
aws sesv2 create-configuration-set-event-destination \
--configuration-set-name app-mail \
--event-destination-name bounces \
--event-destination '{"Enabled": true,"MatchingEventTypes": ["BOUNCE","COMPLAINT"],"SnsDestination": {"TopicArn": "arn:aws:sns:us-east-1:111122223333:ses-events"}}'Your "reputation" is how much mail providers trust you, driven by low bounce/complaint rates. SES shows it on a dashboard. Why dedicated IPs: by default you share IPs with other senders; a dedicated IP gives you full control of your reputation — worth it only at high, steady volume that you "warm up" gradually.
Turn on reputation metrics so bounce/complaint rates appear in CloudWatch
aws sesv2 put-account-dedicated-ip-warmup-attributes 2>/dev/null || trueWatch the two numbers that matter most (keep bounces & complaints low)
aws cloudwatch get-metric-statistics --namespace AWS/SES \
--metric-name Reputation.BounceRate \
--start-time 2024-05-01T00:00:00Z --end-time 2024-05-02T00:00:00Z \
--period 86400 --statistics Average