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.bouncedwithbounce.typeTransient. - Permanent rejections that are about the message, not the address: content or policy blocks (
5.7.x), for example. They come back withbounce.typePermanentand a subtype such asPolicyorContentRejected.
Watch these in your webhooks and metrics: a rise in policy rejections usually points to a content or reputation problem. See Deliverability.
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.bouncedwebhook fires for that recipient, withbounce.subTypeset toSuppressed:
{
"type": "email.bounced",
"data": {
"email_id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10",
"subject": "Your invoice",
"bounce": { "type": "Permanent", "subType": "Suppressed", "message": "Recipient [email protected] is on the suppression list (hard_bounce)" }
}
}
- When every recipient of the email is suppressed, the email's status is
bouncedright away. - The email still counts toward your daily quota.
- In metrics, these recipients count under
suppressed, and theiremail.bouncedevents also count underbounced. 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.
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 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 theunsubscribeentry 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.