One-click unsubscribe moved from good practice to hard requirement when Google and Yahoo introduced their bulk sender rules. It is also one of the most commonly mis-implemented requirements, because a plausible-looking partial implementation produces no error — it simply fails to work.
The two headers
RFC 8058 requires both of these on every message:
List-Unsubscribe: <https://example.com/u/8f3a2b1c>, <mailto:[email protected]>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
List-Unsubscribe has existed for years and advertises where to send an opt-out. Many senders have this already.
List-Unsubscribe-Post is the newer one, and the one that is usually missing. It declares that the URL will accept an HTTP POST and complete the unsubscribe without any further interaction from the recipient.
Without the second header, mail clients will not render the native unsubscribe control, and you are not compliant regardless of how correct the first header looks.
What the endpoint has to do
When a recipient uses the control, their provider sends a POST to your URL with the body List-Unsubscribe=One-Click. Your endpoint must:
- Accept the POST — not require a GET, and not redirect.
- Identify the recipient from the opaque token in the URL.
- Suppress them immediately.
- Return a success status.
It must not require login, present a confirmation page, ask for a reason, or offer preference options before completing. Those flows are all acceptable for a body link; none of them are acceptable here.
Make the token opaque and unguessable
The identifier in the URL should be a random token mapped to the subscription server-side — not the email address, and not a sequential ID. Putting the address in the URL leaks it into logs and referrer headers; a sequential ID means anyone can unsubscribe anyone else by counting.
Why this helps you, not just the recipient
It is easy to read the requirement as an imposition. It is better understood as protection.
A recipient who wants to stop receiving your mail has two options: find the unsubscribe, or press "report spam". The first is invisible to mailbox providers. The second is a direct negative signal against your sending domain and counts toward the complaint rate that has a hard 0.3% threshold attached.
Every unsubscribe you make easy is a spam complaint you did not receive. Making opt-out frictionless is straightforwardly in your interest.
Honour it within two days
The bulk sender requirements specify two days — considerably tighter than the ten business days CAN-SPAM permits. Any process involving a manual export step will struggle to meet that reliably.
The workable implementation is automatic: the opt-out enters a suppression list on receipt, and every subsequent campaign is checked against that list before sending. Storing entries as SHA-256 hashes lets you match reliably without keeping a readable address for someone who has already asked not to be contacted.
Verifying your implementation
| Check | How |
|---|---|
| Both headers present | View raw source of a received campaign message |
| Native control renders | Look for Gmail's unsubscribe link beside the sender name |
| Endpoint accepts POST | POST to the URL with List-Unsubscribe=One-Click and expect success |
| Opt-out actually applies | Unsubscribe yourself, then try to include that address in a new campaign |
That last check is the one worth running periodically. A header that renders correctly but does not actually suppress the recipient is worse than no header at all — it produces a complaint from someone who believes they already opted out.