Skip to content
MiniMailer
Docs
Toggle sidebar
Quick links
Documentation
Knowledge Base
API Reference
Changelog
No results found

Bounces and complaints

When delivery goes wrong, the failure has a category, and the category decides what happens next. MiniMailer converts these signals into a per-domain suppression list automatically, because the worst thing you can do to your sender reputation is keep mailing an address that already told you no.

The categories

  • Hard bounce — permanent failure: the address doesn't exist, the domain has no mail server. The address will not start working next week; retrying reads as negligence to mailbox providers.
  • Soft bounce — temporary failure: full mailbox, greylisting, a transient server problem. Retried within the delivery window; repeated soft bounces on the same address eventually indicate a dead mailbox.
  • Complaint — the recipient marked your message as spam. Their mailbox provider reports it back, and the only correct response is to never mail them again. Complaint rate is the single most damaging reputation signal there is.
  • Unsubscribe — the recipient opted out, via the one-click unsubscribe header (RFC 8058, which MiniMailer sets up for you) or your own flow. Honoured immediately.

Each failure fires its webhook (email.bounced, email.complained, email.unsubscribed) as it happens, with the details in the payload.

How suppression works

A suppression is scoped to the (domain, recipient) pair and records why it exists and what it blocks — its scope:

Reason Created by Scope Removable?
hard_bounce A permanent delivery failure all — every send No — permanent
complaint A spam complaint all — every send No — permanent
unsubscribe An opt-out marketing — campaigns Yes
soft_bounce Repeated temporary failures all — every send Yes (may also expire on its own)
manual You, via API or dashboard all — every send Yes
list_import A suppression list you imported all — every send Yes

Every campaign send is checked against the whole list before delivery; transactional sends are blocked only by all-scope entries. The distinction is deliberate: an unsubscribe is an opt-out from your marketing — the recipient still gets transactional mail like receipts and password resets — while a bounce or complaint is a statement about the mailbox itself and stops everything. If an unsubscribed address later hard-bounces or complains, its entry is escalated to a permanent all-sends block. A suppressed recipient is rejected with a 422 at the API instead of being sent; this check is not optional — it is the guardrail that keeps one bad list from burning the domain.

Working with the list

  • GET /suppressions — browse and filter your suppression list (suppressions:read).
  • DELETE /suppressions/{suppression} — remove a suppression (suppressions:write). Removing hard_bounce and complaint suppressions is refused with a 422: a dead address stays dead, and re-mailing a complainer is how spam folders are earned. If a recipient genuinely wants back in after complaining, they can re-engage through your own opt-in flow.
  • Adding an address manually (manual) is the right way to honour an opt-out that arrived outside MiniMailer — a support email, a legal request.

AI agents get the same controls through the MCP tools check-suppression-tool and remove-suppression-tool, with the same permanence rules enforced.

Practical guidance

  • Watch the rates, not just the events. A handful of hard bounces is normal; a bounce rate above a few percent means the list itself is the problem.
  • Import your existing suppressions when migrating from another provider — carrying over your opt-outs is both a legal obligation and cheap reputation insurance.
  • Don't fight permanence. The two permanent reasons exist because remailing those addresses has no upside: one can't receive, the other doesn't want to hear from you — and both cost reputation to retry.