Email infrastructure

One-click unsubscribe, the header that actually counts.

The most under-implemented bulk-sender requirement is not the unsubscribe link in your footer — it is the List-Unsubscribe-Post header that Gmail and Yahoo specifically check for. RFC 8058 one-click needs two headers (List-Unsubscribe with an HTTPS URI, and List-Unsubscribe-Post set to exactly List-Unsubscribe=One-Click), both DKIM-signed, plus an HTTPS endpoint that completes the opt-out on POST and returns 200 — no login, no redirect, no confirmation page. Get it right and you cut spam complaints; get it wrong and link scanners can unsubscribe people for you.

In short

  • The footer link is not enough. Bulk promotional mail needs the header-based one-click, not just a link in the body.
  • Two headers, both DKIM-signed. List-Unsubscribe (HTTPS URI) plus List-Unsubscribe-Post set to exactly List-Unsubscribe=One-Click.
  • POST only, never GET. Opt out on POST and return 200; a GET-triggered unsubscribe lets scanners opt people out by accident.
  • No redirect, no preference page. The endpoint must complete the opt-out itself, within 48 hours.
  • Promotional only. Transactional mail — resets, receipts, confirmations — is exempt.

Why isn't the footer unsubscribe link enough anymore?

For years the unsubscribe link at the bottom of an email was the whole story. Since Gmail and Yahoo began enforcing bulk-sender rules in 2024, it is only half of it. The providers now expect a header-driven one-click mechanism their own interface can trigger — a native Unsubscribe button rendered next to your sender name that completes the opt-out without sending the recipient to a third-party page. The footer link is still required, by anti-spam law and by the providers, but on its own it no longer satisfies the requirement for promotional mail.

The reasoning is behavioural, and it is the whole point of the standard. When leaving a list is genuinely one click, recipients use it; when it is buried or awkward, their alternative is to hit Report Spam instead. Mailbox providers know users do not distinguish between unsubscribing and marking as junk, so they reward senders who make exit frictionless. A clean one-click exit that does not count as a spam complaint is, in practice, a direct lever on the complaint rate that decides your deliverability.

That is why this one header carries so much weight relative to its size. Benchmark data repeatedly names the List-Unsubscribe-Post header as the single most under-implemented bulk-sender requirement: teams add a visible footer link, see an unsubscribe option in their own email, and assume they are compliant — while omitting the one header Gmail actually checks for. The gap is small to fix and expensive to ignore, because since late 2025 missing it can move you from delayed delivery to outright rejection.

What exactly are the two headers?

One-click is a pair of headers that work together, defined by RFC 8058 (one-click POST signalling), built on RFC 2369 List-* headers. The first advertises the unsubscribe mechanism; the second signals that it is genuinely one-click and must be processed by an HTTP POST. Miss either and you do not have one-click — you have an ordinary link.

message headers — promotional mail
# Two headers on every promotional message — both must be DKIM-signed
List-Unsubscribe: <https://example.com/u/9f2c4a8e>,
                  <mailto:unsub@example.com?subject=unsubscribe>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
# the -Post value must be EXACTLY this; it is the one-click signal
The required pair: an HTTPS URI in angle brackets, plus the exact one-click signal.

Three details decide whether this works. The List-Unsubscribe header must contain at least one HTTPS URI, inside angle brackets — missing brackets are the most common reason a header is present but does nothing. The List-Unsubscribe-Post value must be exactly List-Unsubscribe=One-Click. And both headers must be covered by a valid, aligned DKIM signature, because a receiver that cannot verify them may ignore them entirely — which is how headers injected by middleware after signing quietly fail.

Including a mailto: URI alongside the HTTPS one is good practice, but a mailto on its own does not satisfy the requirement, because it cannot guarantee instant automated processing. The HTTPS URI is what carries the POST mechanism; the mailto is there for Apple Mail and older clients that prefer it.

The HTTPS URI itself deserves a moment of thought, because it is where security and reliability meet. RFC 8058 recommends that the unsubscribe URL carry an opaque, hard-to-forge identifier rather than a plain email address in the query string. The reason is twofold: a plain address is trivial for anyone to tamper with, and it leaks the recipient's address to anything that logs URLs along the way. An opaque token — a random, non-guessable string that your system maps back to the right recipient and list — lets the POST complete immediately while keeping the address private and the request hard to abuse. It also means the URL carries everything the endpoint needs to act on its own, which is exactly what one-click requires: the opt-out must succeed from the POST alone, without the endpoint reaching back to a session, a cookie, or a logged-in state that a mailbox provider's server will never have.

Implementation

Implementing it end to end

Six steps from separating your streams to verifying on a delivered message. A competent engineer ships this in an afternoon — the value is in getting the details exactly right.

  1. 1

    Identify your promotional streams

    One-click applies to marketing and subscription mail, not transactional. The first step is not to add headers everywhere — it is to separate promotional streams (newsletters, campaigns) from password resets, receipts, and confirmations, which are exempt.

  2. 2

    Generate an opaque per-recipient token

    Build an unsubscribe URL that identifies the recipient and list well enough to act immediately, using a hard-to-forge opaque token rather than a plain email address. The POST must carry everything needed to complete the opt-out on its own.

  3. 3

    Add both headers, DKIM-signed

    Add List-Unsubscribe with an HTTPS URI (and a mailto for Apple Mail), plus List-Unsubscribe-Post with the exact value List-Unsubscribe=One-Click. Both headers must be inside the DKIM signature, or receivers may ignore them.

  4. 4

    Build a POST endpoint that completes the opt-out

    The HTTPS endpoint must unsubscribe the recipient and return 200 OK on POST, with no login, no redirect chain, and no confirmation page. Crucially, never opt out on GET — scanners prefetch links and will silently unsubscribe people.

  5. 5

    Suppress in real time, within 48 hours

    Process the opt-out immediately and stop sending within the 48-hour window the providers require. A delayed batch job means people keep receiving mail after opting out, which is exactly when spam complaints spike.

  6. 6

    Verify on the delivered message

    Send a live message through the real campaign path and read the raw delivered headers — not a test send — because some stacks add the headers on one path but not another. Then POST to the endpoint with curl to confirm it actually removes the recipient.

The detail that catches the most careful teams is the multi-path problem: campaign mail, lifecycle mail, and legacy mailers often travel different routes, and one path gets the headers right while another silently does not. Verifying on the real delivered message, not a test, is what surfaces it.

How do I verify it actually works?

Do not judge it by whether the inbox button appears. The Unsubscribe button frequently does not show on a test send even when the implementation is perfect, partly because providers weigh sender reputation before rendering it. The only reliable check is to read the raw headers of a delivered message and then exercise the endpoint directly.

verify the POST endpoint
# Verify the endpoint opts out on POST alone — no login, no redirect, 200 OK
curl -i -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data "List-Unsubscribe=One-Click" \
  https://example.com/u/9f2c4a8e
# expect: 200 OK, and the recipient actually removed from the list
A compliant endpoint removes the recipient on this POST alone — no further click.

The test should confirm two things: that the endpoint returns 200 and that the recipient is genuinely removed from the intended list, with no login, redirect chain, or confirmation page standing in the way. If any of those appear, you have a working link but not RFC 8058 one-click, and the providers will treat it as non-compliant.

Pitfalls

The mistakes that quietly break one-click

Most of these pass a casual look in your own inbox and only surface as rising complaints or sudden rejections.

MistakeWhy it breaks
Triggering unsubscribe on GETSecurity scanners and link prefetchers fetch URLs and silently opt people out; one documented case mass-unsubscribed thousands of Microsoft recipients. Process opt-outs only on POST.
Missing the List-Unsubscribe-Post headerThe footer link or a plain List-Unsubscribe is present, but without the -Post header there is no one-click signal Gmail and Yahoo require.
Mailto-only headerA mailto URI alone cannot guarantee instant automated processing; an HTTPS URI is required for the POST mechanism.
Non-HTTPS URLPlain HTTP endpoints do not satisfy RFC 8058; Gmail ignores them.
Redirecting to a preference centreThe endpoint must complete the opt-out and return 200; redirecting to a confirmation or preferences page breaks one-click and reads as non-compliant.
Missing angle bracketsThe #1 'header is there but nothing happens' cause — the URL must sit inside <...>.
Headers added after signingMiddleware or a downstream path that injects headers after DKIM signing leaves them unsigned, so receivers may ignore them. Multiple mail paths often differ silently.

The one to take most seriously is the GET-triggered unsubscribe. It feels harmless in testing, because a human clicking a link does the right thing — but in production, automated scanners and previewers fetch header URLs constantly, and every one of those fetches silently opts someone out. Processing opt-outs only on POST is not a nicety; it is the specific problem RFC 8058 was written to solve.

The flow

What happens when someone clicks Unsubscribe

The one-click path, and where the common implementations fall off it.

The one-click POST flow
Recipient clicksnative Unsubscribe buttonin the inbox UI Provider POSTsList-Unsubscribe=One-Clickto your HTTPS endpoint Endpoint opts outreturns 200 OKwithin 48 hours · no extra step GET must never trigger the opt-out — scanners prefetch URLs

Two clients sit outside this clean path and need handling. Apple Mail uses the mailto URI and ignores the POST, so you must also accept inbound unsubscribe emails; Outlook's webmail can block a sender for a user internally without ever calling your endpoint, so you keep getting complaints you cannot see — which is why a prominent in-body link remains your backstop. Belt, suspenders, and a backup belt.

The 48-hour window and real-time suppression

The headers are only half the obligation; honouring the request is the other half. When a recipient clicks Unsubscribe, the providers require the opt-out to be processed within 48 hours, and Google's own guidance pushes senders to act faster where they can. That window sounds generous until you look at how most sending stacks actually suppress: in a delayed batch job that runs overnight, or once a day, or whenever the next campaign is built. Anything slower than near-real-time means people keep receiving mail after they have explicitly asked to stop.

That lag is precisely where complaints come from. A recipient who unsubscribes and then receives another message the next morning does not assume your batch job is behind — they assume you ignored them, and they reach for Report Spam, which is the exact outcome the whole mechanism exists to prevent. The fix is to treat the unsubscribe POST as an event that updates suppression immediately, before the next send can pick the address back up, rather than as a row to be reconciled later.

Idempotence matters here too, and it is easy to overlook. Providers and scanners can send the same POST more than once, so your endpoint must treat a repeated unsubscribe as a no-op that still returns 200, not as an error and certainly not as something that could toggle a re-subscription. An endpoint that unsubscribes cleanly on the first POST but throws on the second is a subtle bug that surfaces as confusing support tickets and the occasional person who claims they were resubscribed against their will.

How one-click ties into your complaint rate and the law

One-click is not a standalone box to tick; it sits directly on top of the complaint-rate threshold that governs your deliverability. Gmail and Yahoo want bulk senders below a 0.1% spam-complaint rate and treat anything above 0.3% as a filtering trigger. At scale that is a razor-thin margin, and a frictionless unsubscribe is one of the few levers that moves it in your favour: every recipient who leaves cleanly through the header is a recipient who did not instead file a complaint. A correct one-click implementation is, in that sense, complaint-rate management by another name.

It also lives inside a legal frame worth respecting on its own terms. A visible in-body unsubscribe link is mandated by anti-spam law independently of what Gmail and Yahoo ask for, and the penalties for getting opt-out wrong are not trivial — under CAN-SPAM in the United States, violations are assessed per individual email, not per campaign, which turns a sloppy unsubscribe flow into a genuine liability at volume. The header-based one-click and the legally required footer link are two distinct obligations that happen to point the same way.

The encouraging part is that compliance and good practice converge completely here. There is no version of this where the deliverability-optimal choice and the recipient-friendly choice diverge: the same frictionless exit that keeps you below the complaint threshold is also the one that respects the person who no longer wants your mail. That alignment is rare enough in deliverability that it is worth naming — most levers involve a trade-off, and this one does not.

Where we stand

We host sending infrastructure, and on the platforms we run, the compliant headers are part of the setup rather than an afterthought — a self-hosted KumoMTA or PowerMTA stack can emit a correct List-Unsubscribe pair, DKIM-signed, on every promotional message, and a clean POST endpoint is a small piece of glue. The honest point, though, is that the headers are the easy part. The harder, more valuable work is keeping the streams separated, the suppression real-time, and the list clean enough that few people want to leave in the first place.

So our advice is to treat one-click as table stakes and then move past it: ship the two headers and the POST endpoint this week, verify them on a delivered message, and spend the saved energy on list hygiene and engagement, which is where deliverability is actually won or lost. If you send with us, we will make sure the headers are correct and signed; if you self-host or use an ESP, the same standard applies regardless of who runs the servers.

Questions

Answered plainly

The questions teams ask before shipping one-click unsubscribe.

Isn't the unsubscribe link in my footer enough?

No, not for bulk promotional mail. The footer link is still required by anti-spam law and by the providers, but it does not satisfy the one-click requirement on its own. Gmail and Yahoo specifically look for the List-Unsubscribe-Post header, which lets their interface render a native Unsubscribe button next to your name and complete the opt-out with a single POST. The footer link and the header-based one-click are complementary: keep both.

What exactly does List-Unsubscribe-Post need to contain?

Exactly the value List-Unsubscribe=One-Click — nothing else. That string is not decorative; it is the signal defined by RFC 8058 that tells the receiver it may perform an HTTPS POST for a direct unsubscribe. Pair it with a List-Unsubscribe header that contains at least one HTTPS URI inside angle brackets. This is where many otherwise-correct setups quietly miss the point: they have List-Unsubscribe but omit the -Post header, so there is no one-click signal at all.

Does one-click unsubscribe apply to transactional email?

No. Password resets, receipts, shipping notifications, and reservation confirmations are exempt — the requirement targets promotional and subscription mail. The providers distinguish the two largely by content and recipient behaviour rather than your intent, so the practical move is to separate your promotional streams and apply the headers there, while leaving genuinely transactional mail alone.

Why did link scanners unsubscribe people automatically?

Because the endpoint opted out on a GET request. Security tools, antivirus, and inbox previews routinely prefetch URLs in headers, and if your unsubscribe fires on GET, those automated fetches silently opt people out — one documented case mass-unsubscribed thousands of Microsoft recipients this way. RFC 8058 exists precisely to prevent this: the opt-out must happen only on POST, never on GET. A GET should at most show an information page.

How do Apple Mail and Outlook differ here?

Apple Mail renders an Unsubscribe banner that uses the mailto URI and ignores the HTTPS POST entirely, which is why you should include both a mailto and an HTTPS URI and be ready to process inbound unsubscribe emails. Outlook is trickier: its webmail quick action can block the sender for that user internally without ever calling your endpoint, so you never receive the signal and keep sending — which then drives complaints. The defence is to keep a prominent in-body unsubscribe link as a fallback alongside the headers.

How do I verify my implementation actually works?

Do not rely on whether the inbox button appears — it often does not show on test sends even when everything is correct, partly because providers weigh sender reputation before displaying it. Instead, send a live message through your real campaign path and read the raw delivered headers to confirm both are present and DKIM-signed. Then POST to the endpoint with curl, sending List-Unsubscribe=One-Click, and confirm the recipient is actually removed with no login, redirect, or confirmation page required.

Want one-click handled correctly from the start?

Tell us how you send, and we will make sure your promotional mail carries correct, DKIM-signed one-click headers — and a POST endpoint that opts people out cleanly.