bigonotes
CloudMessaging and Email

Email Delivery with Amazon SES

Send email with Amazon SES: bounces, complaints, suppression lists, verification, SPF, DKIM, DMARC, reputation and sending limits.

8 min readLast updated

Sending one email is easy. Getting thousands of emails into inboxes instead of spam folders is hard. Mailbox providers such as Gmail and Outlook judge every sender, and they block or junk senders that look like spammers. Amazon Simple Email Service (SES) is AWS's managed service for sending (and receiving) email at scale. This note covers how SES works and the deliverability rules that apply to any email you send.

What you send#

Deliverability rules depend on what kind of email you send, so start there. Application email falls into two broad groups with different rules and expectations.

Transactional Marketing (bulk)
Trigger A user action or system event A campaign you schedule
Examples Password reset, receipt, shipping update, alert Newsletter, promotion, product news
Recipient expects it? Yes, often waits for it Only if they opted in
Unsubscribe link Usually not needed Required by law in many countries

Many teams send the two from different subdomains or SES configuration sets. Then complaints about a newsletter don't hurt password-reset delivery.

Sending is the main job, but SES can also receive email for your domain. Receipt rules then store messages in S3, invoke Lambda or publish to SNS.

Getting started: verification and the sandbox#

Before SES sends anything, you have to prove who you are. It sends only from identities you have verified, which stops anyone from sending as your domain.

  • Email address identity: SES sends a link to the address, and you click it.
  • Domain identity: you add DNS records that prove you control the domain. Every address at that domain can then send. With Easy DKIM, these are CNAME records that also turn on DKIM signing. Older setups used a TXT record.

New accounts start in the sandbox. In the sandbox you can send only to verified addresses, with a low quota. To send to real customers, request production access and describe how you collect addresses and handle bounces and complaints.

Bounces#

Once you're sending to real people, some messages will fail. Those failures are the first signal providers use to judge you. A bounce means the email couldn't be delivered. The receiving mail server rejects it, and SES passes the result back to you.

Hard bounce Soft bounce
Meaning Permanent failure Temporary failure
Examples Address or domain doesn't exist; policy rejection Mailbox full, server busy, connection timeout
SMTP reply 5xx 4xx
SES action No retry; address goes on suppression lists Retries for a period, then gives up
Your action Remove the address from your list Watch it; remove if it keeps failing

Bounces also differ by when they happen:

  • A synchronous bounce happens during the SMTP conversation. The receiving server rejects the message before it accepts it.
  • An asynchronous bounce happens later. The server accepts the message, fails to deliver it, and sends a bounce message back.

SMTP reply codes#

The hard and soft split comes straight from the reply code the receiving server sends. SMTP replies start with a digit that tells you the class of result (RFC 5321). 4xx means "try again later". 5xx means "don't try again".

Code Class Typical meaning
421 Temporary Service not available, e.g. overloaded
450 Temporary Mailbox unavailable or busy
451 Temporary Local error on the receiving server
452 Temporary Insufficient storage on the server
550 Permanent Mailbox unavailable, e.g. no such user
554 Permanent Transaction failed, often a policy block

Replies often carry an enhanced status code too, such as 5.1.1 (bad destination mailbox). It gives a more specific reason.

Complaints and feedback loops#

Bounces are about addresses that don't work; the second signal is about people who don't want your email. A complaint happens when a recipient clicks "Report spam" or reports your email to their provider. A complaint tells the provider that the recipient didn't want your email. It hurts your reputation more than a bounce does.

Many large providers run feedback loops (FBLs). When a user reports a message, the provider sends a report back to the sender. SES receives these reports and forwards them to you.

To keep complaints low:

  1. Send only to people who opted in and expect your email.
  2. Put a clear unsubscribe link in marketing email, and honor it quickly.
  3. Stop emailing anyone who complains.
  4. Remove recipients who never open or click.

Handling notifications#

Bounces and complaints only help you if your app acts on them. Don't wait for a dashboard to show trouble. Have SES tell your app about every bounce and complaint, and update your mailing list automatically.

  • Send bounce, complaint and delivery notifications to an SNS topic, often fanned out to an SQS queue (see SNS and SQS).
  • Or use configuration sets with event destinations, which also report sends, opens and clicks.
  • A small worker reads each event and marks the address as invalid or unsubscribed in your database.

Suppression lists#

SES also acts on bounces and complaints itself, through suppression lists. A suppression list holds addresses that SES won't send to, and there are two levels.

Global suppression list Account-level suppression list
Owned by SES, shared across all customers Your account
Added when An address hard bounces for any SES customer An address bounces or complains for you
Can you view or edit it? ✗ ✓ add, remove, list
How long Up to 14 days; longer after each repeat bounce Until you remove it

Suppression doesn't make a bad list harmless. Some behavior to know:

  • If you send to a globally suppressed address, the API call succeeds, but SES doesn't deliver. You get a bounce with subtype Suppressed.
  • These suppressed sends still count toward your bounce rate and daily quota. Clean your list instead of relying on suppression.
  • You choose whether the account-level list adds addresses on bounces, complaints or both. Configuration sets can override it.

Email authentication: SPF, DKIM and DMARC#

Authentication shows providers that you are the one sending. Anyone can type any From address into an email. Authentication lets the receiving server check that a message comes from the domain it claims. All three methods publish records in DNS; see DNS for how TXT, CNAME and MX records work.

Method What it proves How
SPF The sending server may send for the envelope domain TXT record listing allowed senders
DKIM The message wasn't changed, and a domain signed it Signature header, checked against a public key in DNS
DMARC The visible From domain matches SPF or DKIM, and what to do if not TXT record at _dmarc.<domain>

SPF#

Sender Policy Framework checks the envelope sender (the MAIL FROM, or Return-Path) domain. The receiving server looks up that domain's SPF TXT record and checks that the sending IP is on the list.

By default, SES uses its own MAIL FROM domain, so SPF passes for an amazonses.com domain, not yours. To make SPF count for your domain, set up a custom MAIL FROM domain, such as bounce.example.com, with an MX record and an SPF record that includes SES.

bounce.example.com.  TXT  "v=spf1 include:amazonses.com ~all"

DKIM#

DomainKeys Identified Mail signs each message with a private key. The signature goes in a DKIM-Signature header. The receiving server fetches the public key from DNS and checks the signature. A valid signature proves that the signing domain sent the message and that the signed parts weren't changed in transit.

With Easy DKIM, SES creates the key pair, gives you CNAME records to publish, signs every message and rotates the keys.

DMARC#

DMARC (Domain-based Message Authentication, Reporting and Conformance) ties SPF and DKIM to the From address that users see. A message passes DMARC when SPF or DKIM passes and its domain aligns with the From domain.

The DMARC record also tells receivers what to do with failing mail, and where to send reports:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
Policy p= Receiver action on failure
none Deliver as normal; send reports only
quarantine Put it in spam
reject Refuse the message

Start with p=none and read the reports. Move to quarantine and then reject once every legitimate sender passes. Large mailbox providers now require SPF, DKIM and DMARC from bulk senders.

Reputation and sending limits#

Bounces, complaints and authentication all feed into one score. Reputation is how much mailbox providers trust that your IP addresses and domains don't send spam. With SES, two reputations matter:

  • Your reputation with mailbox providers. SES sends from shared IP pools by default, with a good reputation that all customers share. You can buy dedicated IPs if you send high, steady volume and want your own reputation.
  • Your reputation with SES. SES watches your bounce and complaint rates. If they climb too high, SES can put the account under review, pause sending, or lower your limits.

SES also caps how fast you can send, and those caps grow with your reputation. It enforces two sending limits:

  • Sending quota: the most emails you can send in a rolling 24-hour period.
  • Maximum send rate: the most emails per second.

SES raises the limits over time as you send good email. You can also request an increase. On a new dedicated IP, warm it up: start with low volume and raise it gradually, so providers learn to trust it.

Key takeaways#

  • Separate transactional and marketing email so one can't damage the other's reputation.
  • Hard bounces (5xx) are permanent: stop sending. Soft bounces (4xx) are temporary: SES retries.
  • Complaints hurt more than bounces. Send only to opted-in recipients and honor unsubscribes.
  • Process bounce and complaint events automatically, and keep your list clean.
  • Publish SPF, DKIM and DMARC records, with a custom MAIL FROM domain so SPF aligns.
  • Keep bounce and complaint rates low, or SES can pause your sending.
Revision notes · 2 min

Core idea#

Amazon SES sends email at scale. Deliverability depends on low bounces and complaints, plus SPF, DKIM and DMARC.

Key points#

  • Separate transactional and marketing email, for example by subdomain or configuration set.
  • SES sends only from verified email addresses or domains. Easy DKIM CNAME records verify a domain.
  • New accounts start in the sandbox: verified recipients only, low quota. Request production access.
  • Send bounce and complaint events to SNS or configuration set destinations. Update your list automatically.
  • Complaints come from "Report spam" and reach you through feedback loops. They hurt more than bounces.

Bounces#

Hard Soft
Meaning Permanent Temporary
SMTP reply 5xx 4xx
SES action No retry; suppress Retries for a period
Your action Remove the address Watch it
  • Synchronous bounce: rejected during the SMTP conversation.
  • Asynchronous bounce: accepted, then bounced later.

Suppression lists#

  • Global: SES-wide, after hard bounces for any customer, up to 14 days. You can't view or edit it.
  • Sends to a globally suppressed address succeed in the API, but bounce with subtype Suppressed. They count toward your bounce rate and quota.
  • Account-level: yours to add, remove and list. Choose bounces, complaints or both.

Authentication#

Method Proves
SPF The sending server may send for the envelope domain
DKIM A domain signed the message, and it wasn't changed
DMARC The From domain aligns with SPF or DKIM; sets the failure policy
  • Use a custom MAIL FROM domain so SPF aligns with your domain.
  • DMARC policies: none, quarantine, reject. Start with none and read the reports.

Reputation and limits#

  • SES watches bounce and complaint rates. High rates lead to review, a pause or lower limits.
  • Limits: sending quota per rolling 24 hours, and maximum send rate per second.
  • Warm up dedicated IPs gradually.

Pitfalls#

  • Relying on suppression instead of cleaning your list.
  • Sending to people who didn't opt in.
  • Jumping straight to p=reject before every sender passes.

Say it in an interview#

  • "Hard bounces are permanent 5xx failures; stop sending. Soft bounces are 4xx; SES retries."
  • "Publish SPF, DKIM and DMARC, and process bounce and complaint events automatically."

Found a mistake? Email ask@bigonotes.com

Further reading#