List-Unsubscribe and One-Click Unsubscribe (RFC 2369 & RFC 8058)
Exact syntax and semantics of the List-* header fields and the one-click List-Unsubscribe-Post mechanism, including DKIM requirements and why major mailbox providers mandate them.
Two RFCs define the standard machine-readable unsubscribe mechanism:
- RFC 2369 (1998) defines the
List-*header fields, includingList-Unsubscribe. - RFC 8058 (2017) adds
List-Unsubscribe-Post, turning the HTTPS variant into a one-click action that mail clients can perform on the user's behalf without loading a web page.
Together they are the plumbing behind the "Unsubscribe" link that Gmail, Yahoo, Apple Mail, and Outlook.com render next to the sender name.
RFC 2369: the List-* header fields
RFC 2369 defines six header fields for messages distributed by a mailing list:
| Header | Purpose | Notes |
|---|---|---|
List-Help |
Full instructions for the list | Considered the most important field; acceptable as a standalone implementation |
List-Unsubscribe |
Command/URL to leave the list | The field mailbox providers act on |
List-Subscribe |
Command/URL to join the list | |
List-Post |
How to post to the list | Special value NO for lists that do not accept posting (announcement lists) |
List-Owner |
Contact for the list administrator | |
List-Archive |
How to access the list archives |
Syntax rules
- Field contents are angle-bracket-enclosed URLs:
<mailto:...>or<http://...>. Internal whitespace inside brackets is ignored; generators must not insert whitespace within brackets, but clients should tolerate poorly formatted entries. - Multiple alternate URLs MAY be given as a comma-separated list of angle-bracket-enclosed URLs. Order is preference, left to right — a client uses the leftmost protocol it supports (e.g. HTTPS first,
mailto:fallback). - Optional comments in parentheses may follow a URL:
List-Post: NO (posting not allowed on this list). - At most one of each field per message.
- The fields MUST only be generated by the list/sending system, never by end users.
- Fields implemented for a list SHOULD appear on all messages distributed by that list.
- Client parsing rules: if the field content begins with anything other than
<, the field SHOULD be ignored; characters after a closing>are ignored unless the next non-whitespace/comment character is a comma; a comma-separated sub-item that is not an angle-bracket URL causes the remainder of the field to be ignored. - Sublists redistributing a parent list's mail should replace the parent's
List-Help,List-Subscribe,List-Unsubscribe, andList-Ownerwith their own, preservingList-Archiveunless they provide their own.
Examples (from the RFC)
List-Unsubscribe: <mailto:list@host.com?subject=unsubscribe>
List-Unsubscribe: <http://www.host.com/list.cgi?cmd=unsub&lst=list>,
<mailto:list-request@host.com?subject=unsubscribe>
List-Help: <http://www.host.com/list/>, <mailto:list-info@host.com>
List-Subscribe: <http://www.host.com/list.cgi?cmd=sub&lst=list>,
<mailto:list-manager@host.com?body=subscribe%20list>
List-Post: <mailto:list@host.com>
List-Owner: <mailto:listmom@host.com>
List-Archive: <http://www.host.com/list/archive/> (Web Archive)
For mailto: URLs, clients are expected to show a confirmation dialog (destination + command) before sending.
RFC 8058: one-click unsubscribe (List-Unsubscribe-Post)
Problem RFC 8058 solves: a plain HTTPS List-Unsubscribe URL cannot safely be fetched automatically — anti-spam scanners, link prefetchers, and security proxies follow GET links, which would unsubscribe users who never asked. RFC 8058 defines a POST-based signal that only a deliberate mail-client action produces.
Header syntax
list-unsubscribe-post = "List-Unsubscribe-Post:" 0*1WSP postarg CRLF
postarg = "List-Unsubscribe=One-Click"
The header value is exactly List-Unsubscribe=One-Click — nothing else is valid.
Requirements on the sender
| Requirement | Level |
|---|---|
Message carries a List-Unsubscribe header containing one HTTPS URI (other URIs such as mailto: MAY also be present) |
MUST |
| The HTTPS URI contains enough information to identify the recipient and the list, so unsubscription completes with no further input | MUST |
| The URI includes an opaque, hard-to-forge component (e.g. HMAC over recipient+list), verified server-side | SHOULD |
| The unsubscribe endpoint completes the action without any further interaction with the user (no login, no confirmation form) | MUST |
| The POST endpoint does not return HTTPS redirects (redirected POSTs are historically unreliable) | MUST NOT |
Message has at least one valid DKIM signature whose h= tag covers both List-Unsubscribe and List-Unsubscribe-Post |
MUST |
If the required DKIM signature is absent or invalid, the mail receiver SHOULD NOT offer one-click unsubscribe — this is what prevents an attacker from injecting forged unsubscribe headers.
POST semantics (what the mailbox provider sends)
When the user clicks the client's unsubscribe control, the mail receiver performs an HTTPS POST to the URI from List-Unsubscribe, with the key/value pair from List-Unsubscribe-Post as the body:
Content-Type:multipart/form-data(SHOULD) orapplication/x-www-form-urlencoded(MAY).- Body: the single pair
List-Unsubscribe=One-Click. - The request MUST NOT include cookies, HTTP authorization, or any other context information — so the endpoint cannot rely on session state, only on the URI itself.
- The receiver MUST NOT perform the POST without user consent (i.e. only on an explicit user action, never speculatively).
Examples (from the RFC)
List-Unsubscribe: <https://example.com/unsubscribe/opaquepart>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
POST /unsubscribe/opaquepart HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 26
List-Unsubscribe=One-Click
With a mailto: alternative and multipart/form-data:
List-Unsubscribe:
<mailto:listrequest@example.com?subject=unsubscribe>,
<https://example.com/unsubscribe.html/opaque123456789>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
POST /unsubscribe.html/opaque=123456789 HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=---FormBoundaryjWmhtjORrn
Content-Length: 124
---FormBoundaryjWmhtjORrn
Content-Disposition: form-data; name="List-Unsubscribe"
One-Click
---FormBoundaryjWmhtjORrn--
Security model
- Limiting the POST body to one fixed pair prevents the header from being abused to drive arbitrary form submissions.
- Excluding cookies/authorization prevents linking the unsubscribe to the user's other web activity.
- As with classic
List-Unsubscribe, anyone with a copy of the message can unsubscribe the recipient — the opaque URI component is the mitigation, not a cure.
Why Gmail and Yahoo mandate it
Since February 2024, Gmail and Yahoo require bulk senders (Gmail's threshold: ~5,000+ messages/day to their users) to include RFC 8058 one-click unsubscribe on commercial/promotional mail and to honor unsubscribes within two days. The rationale maps directly to deliverability fundamentals (see Foundations of Email Deliverability):
- A frictionless unsubscribe is the alternative to the "report spam" button. Every user who unsubscribes instead of complaining protects your complaint rate (Gmail: keep spam-rate below 0.10%, never above 0.30%).
- The DKIM-coverage requirement ties the unsubscribe promise to an authenticated domain, complementing DMARC alignment.
- Because the POST carries no cookies or context, honoring it requires sender-side infrastructure that actually maps the opaque token to a real suppression — a proxy for list-hygiene competence.
Sender implementation checklist
- Add both headers to every commercial/list message; keep
mailto:as a fallback URI alongside the HTTPS one. - Sign with DKIM and include both headers in the signature's
h=list. - Make the endpoint idempotent, redirect-free, and instant — suppress on POST, no login, no "are you sure?".
- Feed one-click unsubscribes into the same suppression list as complaints from feedback loops; process within 48 hours at the latest.
- Keep the in-body unsubscribe link too — the headers complement, not replace, it.