- RFC 8058 one-click unsubscribe became mandatory for bulk senders to Gmail, Yahoo, and Microsoft consumer domains during the 2024-2025 enforcement wave, and Gmail moved from warnings to outright rejection in November 2025.
- Compliance requires two headers (List-Unsubscribe and List-Unsubscribe-Post), an HTTPS endpoint that accepts POST requests, and a DKIM signature that covers both headers.
- The most common implementation bug is an endpoint that returns a confirmation page rather than silently processing the POST. Inbox providers treat that as non-compliant.
- Mailbox providers may send the POST from any IP address with no warning, often within seconds of the user clicking. Your endpoint needs to be fast, idempotent, and require no human interaction.
- Transactional messages (password resets, receipts, order confirmations) are exempt from one-click unsubscribe and should not carry these headers; including them risks accidental opt-outs from critical alerts.
The one-click unsubscribe header has existed since 2017 as RFC 8058, but it sat almost entirely ignored until Gmail and Yahoo made it mandatory for bulk senders in February 2024. Microsoft followed in May 2025. By November 2025, Gmail transitioned from spam-foldering non-compliant messages to outright rejecting them at the SMTP layer. If you send 5,000 or more messages per day to any of these providers and you have not implemented one-click unsubscribe correctly, your mail is being rejected right now.
This guide is the technical implementation reference. Not "add this header and you are done," which is what most coverage stops at, but the full picture: header formatting, server-side POST handling, DKIM coverage, tokenization, idempotency, and the subtle bugs that silently break compliance even when everything looks correct on the surface.
What RFC 8058 Actually Requires
RFC 8058 layers on top of an older spec, RFC 2369 (the original List-Unsubscribe header). The combination of the two is what mailbox providers check for compliance.
The minimum compliant configuration on every marketing message:
List-Unsubscribe: <https://example.com/u/abc123token>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
That is it at the header level. Three rules govern these headers:
- The List-Unsubscribe URL must be HTTPS. HTTP is rejected. A mailto: address is allowed as a secondary entry but does not satisfy the one-click requirement on its own.
- The List-Unsubscribe-Post header must contain exactly the literal value
List-Unsubscribe=One-Click. Any other value, including extra whitespace inside the value, breaks the signal. - Both headers must be present on the same message. List-Unsubscribe without List-Unsubscribe-Post tells the inbox you support unsubscribe but not one-click; List-Unsubscribe-Post without List-Unsubscribe is malformed.
Why the Distinction Between List-Unsubscribe and One-Click Matters
Before RFC 8058, the List-Unsubscribe header by itself was ambiguous. The unsubscribe URL might lead to a confirmation page, a login wall, a survey, or a silent opt-out. Inbox providers could not safely click these URLs because they had no guarantee what would happen on the other end. Some providers fired GET requests to "prefetch" links for anti-phishing scanning, which could accidentally unsubscribe users from mailing lists they wanted.
RFC 8058 solves this by introducing a clear contract: the presence of List-Unsubscribe-Post: List-Unsubscribe=One-Click means "this URL is safe to fire as a POST, will silently process the unsubscribe, and will not require any further user interaction." Inbox providers can now confidently render a one-click "Unsubscribe" button in their UI, fire the POST when the user clicks, and trust that the operation completed.
The header on its own is the contract. The actual unsubscribe processing is your responsibility on the server.
The Server-Side Endpoint: What Your Server Must Do
The header is the easy part. The endpoint behavior is where most implementations break.
Accept POST Requests Without Confirmation
When a user clicks the inbox unsubscribe button, the mailbox provider sends a POST request to your URL with Content-Type: application/x-www-form-urlencoded and a body of List-Unsubscribe=One-Click. Your endpoint must:
- Accept the POST and return HTTP 200 (or 202) immediately.
- Process the unsubscribe silently. No confirmation page. No "are you sure?" interstitial. No login requirement.
- Add the recipient to your suppression list before the response is sent (or queue it for immediate background processing).
An endpoint that responds with HTML asking the user to confirm fails the one-click contract even if the visual experience seems user-friendly. The whole point is that the inbox provider, not the user, is making the click.
Also Handle GET (For Users Who Click Through)
The mailbox provider sends a POST. But users who click the body-text unsubscribe link in your footer will hit the same URL with a GET request. Your endpoint must distinguish between these and respond appropriately.
A clean pattern:
- POST: Silently process the unsubscribe, return 200.
- GET: Process the unsubscribe and show a confirmation page ("You have been unsubscribed from [list name]"). Optionally offer a preferences center, but the unsubscribe should already be done.
Returning a confirmation page on POST is one of the most common compliance bugs. It usually happens because developers built the GET-based unsubscribe page first, then added POST support by simply allowing the same route to accept POST. The handler renders HTML in both cases, and the inbox provider sees an HTML body where it expected a clean 200, flags the implementation as non-compliant, and stops surfacing the one-click button.
Tokenize the URL Uniquely Per Recipient
The URL must identify the specific recipient (and the specific list, if you operate multiple). Two patterns are common:
https://example.com/u/[opaque-token]
https://example.com/unsubscribe?u=[recipient_id]&l=[list_id]&sig=[hmac]
The opaque token pattern is generally cleaner: a single random or encrypted blob identifies everything needed without exposing internal identifiers. The query string pattern exposes more structure but allows signing each parameter individually.
Whatever pattern you use, the token must be:
- Unique per recipient. Reusing a token across recipients lets one user accidentally unsubscribe another.
- Cryptographically signed or random. An HMAC of recipient ID plus list ID plus a server-side secret prevents tampering. A purely sequential token lets attackers iterate through and mass-unsubscribe your list.
- Rotated or scoped per campaign. A token that is valid forever lets old forwarded messages unsubscribe users years later. A token with a 90-day expiration window is a reasonable balance.
Use a short URL host like u.yourdomain.com rather than your main site. The unsubscribe service is on a hot path that needs to respond quickly under load, and you want it isolated from your marketing site's caching, framework overhead, and deployment cycle. A purpose-built unsubscribe service running on a CDN edge or a tiny serverless function handles thousands of requests per second cheaply.
Make the Endpoint Idempotent
Inbox providers may retry the POST if they do not get a clean response, and users sometimes hit the same URL multiple times. The endpoint must return 200 on every call, even if the recipient is already unsubscribed. Returning 4xx on a "duplicate" unsubscribe is a bug that inbox providers may interpret as a broken endpoint.
A clean pattern: on any successful processing or any state where the recipient is in your suppression list, return 200. Only return 4xx for malformed tokens, expired tokens, or unparseable requests.
DKIM Must Cover the List-Unsubscribe Headers
The single most overlooked compliance requirement: your DKIM signature must explicitly include both the List-Unsubscribe and List-Unsubscribe-Post headers in the h= tag of the signature.
If your DKIM signature is configured as:
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=default;
h=from:to:subject:date;
bh=...;
b=...
The List-Unsubscribe headers are unsigned. A man-in-the-middle could rewrite them, the inbox provider knows this, and the one-click signal is rejected.
The correct configuration explicitly signs the unsubscribe headers:
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=default;
h=from:to:subject:date:list-unsubscribe:list-unsubscribe-post;
bh=...;
b=...
Most reputable ESPs handle this automatically. Self-hosted mail servers and custom sending pipelines frequently miss it. If your DKIM signature does not list the List-Unsubscribe headers in the h= tag, the inbox provider will not honor the one-click signal even if everything else is correct. You can verify this by inspecting the DKIM-Signature header on a delivered message and confirming both header names appear in the h= field.
Critical: DKIM coverage of List-Unsubscribe is one of the easiest compliance bugs to introduce and one of the hardest to detect, because the mail still sends successfully, the headers still appear, and only the one-click signal silently fails. Audit your DKIM signing config explicitly when you implement RFC 8058.
When NOT to Include the Headers
RFC 8058 applies to bulk marketing mail. Transactional messages like password resets, order confirmations, shipping notifications, account alerts, and two-factor codes should not carry one-click unsubscribe headers.
Two reasons. First, if the user clicks "Unsubscribe" on a password reset email, they have just opted out of receiving future password resets, which is almost certainly not what they intended. Second, transactional mail is exempted from bulk sender rules at every major provider, so the headers add risk without adding compliance benefit.
The clean separation pattern: marketing campaigns get List-Unsubscribe and List-Unsubscribe-Post. Transactional traffic does not. If your platform sends both types from the same code path, gate the header injection behind a message-type flag.
Common Implementation Bugs That Silently Break Compliance
The Endpoint Returns a Confirmation Page on POST
Covered above but worth repeating. If a POST to your endpoint returns HTML asking the user to confirm, the implementation is non-compliant. Inbox providers want a silent 200.
DKIM Does Not Cover the Unsubscribe Headers
Also covered above. Inspect your DKIM-Signature h= tag on a delivered message and confirm both List-Unsubscribe and List-Unsubscribe-Post appear.
The URL Uses HTTP Instead of HTTPS
HTTP URLs in the List-Unsubscribe header are rejected. This usually happens when development environments send real mail with localhost or HTTP staging URLs that get accidentally promoted to production templates. Always use HTTPS, including in staging.
Only a mailto: Entry, No HTTPS
The pre-RFC-8058 pattern of List-Unsubscribe: <mailto:[email protected]> is no longer sufficient. You can include the mailto as a secondary entry, but an HTTPS URL is required for one-click compliance.
The Endpoint Times Out or Returns 5xx
The POST is fired by the inbox provider in real time when the user clicks. If your endpoint takes more than a few seconds or returns a 5xx, the user sees a failed unsubscribe and is significantly more likely to click "Report Spam" instead. Treat the unsubscribe endpoint as a hot path with the same uptime expectations as your login service.
Tokens Allow Mass Unsubscription
If your tokens are sequential or guessable, an attacker can iterate through them and unsubscribe your entire list. Always use HMAC-signed tokens with a server-side secret, or fully random opaque tokens of sufficient length (at least 128 bits of entropy).
Testing Your Implementation
You cannot test one-click unsubscribe in a development environment because inbox providers will not fire POSTs against your local server. Test in production with controlled checks:
- Send a test campaign from your real production sending infrastructure to a Gmail address, an Outlook.com address, and a Yahoo address you control.
- Open each message in the respective inbox UI and confirm the one-click "Unsubscribe" button appears next to the sender name or at the top of the message.
- Click it. Confirm your suppression list updates within seconds.
- Send another test to the same address and confirm it does not deliver (or hits your suppression filter at the application layer).
- Inspect the raw headers of the delivered test message and verify both List-Unsubscribe and List-Unsubscribe-Post are present, the URL is HTTPS, and both headers appear in your DKIM signature's
h=tag.
If any major inbox provider does not show the one-click button, the issue is almost always one of the bugs in the previous section. Inspect the headers, fix the issue, and re-test.
The Reputation Impact of Getting This Right
One-click unsubscribe directly affects your spam complaint rate, which is the metric mailbox providers use most aggressively to throttle and block senders. When users can unsubscribe in one click, they take that action instead of clicking "Report Spam." Industry data consistently shows complaint rates dropping 30-50% after correct RFC 8058 implementation.
Because the 0.3% complaint threshold at Gmail, Yahoo, and Microsoft triggers throttling and blocking, even a modest reduction in complaints can be the difference between healthy Sender Reputation and a domain-level block. The cost of implementing one-click unsubscribe correctly is a few hours of engineering work. The cost of not implementing it is, increasingly, the entire deliverability of your marketing program.
Frequently Asked Questions
Yes. RFC 8058 one-click unsubscribe is an additional layer, not a replacement for the visible footer link. CAN-SPAM and similar laws require a clear unsubscribe mechanism in the message body. Some recipients still scroll to the footer rather than using the inbox UI, and not every email client surfaces the one-click button.
Target sub-2-second response times under normal load and never more than 10 seconds. Mailbox providers fire the POST in real time when the user clicks, and a slow response degrades the user experience and may cause the provider to mark the implementation as broken. Acknowledge the request immediately and process the suppression list update in the background if needed.
Return HTTP 200 on successful processing. HTTP 202 (Accepted) is also acceptable if you queue the unsubscribe for asynchronous processing. Do not return 4xx for already-unsubscribed users; return 200 because the desired state (user is suppressed) is already achieved. Reserve 4xx for genuinely malformed requests like invalid tokens.
Most reputable ESPs add the headers automatically and host the unsubscribe endpoint on their own infrastructure. SendGrid, Mailchimp, Brevo, Postmark, and ActiveCampaign all handle RFC 8058 compliance out of the box. If you use a smaller ESP or self-host, verify by inspecting the headers on a sent message. Custom sending pipelines almost always need explicit implementation work.
No. The "one-click" contract means the unsubscribe completes silently when the POST is received. Requiring login, email confirmation, or any human interaction after the POST violates the contract and inbox providers will detect this and stop honoring the one-click signal. If you need re-engagement, send a follow-up email separately rather than blocking the unsubscribe itself.