# Suppressions and bounces

Sending again to an address that does not exist, or to someone who marked your mail as spam, hurts your sender reputation fast. Ha Tang keeps a **suppression list** per business and stops sending to those addresses automatically. This page explains what adds an address to the list, what happens when you send to it, and how to see and remove entries.

## What adds an address

| Reason | Dashboard label | Added when |
|---|---|---|
| `hard_bounce` | hard bounce | A message bounced permanently because the mailbox does not exist: the bounce has the `NoEmail` subtype or an SMTP status starting with `5.1.` (for example `550 5.1.1 User unknown`). |
| `complaint` | complaint | The recipient marked a message as spam in their mail client. |
| `unsubscribe` | unsubscribe | A contact unsubscribed from everything: on the preferences page, with one-click unsubscribe from a broadcast without a topic, through the API (`"unsubscribed": true`), with an automation's `update_contact` step, or from a CSV import. |
| `manual` | manual | Someone on your team added the address under **Suppressions**. |

The list belongs to your business and applies to every email you send: through the API, the SMTP relay, broadcasts and automations. Addresses are compared in lower case.

### Bounces that do not suppress

Not every bounce means the address is bad. These are recorded on the email but do **not** add the address to the list:

- **Temporary (soft) bounces**: a full mailbox, a server that is down, a message too large. They come back as `email.bounced` with `bounce.type` `Transient`.
- **Permanent rejections that are about the message, not the address**: content or policy blocks (`5.7.x`), for example. They come back with `bounce.type` `Permanent` and a subtype such as `Policy` or `ContentRejected`.

Watch these in your webhooks and metrics: a rise in policy rejections usually points to a content or reputation problem. See [Deliverability](https://hatang.dev/docs/guides/email/deliverability.md).

## What happens when you send to a suppressed address

Ha Tang still accepts the request, then skips that recipient:

- The recipient's state is `suppressed`, and nothing is sent to it.
- An `email.bounced` webhook fires for that recipient, with `bounce.subType` set to `Suppressed`:

```json
{
  "type": "email.bounced",
  "data": {
    "email_id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10",
    "to": ["old-address@example.net"],
    "subject": "Your invoice",
    "bounce": { "type": "Permanent", "subType": "Suppressed", "message": "Recipient old-address@example.net is on the suppression list (hard_bounce)" }
  }
}
```

- When every recipient of the email is suppressed, the email's status is `bounced` right away.
- The email still counts toward your daily quota.
- In [metrics](https://hatang.dev/docs/guides/email/metrics-and-logs.md), these recipients count under `suppressed`, and their `email.bounced` events also count under `bounced`. Clean your lists so they do not inflate your bounce rate.

Recipients skipped because of a `topic_id` they left are reported the same way (the reason is `topic_opt_out`), but they are not added to the suppression list.

> **Note: Unsubscribes block transactional mail too**
>
> An `unsubscribe` entry blocks every email to that address, including receipts and password resets sent through `POST /emails`. If someone only wants fewer marketing emails, let them leave a [topic](https://hatang.dev/docs/guides/email/audiences.md) instead of unsubscribing from everything.

## See the list

Open **Email → Audiences → Suppressions**. The list shows each address, the reason, a note (for a hard bounce, the bounce message from the receiving server) and when it was added.

There is no API for the suppression list. To keep your own records in sync, listen to these webhooks:

| Webhook | Use it to |
|---|---|
| `email.bounced` | Mark the address as invalid when `bounce.type` is `Permanent` and the subtype is `NoEmail`. |
| `email.complained` | Stop all marketing to that person. |
| `contact.updated` | Notice when `unsubscribed` changes. |

## Add or remove an address

On the **Suppressions** tab, type an address and click **Add** to block it by hand (reason `manual`). Click **Remove** next to an address to delete its entry; you need the permission to manage email.

Remove an entry only when you are sure:

- **Hard bounce**: the address has been fixed or the mailbox now exists, for example after the customer corrected a typo in their account.
- **Complaint**: the person asked to get your email again. Sending to people who complained is the fastest way to get your domain blocked.
- **Unsubscribe**: resubscribe the contact instead, so the contact record and the list stay consistent. Click **Resubscribe** on the contact, or send `PATCH /contacts/{id or email}` with `{ "unsubscribed": false }`; that removes the `unsubscribe` entry for you. Removing only the list entry lets transactional email through again, but the contact still does not receive broadcasts while it is marked unsubscribed.

## Next steps

- [Deliverability](https://hatang.dev/docs/guides/email/deliverability.md)
- [Contacts, segments and topics](https://hatang.dev/docs/guides/email/audiences.md)
- [Metrics and logs](https://hatang.dev/docs/guides/email/metrics-and-logs.md)

Source: https://hatang.dev/docs/guides/email/suppressions-and-bounces
