← Back to Blog
How to build a suppression list for self-hosted email
2026-06-20

A suppression list is exactly what it sounds like — a list of addresses you've decided to never email again. Hard bounces, spam complaints, unsubscribes. Anyone who has told you, directly or through their mail server, that they don't want your messages.

If you're using a managed ESP, they handle this for you. But if you're running your own mail infrastructure — Postfix, Haraka, your own SMTP — then building and maintaining a suppression list is entirely your responsibility.


What goes on the list

Three categories of addresses should always be suppressed:

Hard bounces. Any address that returns a 5xx error goes on the list immediately, after the first occurrence. No exceptions.

Spam complaints. If you're signed up with feedback loops (and you should be), ISPs will send you a copy of every complaint from their users. Those addresses come off your list, period. Someone who marks your email as spam is not going to change their mind.

Unsubscribes. Anyone who has opted out needs to stay opted out. This is a legal requirement in most jurisdictions and just basic respect for your recipients.


How to structure it

Technically, a suppression list can be as simple as a text file with one address per line. For small volumes this is fine. As it grows you'll want it in a database so you can query it efficiently before each send.

The check at send time is simple: before you dispatch a message, look up the recipient address in your suppression list. If it's there, skip it. This lookup needs to be fast — if you're sending at any volume, a slow suppression check will become a bottleneck.


Domain-level suppression

Beyond individual addresses, it's worth maintaining a domain-level list. Some domains will never accept email from you — maybe they've blocked your IP, maybe the domain no longer exists. Suppressing the entire domain saves you from trying individual addresses one at a time.


Keeping it maintained

A suppression list only works if it's actually used. The most common failure mode is having a list that grows correctly but never gets checked — someone changes the sending infrastructure and forgets to hook up the suppression check, or a new list import doesn't get scrubbed against it before sending.

Build the check into your sending pipeline as a mandatory step, not an optional one. Every address goes through the suppression list, every time. No exceptions for "but this list is definitely clean" — that's how you end up emailing someone who unsubscribed six months ago.

Comments
Post Comment Below

All comments are moderated.

Replying to Cancel