Updated: 28 September 2026 · Applies to: Email sent from your own server (RFC 8058)

Every marketing or subscription email needs a working way to unsubscribe. Mailbox providers now require two things: a clearly visible unsubscribe link in the message, and a one-click unsubscribe function in the message headers, which shows the recipient an "Unsubscribe" button in the mail app. This guide explains how both work, how to build them on your own server, and how to honour requests.

What providers ask for

  • Gmail (for senders of more than 5,000 messages a day to Gmail): marketing and subscribed messages must support one-click unsubscribe, with the headers List-Unsubscribe-Post: List-Unsubscribe=One-Click and List-Unsubscribe: <URL>, plus a clearly visible unsubscribe link in the message body.
  • Yahoo asks for a functioning List-Unsubscribe header with one-click support for marketing and subscribed messages, and asks you to honour unsubscribes within 2 days.
  • Ucartz's Acceptable Use Policy requires unsubscribe links for bulk or marketing mail, and lists mail that only allows opting out (without a real way to do so) as prohibited.

Transactional mail (a receipt or a password reset) is not subject to the one-click rule.

1. The headers

Add both headers to every marketing message, with a unique link for each recipient:

List-Unsubscribe: <https://example.com/unsubscribe.php?e=jane%40example.org&t=SIGNATURE>, <mailto:unsubscribe@example.com?subject=unsubscribe>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

The rules from RFC 8058:

  • One List-Unsubscribe and one List-Unsubscribe-Post header per message.
  • The List-Unsubscribe header must contain at least one HTTPS link. A mailto: link may be added as a second choice.
  • The link must contain enough information to identify the recipient and the list without cookies or a login.
  • The message must have a valid DKIM signature that covers both headers. The setup in How to set up DKIM signing with OpenDKIM and Postfix for several domains? does this.
  • The page must not answer the POST with a redirect.

2. The unsubscribe page

Two different requests reach the link: a person who clicks it in a browser (GET), and the mail program of the recipient that posts List-Unsubscribe=One-Click when the user presses the button (POST). A GET must not unsubscribe by itself, because security scanners open links in mail. Example in PHP (/var/www/example.com/unsubscribe.php):

<?php
$secret = 'CHANGE-THIS-TO-A-LONG-RANDOM-VALUE';
$email  = $_GET['e'] ?? '';
$token  = $_GET['t'] ?? '';
$valid  = $email !== '' && hash_equals(hash_hmac('sha256', $email, $secret), $token);
if (!$valid) { http_response_code(400); exit('This link is not valid.'); }

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // One-click request or confirmation form: record the unsubscribe.
    // Example: INSERT INTO suppression (email, created) VALUES (?, NOW())  (use a prepared statement)
    http_response_code(200);
    echo 'You have been unsubscribed.';
    exit;
}
// GET: ask for confirmation (do not unsubscribe on GET)
?>
<form method="post">
  <p>Unsubscribe <?= htmlspecialchars($email) ?> from our emails?</p>
  <button type="submit">Unsubscribe</button>
</form>

When you send, create the token the same way: hash_hmac('sha256', $email, $secret). The token prevents others from unsubscribing addresses by guessing. Serve the page over HTTPS and save the request in your subscriber database or suppression list.

3. The visible link

Put a plain link in the footer of every message ("Unsubscribe") that goes to the same page. It must be easy to see and work in one or two clicks.

4. Honour the request

  1. Save the address on a suppression list at once, together with the date and the list.
  2. Check the suppression list before every send, and remove those addresses from all outgoing queues.
  3. Never delete an unsubscribed address from your records; keep it on the suppression list so that it is not added again by an import.
  4. If you also accept mailto: unsubscribes, read that mailbox automatically and process the requests within the same time.

Ready-made tools

Open-source newsletter managers such as listmonk keep the subscriber and suppression lists for you, provide an unsubscribe page and, when the option is on, add the List-Unsubscribe headers. They send through any SMTP server, including your own Postfix. Whichever tool you use, open a test message and check that both headers are in the message source.

Test

  1. Send yourself a test message and open "Show original" in Gmail.
  2. Check that both headers are present and that the DKIM-Signature header contains list-unsubscribe and list-unsubscribe-post in its h= list.
  3. In Gmail the message shows an "Unsubscribe" link next to the sender name. Click it and check that your page receives a POST and records the request.

Common mistakes

  • Unsubscribing on GET, so that link scanners unsubscribe your readers.
  • A redirect in answer to the POST.
  • Headers added but not signed by DKIM.
  • A unique link that needs a login.
  • Ignoring the suppression list when you import a new list.

Frequently asked questions

Does it matter that the unsubscribe link is at another domain?
Use your own sending domain. It builds trust and keeps everything in one place.

What about replies that say "stop"?
Treat them as unsubscribe requests as well.

Sources: RFC 8058, Google's email sender guidelines and Yahoo's sender best practices.

Need a dedicated server, more IP addresses, or a hand with the setup?

Prefer a hand with the setup? Our engineers can do it for you: Hire an Expert, or use our on-demand server management.

Was this answer helpful? 0 Users Found This Useful (0 Votes)