Guide
How to send bulk email with Amazon SES
Amazon SES will happily send your newsletter, product announcement, or marketing campaign at $0.10 per 1,000 emails — but it hands you an API, not a campaign tool. This guide covers the full picture: the two send paths, templates, compliance for bulk senders, throughput engineering, and how to actually measure what happened.
Can SES Do Bulk?
Yes — SES is built for volume. The catch is everything around it.
The direct answer: Amazon SES can absolutely send bulk and marketing email. There's no rule against newsletters or promotions — SES powers some of the highest-volume senders on the internet, and AWS explicitly supports marketing mail as long as recipients opted in. It even has a dedicated bulk API, SendBulkEmail, that takes a template and up to 50 recipients per call.
The reason people ask is that SES looks nothing like Mailchimp. It's a sending API: no campaign editor, no audience dashboard, no unsubscribe page, no open-rate chart. Those are all things you build on top — this guide covers each one. What you get in exchange is the price:
| Monthly volume | Amazon SES | Typical marketing platform |
|---|---|---|
| 50,000 emails | ~$5 | $100–400 |
| 500,000 emails | ~$50 | $500–2,000+ |
SES pricing as of July 2026: $0.10 per 1,000 emails sent, plus data charges for attachments. Platform prices vary by list size and features — see our full SES pricing breakdown for the detailed comparison.
Prerequisites
Before your first bulk send
Three things have to be true before a bulk campaign leaves your account. Skip any of them and the send either fails outright or lands in spam.
- Production access. New SES accounts start in the sandbox — 200 messages per day, verified recipients only. Useless for bulk. Our SES setup guide covers the production-access request, including what to write about your list and opt-in practices so it's approved first pass.
- A verified domain with DKIM, SPF, and DMARC. Gmail and Yahoo require all three for bulk senders — mail without them is rejected or junked at volume. Send from a domain identity, never a bare email address. The SES deliverability guide walks through each DNS record.
- Enough quota — on both axes. Your 24-hour sending quota must cover the campaign size, and your per-second rate determines how long the send takes. A 100,000-recipient campaign at 14 messages per second runs for two hours. Check your numbers against the SES sending limits guide before you commit to a send date.
One more, if your account is new to volume: warm up before the big send. An account that has never delivered 50,000 messages and suddenly does looks compromised to every mailbox provider. Ramp daily volume gradually over one to two weeks, starting with your most engaged recipients — their opens and low complaint rates build the reputation that carries the rest of the list.
The Two Send Paths
SendBulkEmail vs. looping SendEmail
SES gives you two ways to send the same campaign, and the right choice depends mostly on volume.
Loop over SendEmail
One API call per recipient, with the full message body in each call. Simplest to build — no templates to manage, personalization is just string interpolation in your code. The cost is API round-trips: every recipient is a separate HTTPS request, which gets slow and failure-prone at tens of thousands of recipients. Fine for lists in the hundreds or low thousands.
SendBulkEmail
Up to 50 destinations per call, each with its own per-recipient data. Requires a stored template — you can't pass raw content. Each destination still counts as one message against your rate and quota, so batching cuts round-trips 50x without buying capacity. The response returns a per-destination status, so partial failures are visible per recipient. The right path for real campaigns.
Templates. SES templates are stored server-side (via CreateEmailTemplate) and use Handlebars-style variables — {{first_name}}, {{#if plan}}…{{/if}} — in the subject and both HTML and text bodies. At send time you supply template data as a JSON string: a default set for the whole call, plus per-recipient replacement data that overrides it. That's the entire personalization model.
A SendBulkEmail call (SES v2 API) looks like this, as of July 2026:
{
"FromEmailAddress": "news@mail.example.com",
"DefaultContent": {
"Template": {
"TemplateName": "july-newsletter",
"TemplateData": "{\"first_name\":\"there\"}"
}
},
"BulkEmailEntries": [
{
"Destination": { "ToAddresses": ["ada@example.com"] },
"ReplacementEmailContent": {
"ReplacementTemplate": {
"ReplacementTemplateData": "{\"first_name\":\"Ada\"}"
}
}
}
// ...up to 50 entries per call
],
"ConfigurationSetName": "campaign-events"
} Note the ConfigurationSetName — it's optional, but without it you get no per-campaign event data. More on that in Measuring Results.
Compliance
Unsubscribe, consent, and the Gmail/Yahoo rules
Bulk senders face requirements that transactional senders don't, and since 2024 Gmail and Yahoo enforce them technically — not just in policy documents. As of July 2026, senders above roughly 5,000 messages per day to those providers must meet all of the following, and SES does none of it for you on ordinary API sends.
One-click unsubscribe headers
Every marketing message needs List-Unsubscribe and List-Unsubscribe-Post: List-Unsubscribe=One-Click headers per RFC 8058 — an HTTPS endpoint the mailbox provider can POST to, unsubscribing the recipient without any confirmation page. Your sending code adds these headers and your app hosts the endpoint.
A visible unsubscribe link
The headers don't replace the classic footer link — you need both. The link must work, and opt-outs must be honored within two days under the Gmail/Yahoo rules (CAN-SPAM allows ten business days; meet the stricter one).
Consent
Send marketing mail only to people who opted in. Under GDPR that consent must be explicit and provable; purchased and scraped lists are illegal there and reputational suicide everywhere. High complaint rates from non-consenting recipients will also put your SES account under review — AWS enforces this independently of the law.
CAN-SPAM basics
A valid physical mailing address in every marketing message, no deceptive subject lines or headers, and a clear identification of the message as an ad where applicable. Cheap to comply with, expensive to ignore — penalties run per email.
The SES suppression list. SES maintains an account-level suppression list that automatically catches hard bounces and complaints — addresses on it are dropped before sending, protecting your reputation. But it is not an unsubscribe system: someone who clicks unsubscribe never appears on it. You need your own suppression store for opt-outs, checked on every send, on top of what SES suppresses for you.
List Management
What SES gives you for lists: almost nothing
SES does have a built-in contact-list feature, and it's worth knowing exactly how minimal it is. As of July 2026 you get one contact list per account, with contacts organized into basic topics (think: "newsletter", "product updates") that recipients can opt in and out of. It can store contacts and their topic preferences. That's the feature.
What it doesn't have is everything a marketing tool means by list management: no segmentation engine (no "customers on the Pro plan who signed up this quarter"), no engagement filtering (no "exclude anyone who hasn't opened in 90 days" — SES doesn't even aggregate opens per contact), no custom fields beyond what you serialize yourself, no import/export tooling, no preference center UI. Sending to a segment means your application queries its own database for the audience, applies its own suppression and engagement rules, and hands SES the final address list.
In practice, teams doing bulk on SES keep the audience in their own database or bring a tool that manages it for them. The contact list is fine as a bare opt-in/opt-out store; it is not a CRM and doesn't try to be.
Throughput
Pushing a big campaign through a rate limit
Your sending rate — commonly around 14 messages per second for newer production accounts — is the bottleneck for any large campaign, and SES enforces it hard: exceed it and calls fail with a Throttling error. SES doesn't queue anything for you, so the campaign pipeline is yours to engineer.
The standard architecture
- Enqueue, don't send inline. When a campaign launches, resolve the audience and push every recipient (or batch of 50) onto a queue — SQS is the usual choice on AWS. The campaign is now durable: a crash mid-send loses nothing.
- Drain below your rate. A worker consumes the queue and calls SES at a pace safely under your per-second limit — remembering that one SendBulkEmail call with 50 destinations consumes 50 messages of rate, not 1. Leave headroom for the transactional mail your app sends at the same time.
- Back off on throttling. When a Throttling error comes back anyway, retry with exponential backoff and jitter. With SQS this is nearly free — leave the message on the queue and let visibility timeout redeliver it.
- Watch the daily quota. The 24-hour quota is a separate ceiling. If a campaign plus your transactional volume would cross it, pause the drain rather than burning sends into failures — see the sending limits guide for how the rolling window behaves.
Measuring Results
Knowing what actually happened to the send
A successful API call means SES accepted the message — nothing more. Deliveries, bounces, complaints, opens, and clicks arrive later as events, and you only get them if you set up a configuration set with an event destination (SNS, Kinesis Firehose, EventBridge, or CloudWatch) and attach it to the send.
Even then, what you receive is a stream of individual events, not a campaign report. To answer "how did Tuesday's newsletter do?" you need to tag each send with a campaign identifier (message tags on the configuration set, or the config set name itself), consume the event stream, and aggregate per campaign yourself — deliveries over sends, bounce rate, complaint rate, opens and clicks if you enabled tracking. There is no SES dashboard that shows results per campaign.
Two numbers matter beyond curiosity: bounce rate and complaint rate feed your SES account reputation, and a single bulk send to a stale list can push you over the review thresholds. Wire the event stream into your suppression store — hard bounces and complaints from this campaign must be excluded from the next one automatically.
SendOps
The honest math — and the shortcut
SES can absolutely do bulk email at $0.10 per 1,000. But tally what this guide just described: audience storage and segmentation, consent and suppression tracking, RFC 8058 headers and an unsubscribe endpoint, a template system, a queue with pacing and backoff, an event pipeline, and per-campaign aggregation. Everything around the send is yours to build. That's a reasonable project for a team that wants to own it — and a lot of undifferentiated plumbing for everyone else.
SendOps is that layer, running through your own SES account — your quota, your reputation, SES's pricing:
Broadcasts
Pick a list or segment, write the email, send — paced within your SES rate automatically, with test sends to yourself before the real thing.
Consent, auto-applied
Unsubscribes, one-click headers, and suppression are applied to every broadcast automatically — opted-out and bounced addresses never make it into a send.
Per-campaign results
Deliveries, bounces, complaints, opens, and clicks aggregated per broadcast — the report SES doesn't give you, without building the event pipeline.
Free to start
There's a free plan — connect your SES account and send your first broadcast in minutes.
FAQ
Frequently asked questions
Can I send bulk email with Amazon SES?
Yes. Amazon SES is built for volume — bulk, marketing, and transactional mail alike. You need production access (out of the sandbox), a verified domain with DKIM, SPF, and DMARC, and enough sending quota for your list size. SES gives you the raw sending API at $0.10 per 1,000 emails as of July 2026; the campaign layer — audience, templates, unsubscribes, results — is yours to build or bring.
How many emails can I send at once with SES?
The SendBulkEmail API accepts up to 50 destinations per call, and each destination counts as one message against your per-second sending rate and 24-hour quota. So a single call doesn't buy extra capacity — it just reduces API round-trips. Total campaign size is bounded by your account's sending quota, commonly around 50,000 messages per day for new production accounts as of July 2026.
Does Amazon SES allow marketing emails?
Yes — newsletters, promotions, and announcements are all allowed, provided recipients opted in and you meet bulk-sender compliance: a working unsubscribe (including RFC 8058 one-click List-Unsubscribe headers for Gmail and Yahoo), a physical mailing address under CAN-SPAM, and prompt honoring of opt-outs. What SES does not tolerate is purchased or scraped lists — high bounce and complaint rates will put your account under review regardless of email type.
How much does bulk email cost on SES?
As of July 2026, SES costs $0.10 per 1,000 emails sent, plus a small data charge for attachments. A 50,000-recipient newsletter costs about $5. That's one to two orders of magnitude cheaper than typical marketing platforms at the same volume — but the price covers sending only, not list management, templates, or analytics.
Do I need unsubscribe links on SES?
Yes, on two levels. Legally, CAN-SPAM and GDPR require a working opt-out that you honor promptly. Practically, Gmail and Yahoo require bulk senders to include one-click List-Unsubscribe and List-Unsubscribe-Post headers (RFC 8058) plus a visible unsubscribe link in the body, and to process unsubscribes within two days. SES does not add these headers for you on ordinary API sends — your sending code has to include them.
Get Started
Bulk email on SES, without building the machine
Connect your SES account and get broadcasts, segments, compliance, and per-campaign results — at SES prices, free to start.