Amazon SES: Why Your Emails Aren't Being Delivered

April 10, 2026 — Nick Allevato

Amazon SES is one of the most cost-effective ways to send transactional and marketing email at scale. It’s also one of the services where a misconfiguration can silently drop emails with no obvious indication that anything is wrong.

The failure modes are predictable. Here’s how to diagnose each one.


Problem 1: You’re still in sandbox mode

Every new SES account starts in the sandbox. In sandbox mode:

  • You can only send to email addresses you’ve explicitly verified
  • Your sending limits are capped at 200 emails per day and 1 per second
  • Emails to unverified addresses fail silently or return an error

This catches teams constantly. You verify your sending domain, test successfully to your own address, deploy to production, and then nothing arrives for anyone else — because everyone else is an unverified address.

Fix: Request production access in the SES console under “Account dashboard.” AWS typically approves within 24 hours if you provide a reasonable use case. You’ll need to specify your sending volume, your bounce and complaint handling process, and the type of email you’re sending.


Problem 2: DNS records aren’t set up correctly

SES requires several DNS records for authenticated sending. Missing or misconfigured records cause silent delivery failures or emails landing in spam.

DKIM (DomainKeys Identified Mail): SES generates three CNAME records you add to your DNS. These cryptographically sign your emails so receiving servers can verify they came from you. If these aren’t in place, you’re sending unsigned email — many providers treat this as suspicious.

In the SES console, go to “Verified identities,” click your domain, and check the DKIM status. If it shows “Verification pending” or “Failed,” your CNAME records aren’t resolving correctly.

SPF (Sender Policy Framework): Authorizes SES servers to send email on behalf of your domain. For SES, you typically add a TXT record like:

v=spf1 include:amazonses.com ~all

If you’re already using SPF for other sending (Google Workspace, Mailchimp), you need to combine them into a single SPF record — one TXT record at your root domain, not multiple. Multiple SPF records cause failures.

DMARC (Domain-based Message Authentication, Reporting and Conformance): Tells receiving servers what to do when SPF and DKIM checks fail. Even a permissive DMARC policy (p=none) improves deliverability and enables reporting:

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

Mail From domain: SES uses email.amazonses.com as the default bounce-handling domain. For better deliverability, configure a custom MAIL FROM subdomain (mail.yourdomain.com) and add the required MX and SPF records for that subdomain. This aligns your From domain and bounce domain, which some spam filters check.


Problem 3: Suppression list silently blocking sends

SES maintains a suppression list at the account level. Any email address that has hard-bounced or marked your email as spam gets added automatically, and future sends to that address are suppressed — no bounce, no error, just silence.

This trips up teams during development and testing. If you tested with an invalid address, it gets suppressed. If a customer’s email server was temporarily down and you got a hard bounce, they’re now suppressed permanently until you remove them.

Check your suppression list: In the SES console, go to “Suppression list.” You can search for specific addresses and remove them if they were added in error.

For production: Build suppression list management into your application. SES can publish bounce and complaint events to SNS → SQS, which your application can subscribe to and process. Remove hard bounces from your sending list immediately. Handle complaints (spam reports) by unsubscribing the user permanently.


Problem 4: Your bounce or complaint rate is too high

SES enforces sending limits based on your bounce and complaint rates:

  • Bounce rate above 5%: SES places your account under review and may pause sending
  • Bounce rate above 10%: SES pauses your account
  • Complaint rate above 0.1%: Review; above 0.5%: pause

These thresholds are strict and enforced automatically. A bad email list — addresses that haven’t been cleaned, purchased lists, or lists with lots of typos — will get your SES account paused quickly.

Prevention:

  • Use double opt-in for marketing email. Confirmed subscribers complain less.
  • Clean your list before large sends. Services like NeverBounce or ZeroBounce can validate addresses before you send to them.
  • Honor unsubscribes immediately.
  • Don’t send to lists you’ve bought or haven’t contacted in years.

Monitor: Enable CloudWatch metrics for Bounce, Complaint, and Reject rates. Set alarms before you hit the thresholds so you can investigate rather than react.


Problem 5: You’re sending from the wrong region

SES is regional — you send email from the region where your identity is configured. If your application is deployed in us-east-1 but you configured your SES identity in us-west-2, the API call succeeds but the email is rejected because the sending identity doesn’t exist in the region you called.

Check that your SES client SDK is initialized for the same region where your domains and identities are verified. Verify this explicitly in your application configuration — it’s easy to inherit a default region that doesn’t match.


Problem 6: Raw message header issues

If you’re sending raw email (constructing the MIME message yourself rather than using the SendEmail API), formatting errors can cause silent failures:

  • The From address must exactly match a verified identity
  • Line endings must be \r\n (CRLF), not \n (LF)
  • Headers must not contain illegal characters
  • Attachments must be properly encoded (base64 for binary)

For most use cases, the structured SendEmail API or a library that wraps it is more reliable than constructing raw MIME messages.


Problem 7: IP warming for high-volume sending

If you’re sending large volumes from dedicated IPs (available in SES as “dedicated IP pools”), inbox providers need to see a ramp-up of sending volume to build reputation on those IPs.

Jumping straight to sending 100,000 emails/day from a new IP looks like spam to Gmail and Outlook. The standard warm-up schedule: start with a few thousand per day, double every few days, monitor bounce and complaint rates throughout.

For dedicated IPs, SES has an automatic warm-up feature that manages this. For most teams sending under a few million emails per month, shared IP pools are fine and avoid the warm-up complexity.


Diagnosis checklist

When email isn’t delivering from SES:

  1. Check account status: Is the account in sandbox mode? Any active pauses or limits in the Account dashboard?
  2. Verify sending identity: Is the domain or email address verified in the correct region?
  3. Check DNS records: DKIM CNAME records showing “Verified”? SPF record present? MAIL FROM configured?
  4. Check suppression list: Is the recipient address on the account-level suppression list?
  5. Check bounce/complaint rates: CloudWatch metrics for the last 24-48 hours
  6. Check SES sending statistics: In the console, the Sending Statistics page shows reject reasons

When to bring in help

SES configuration looks simple and fails in specific, non-obvious ways. If your email pipeline is business-critical — transactional notifications, password resets, order confirmations — a misconfiguration costs you more than the fix does.

I’ve configured SES for several client environments, including domain verification, DNS alignment, bounce/complaint handling pipelines, and CloudWatch monitoring. If your SES setup isn’t behaving, I can diagnose it and get it working.

Contact me or email nick@coldsmokeconsulting.com.


Nick Allevato is an AWS Certified Solutions Architect Professional with 20 years of infrastructure experience. He runs Cold Smoke Consulting, an independent AWS consulting practice.