How to Read an Amazon SES Bounce Notification
When Amazon SES can’t deliver a message, it tells you with a notification: a small JSON document published to an Amazon SNS topic. The useful part is three fields, and they answer different questions. This post walks through what each one means and which bounces you need to act on.
The three fields that matter
Inside the bounce object, SES gives you a bounceType and a bounceSubType, both assigned by SES itself. Per recipient, in bouncedRecipients, you may also get the receiving server’s own words: an action, a status code and a diagnosticCode. Those last three come from a delivery status notification (DSN) when one is attached to the bounce, so they can be missing. AWS says explicitly that diagnosticCode may be absent.
That matters in practice. The type and subtype tell you what to do next. The diagnostic code, when present, tells you why, in the receiving server’s own language, for example a line like smtp; 550 user unknown.
Permanent, Transient and Undetermined
- Permanent (a hard bounce): sending to this address again is unlikely to work. AWS says to remove it from your list right away. Continuing to send to addresses that hard-bounce can hurt your sender reputation, and AWS notes it might pause your ability to send.
- Transient (a soft bounce): a temporary problem. SES retries delivery for a period of time, and you get a notification for a soft bounce only after SES has stopped trying. If you want one each time, enable event publishing and delivery delay events.
- Undetermined: the recipient’s provider bounced the message but didn’t say enough for SES to classify it. The bounce email sent to your Return-Path address may have more detail.
The subtypes, and what to do about each
For transient bounces, the subtype tells you whether anything you can change would help:
- MailboxFull: the recipient’s inbox is full. Nothing to fix on your side, and it may work later.
- MessageTooLarge: the message was too large. Reduce its size.
- ContentRejected: the provider didn’t allow something in the content. Change the content.
- AttachmentRejected: the provider objected to an attachment, such as its file type or size. Remove or change it.
- General: a generic bounce. This includes automatic responses such as out-of-office replies, which SES does not count toward your bounce rate.
For permanent bounces, the subtype also tells you whether SES even tried:
- General: the recipient’s provider sent a hard bounce. Remove the address.
- NoEmail: SES couldn’t retrieve the recipient address from the bounce message.
- Suppressed: the address is on the SES suppression list because of a recent history of hard bounces, so SES didn’t send.
- OnAccountSuppressionList and OnTenantSuppressionList: SES didn’t send because the address is on your account-level (or tenant-level) suppression list. These do not count toward your bounce rate metric.
- EmailValidationSuppressed: SES didn’t send because the address didn’t meet the threshold of your email validation settings. Also not counted in your bounce rate.
- UnsubscribedRecipient: the contact unsubscribed through SES list management, so SES didn’t attempt delivery and your reputation isn’t affected.
The practical reading order
- Check bounceType. Permanent means stop sending to that address. Transient means wait, or fix what the subtype points at.
- Check bounceSubType. If it is one of the suppression or validation subtypes, SES never attempted delivery. The right response is to correct your list or settings, not to investigate the recipient’s server.
- If the type is Permanent General or Undetermined, read diagnosticCode and status, when present, for the receiving server’s reason.
- Remember the batching rule: one notification can cover several recipients, and SES makes no ordering guarantees. Handle every entry in bouncedRecipients, and tolerate fields you don’t recognize, because AWS says it may add new ones.
What this doesn’t tell you
- The whole-account picture. One notification explains one bounce. Whether your bounce rate is rising, or one domain is causing most of them, takes aggregation across messages.
- The reason, every time. When the diagnostic code is absent you have a category and nothing more.
- Anything SES didn’t see fail. A message the recipient’s server accepted and then filed as spam won’t produce a bounce notification.
InsightForge turns delivery event data into one dashboard that runs inside your own Azure subscription. Today it supports Postmark, Azure Communication Services and SendGrid. It does not support Amazon SES yet. If you send through SES and would want that, tell us. Requests like that are how we decide what to build next.
Tell us what you send with