Suppressions
Automatic protection for your sender reputation.
The suppression list protects your sender reputation — and your SES account — by making sure you never repeatedly mail an address that hard-bounced or marked you as spam.
How addresses get suppressed
- Hard bounce — the receiving server permanently rejected the address.
- Complaint — the recipient marked a message as spam.
- Unsubscribe — the recipient opted out of all marketing email, through
the one-click header or the hosted preference page. Besides flagging the
contact, the opt-out is retained here so it survives deleting and
re-importing the contact; only an explicit
PATCH /contacts/{id}withunsubscribed: falseclears it. Unlike the other origins it covers marketing mail only (see below). - Manual — you added the address, in the dashboard or via the API.
Bounces and complaints arrive as SES events and suppress the address automatically. Suppressions are per team.
What suppression does
- Transactional sends (
POST /emailsand the SMTP relay, without atopic_id): recipients suppressed for a bounce, a complaint or a manual entry are stripped fromto/cc/bcc. If everytorecipient is suppressed, the send is rejected with422 all_recipients_suppressed(messageAll recipients are suppressed). An unsubscribe entry does not apply here: someone who opted out of marketing still receives password resets, receipts and other account mail — the same meaning Resend givesunsubscribed("unsubscribed from all Broadcasts"). - Topic sends (
POST /emailswith atopic_id) and broadcasts: every entry applies, unsubscribes included, plus the recipient's opt-out of that topic; broadcasts skip such contacts during fan-out.
A list imported with origin: "unsubscribe" therefore blocks topic sends and
broadcasts only. Import with manual to block every send.
Every change to the list publishes a suppression.added or
suppression.removed webhook event.
Reviewing and removing
The dashboard lists every suppressed address with the reason and date. You can remove an address to allow sending again — do this only when you know the cause is fixed (e.g. a mailbox that existed all along but was rejected by a misconfigured server). Re-suppression is automatic on the next bounce or complaint.
SES's own suppression list
Besides this per-team list, Amazon SES keeps an account-level suppression
list per region, shared by every team on the instance. The setup wizard sets
it to bounces only: a hard-bounced mailbox is dead for everyone, so SES may
refuse it account-wide, but a spam report is about one sender's mail and
stays on that team's list here. A send SES refuses because of its own list
shows as a permanent bounce with the subtype OnAccountSuppressionList, and
only the SES console can remove such an entry.
API
The /suppressions endpoints mirror Resend's suppressions surface, so the
Resend SDK's suppressions.* methods work as-is. Each entry reads as
{ id, email, origin, source_id, created_at }, where origin is bounce,
complaint, manual or unsubscribe and source_id is the email whose
bounce or complaint created it.
GET /suppressions?origin=bounce— keyset-paginated list, optionally filtered by origin.GET /suppressions/{id}andDELETE /suppressions/{id}— the path segment is the suppression id or the email address.POST /suppressionswith{ "email": "...", "origin": "manual" }— blocks the address.originis optional (bounce,complaint,manualorunsubscribe, defaultmanual) and lets an import from another provider keep its bounce and complaint history, or a migrated opt-out list keep its reason. Idempotent: an address already suppressed for any reason keeps its entry and origin, and its existing id is returned.POST /suppressions/batch/addwith{ "emails": [...], "origin": "bounce" }andPOST /suppressions/batch/removewith{ "emails": [...] }or{ "ids": [...] }— up to 1000 entries per call (Resend caps at 100). Add applies the one optionaloriginto every row it creates and returns one id per distinct address in input order; remove lists only the rows actually removed.
Three MepMail specifics: origin on add is accepted (Resend's SDK type
has no such field, so pass it through a raw request), origin: "unsubscribe"
is a superset value Resend does not have (its SDK's type union lacks it) and
behaves like a one-click opt-out — only an explicit re-subscribe of the
contact clears it — and an address whose personal
data was erased (GDPR/LGPD) keeps blocking sends but is hidden from the list
and from lookups by email — it is reachable by id only, reading
"[erased]" as its email, and re-suppressing the address returns that id
without restoring it.
Why this matters
SES tracks bounce and complaint rates and pauses senders that cross its thresholds. MepMail's metrics page tracks your rates against those thresholds, and broadcast sending is blocked automatically when a rate crosses the pause line.
On Cloud, sending volume is governed by your plan's limits. Self-hosted, the limits are your own AWS SES account's quotas and reputation — crossing SES's thresholds can pause the whole account, which is exactly what suppression protects you from.