When a mail client shows an «Unsubscribe» button next to the sender's name, it is not reading the link at the bottom of the newsletter. It is reading a message header, List-Unsubscribe, designed precisely to allow unsubscribing without opening web pages. Implementing it properly benefits everyone: a user who no longer wants the messages has an alternative to the «report spam» button, and the sender avoids a complaint that weighs on its reputation.
The two headers
List-Unsubscribe
This is the original header and it can contain an email address, a URL or both, in angle brackets and separated by a comma:
List-Unsubscribe: <mailto:unsub@example.com?subject=unsub-u83kd9>, <https://example.com/unsub/u83kd9>
With the mailto form alone, the client sends an email to the given address. With the URL form, as originally defined, the client could open the page in a browser.
List-Unsubscribe-Post
RFC 8058 added a second header that turns the URL into an automatic action:
List-Unsubscribe-Post: List-Unsubscribe=One-Click
When it is present, the client sends an HTTP POST request to the List-Unsubscribe URL, with the body List-Unsubscribe=One-Click. No page to visit, no form to fill in. This is the form that large providers now require from bulk senders for promotional messages.
Why POST in particular
The choice of POST is not accidental. Many corporate security systems and some spam filters automatically visit the links in messages to check whether they lead to malicious sites. If unsubscribing happened with a simple GET request, these checks would unsubscribe users without their knowledge. POST avoids the problem: scanning systems don't send POST requests.
This leads to a practical rule: the endpoint must unsubscribe only on POST. A GET request to the same URL may show a confirmation page, but must not change anything.
Designing the endpoint
Identify the subscriber without exposing them
The URL must contain an opaque identifier, not the email address in clear text. A good approach is a token that encodes the subscriber and the list, signed with a server secret key, for example using HMAC. That way the server can verify the token has not been tampered with without consulting a table of one-time tokens.
Ask the user for nothing
The POST request comes from the mail client, not from the user in a browser. The endpoint cannot ask for a login, confirmations, cookies or a CAPTCHA. It must respond with a success code and record the unsubscribe.
Be idempotent
The same user may press the button twice, or the client may repeat the request after a network error. The second request must produce the same result as the first, without errors.
Respond quickly
The client expects a fast response. If unsubscribing involves slow operations, such as syncing with a CRM, record the request and complete the rest asynchronously.
A minimal sketch of the expected behaviour:
POST /unsub/u83kd9.f2a1c0
Content-Type: application/x-www-form-urlencoded
List-Unsubscribe=One-Click
→ 200 OK (subscriber u83kd9 removed from the list, action logged)
The DKIM signature must cover the headers
RFC 8058 requires the message to carry a valid DKIM signature that includes both List-Unsubscribe and List-Unsubscribe-Post in its h= list. Without this protection, an intermediary could replace the URL and turn the button into a tool for abuse. Many providers ignore the header if it is not signed.
Recurring mistakes
| Mistake | Effect |
|---|---|
http URL instead of https |
many clients don't show the button |
| Unsubscribing on GET | users unsubscribed by security scanners |
| Endpoint that redirects to a login page | single click doesn't work |
| Headers not covered by DKIM | the provider may ignore them |
| Token reusable for other lists | unintended unsubscribes from everything |
| Requests processed days later | the user still gets messages and reports them |
One list or all lists?
The header refers to the list that generated the message. Unsubscribing the user from that list only is the correct and expected behaviour. In the message body you can then offer a richer preference centre, where people choose topics or frequency. The two coexist: the client's button does one thing and does it immediately, the preferences page offers the nuances.
In my work I always test the full flow with a real message: headers present, signature covering them, POST request returning success, subscriber actually removed and no further sends.
In short
List-Unsubscribesays where to unsubscribe;List-Unsubscribe-Postmakes it automatic via POST.- The endpoint must act only on POST, so it isn't triggered by scanners that visit links.
- The token in the URL must be opaque and signed, and the endpoint idempotent and free of user prompts.
- The DKIM signature must include both headers.
- The client's button unsubscribes from one list; the preference centre in the body offers finer options.