---
title: Bounces, complaints, and the suppression list your agent cannot argue with
metaTitle: Handling email bounces and suppression for AI agents
description: Hard bounces, soft bounces, complaints, and unsubscribes each need a different response. What the platform enforces, what your agent must do with the rest, and why suppression belongs below the model.
date: 2026-07-29
author: MCPmailer
tags: Deliverability
---

Every sending domain that gets into trouble got there the same way: it kept sending to addresses that had already said no, in one of the four ways an address can say no. Handling those four correctly is most of what separates a domain that stays deliverable from one that quietly stops working.

![Four rejection signals arriving back from a send](/blog/bounces-suppression-agent-email/hero.webp "Four ways a send comes back, and four different correct responses.")

## The four signals, and what each one means

| Signal | What happened | Correct response |
| --- | --- | --- |
| Hard bounce | The address does not exist | Never send there again |
| Soft bounce | Temporary: mailbox full, server busy, greylisting | Retry later, a few times, then stop |
| Complaint | The recipient marked it as spam | Stop permanently, and look at why |
| Unsubscribe | The recipient used the opt-out | Stop permanently, immediately |

Confusing the first two is the most common technical mistake. Treating a soft bounce as permanent loses you real recipients whose mailbox was briefly full. Treating a hard bounce as temporary is worse: repeated sends to addresses that do not exist are one of the clearest signals a mailbox provider has that a sender is not paying attention.

Complaints are in a different category again, because they are a judgement rather than a delivery fact. One is noise. A rate is a verdict, and the fix is never "send more carefully to that person", it is to look at what the agent has been sending to everyone.

## What the platform enforces, so your agent cannot get it wrong

Suppression is not advice, it is a refusal. An address that previously bounced or complained produces `recipient_suppressed` on any further attempt, listing the addresses in question, and the send does not happen. Cold sends carry a signed one-click `List-Unsubscribe` link, and using it suppresses that address for your workspace immediately, with later sends rejected before they ever reach the sending infrastructure.

That placement is the point. A model can be persuaded, distracted, or simply wrong; an enforced refusal cannot. It is the same principle as everything in [keeping an autonomous agent from becoming a spam problem](/blog/stopping-agent-email-spam): the rules whose violation is expensive belong under the tool.

> [!note]
> If your agent's plan for honouring unsubscribes is "remember not to email them", you do not have a plan. Suppression has to be a property of the system, not of the context window.

## What your agent still has to do

Enforcement stops the send. It does not stop the underlying problem, and three things remain yours.

**React to the events.** Register a webhook and handle `message.bounced` and `message.complained`: mark the contact, stop the workflow that was in progress, and tell whoever needs to know. A collections chase that keeps running against an address that hard bounced is a workflow that will never succeed, and nobody notices until someone asks why that invoice was never paid.

**Read a refusal properly.** `recipient_suppressed` means stop and escalate, not retry with a different subject line. The habit of treating refusal reasons as information is worth building into the prompt, per [the system prompt for an email agent](/blog/email-agent-system-prompt).

**Honour the informal no.** A reply saying "stop emailing me" or "remove me" counts legally and counts practically, and it does not go through the unsubscribe link. Detect the obvious phrasings, suppress, and escalate anything ambiguous to a person rather than guessing. The legal shape of this is in [the compliance floor](/blog/ai-email-compliance-gdpr-canspam).

```json
{
  "type": "message.bounced",
  "message_id": "msg_...",
  "to": "typo@custmoer.com",
  "reason": "mailbox_not_found",
  "permanent": true
}
```

![A bounce event stopping the workflow that was in progress](/blog/bounces-suppression-agent-email/events.webp "The suppression is automatic. Stopping the workflow behind it is yours.")

## Where bad addresses come from

Suppression is a cure. The prevention is caring where addresses came from, and agents make this easier than marketing tooling does, because an agent's recipients are usually people who wrote first.

The dangerous sources, in rough order: addresses guessed from a naming pattern, addresses scraped from a website, addresses inferred by a model from a company name, and lists imported from anywhere at all. Guessing `firstname.lastname@company.com` is a hard bounce generator and occasionally a spam trap, and a spam trap is close to unrecoverable because it is an address that exists specifically to catch senders who guess.

An agent that only ever writes to people who have written to it will effectively never see a hard bounce, which is the strongest argument there is for shipping an inbound use case first, as in [the warmup plan](/blog/email-warmup-plan-agents).

## Reading the numbers

Watch these weekly, per sending domain, not in aggregate across everything you send.

- **Hard bounce rate.** Should be near zero. Sustained above a fraction of a percent means your address sources are wrong, and no amount of careful sending fixes that.
- **Complaint rate.** Target zero. Anything you can see on a chart is already a problem.
- **Soft bounce pattern.** A cluster at one provider is a reputation signal, not a coincidence.
- **Suppression list growth.** Steady growth on an inbound agent means something upstream is sending where it should not.

If any of them move, stop expanding volume before you investigate, per [deliverability for agent senders](/blog/agent-email-deliverability).

## A short runbook

1. Register webhooks for `message.bounced` and `message.complained` on day one.
2. On a permanent bounce, mark the contact, stop the workflow, and let a human see the pattern.
3. On a complaint, stop that recipient permanently and review what the agent has been sending to everyone.
4. Detect "stop" in replies and suppress on it; escalate ambiguity.
5. Never retry a `recipient_suppressed` refusal.
6. Watch the four numbers weekly, per domain.
7. Fix the source of bad addresses rather than the symptom.

## Questions

### What is the difference between a hard and a soft bounce?

A hard bounce means the address does not exist and you must never send there again. A soft bounce is temporary, such as a full mailbox, and can be retried a few times before you give up.

### Does the platform enforce suppression, or does my agent?

The platform. An address that bounced or complained produces `recipient_suppressed` and the send does not happen, so enforcement does not depend on the agent remembering.

### What happens when someone clicks unsubscribe?

Cold sends carry a signed one-click `List-Unsubscribe` link, and using it suppresses that address for your workspace immediately. Later sends to it are rejected before reaching the sending infrastructure.

### Does a reply saying "stop" count as an unsubscribe?

Yes, legally and practically. Detect the obvious phrasings, suppress on them, and escalate anything ambiguous to a person instead of guessing.

### What bounce rate is acceptable?

Near zero for hard bounces. Anything sustained above a fraction of a percent means the addresses are not coming from real conversations, and that is a sourcing problem rather than a sending problem.

### What should my agent do when a send is refused as suppressed?

Stop and escalate. Not retry, not rephrase. The refusal is protecting the domain the agent depends on.

## Related

- [Deliverability for agent senders](/blog/agent-email-deliverability)
- [The compliance floor for email an AI agent sends](/blog/ai-email-compliance-gdpr-canspam)
- [Webhooks or polling for agent email](/blog/webhooks-vs-polling-agent-email)
- [A warmup plan for a new agent sending domain](/blog/email-warmup-plan-agents)
