Amazon SES
AWS SES returned a Message ID but email never arrived. Diagnose template errors, sandbox limits, suppression-list, and bounces with SES event publishing.
Updated Jul 1, 2026
The short answer
"AWS SES email not received" means SES accepted your SendEmail/SendTemplatedEmail call and returned a Message ID, but the message never reached the inbox. The usual causes are a template RenderingFailure (missing template variable), the sandbox requiring verified recipients, the recipient being on a suppression list, a hard bounce, or ISP spam filtering. Enable SES event publishing to see exactly where it dropped.
A successful Amazon SES API call is not a guarantee of delivery. SendEmail and SendTemplatedEmail return a MessageId as soon as SES accepts the request for processing — what happens afterward (rendering, suppression checks, the SMTP handoff to the recipient's mail server, and the receiving ISP's own filtering) can still silently drop the message. That is why an email can show as "sent" in your logs yet never appear in the recipient's inbox.
There is no single cause — it's a symptom. The common, AWS-documented reasons, roughly in the order worth checking:
SendTemplatedEmail and the TemplateData you pass is missing a variable the template references, SES accepts the call and returns a Message ID but then fails to render and never sends the email, with no error in the API response. SES emits a RenderingFailure event with a message like Attribute 'firstName' is not present in the rendering data. This is the cause the original version of this page described — it is real, but it is only one of several. (AWS re:Post)bounceType: Permanent. The exact bounceSubType tells you which list: OnAccountSuppressionList for your account-level suppression list (and OnTenantSuppressionList for a tenant-level list), or Suppressed for the global SES suppression list (an address with a recent history of producing hard bounces). Bounces suppressed via your account-level or tenant-level list (bounceSubType OnAccountSuppressionList / OnTenantSuppressionList) do not count toward your bounce-rate metric. Bounces suppressed via the global SES list (bounceSubType Suppressed) do count toward your account's bounce rate — so a chronically hard-bouncing address should still be removed from your mailing list even though SES "accepted" the send. (AWS docs)Permanent, not retried); a full mailbox or temporary server issue produces a soft bounce (Transient, retried for a period before SES gives up). The address shows as accepted but is rejected at the recipient's server.Delivery event with a 250 SMTP response) but routed it to spam/junk — often due to missing SPF/DKIM/DMARC alignment or poor sender reputation.The fix depends on the cause, so diagnose first by turning on SES event tracking, then act:
Send, RenderingFailure, Reject, Bounce, Complaint, and Delivery. The first event missing from a given Message ID tells you where it stopped.RenderingFailure: read the SNS notification — it names the missing variable (Attribute 'x' is not present in the rendering data). Add that key to your TemplateData, or make the template tolerant of missing values. Verify the JSON keys match the template variable names exactly (case-sensitive).GetSuppressedDestination, and if it's a known-good address, remove it from your account-level list with DeleteSuppressedDestination after confirming the original bounce was transient. You can't interact with the global list directly — you override it by adding the address to (or keeping it off of) your account-level list.Delivery event but the user still can't find it: it reached the ISP — have the recipient check spam/junk, and confirm SPF, DKIM (via SES Easy DKIM), and a DMARC record are all aligned for your sending domain.Note that identity verification status is per-AWS-Region — an identity verified in us-east-1 is not verified in eu-west-1. Sending from a region where the From/Source/Return-Path identity isn't verified is rejected.
If you send through Courier with SES as the provider, surface these same SES events in your provider configuration and check the message logs for the underlying SES Message ID, Bounce, and RenderingFailure details.
References
FAQ
A returned Message ID only means SES accepted the request, not that it sent the mail. If the template references a variable that's missing from your TemplateData, SES fails rendering and silently drops the email, emitting a RenderingFailure event like "Attribute 'x' is not present in the rendering data." Enable event publishing to SNS to see the exact missing variable, then add it to TemplateData.
One API, every provider
Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.
Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.
© 2026 Courier. All rights reserved.