MAILCRAFT
Home Features Pricing About Blog Contact Log in Get Started →
Deliverability best practices

List-Unsubscribe and one-click unsubscribe

Drewniany organizer na listy z kopertami, żółte tło

The List-Unsubscribe header is one line in the message source that decides whether the recipient clicks “unsubscribe me” or “this is spam”. Mailbox providers read it and draw an unsubscribe button next to the sender name, before anyone opens the content. We run our own fleet of sending servers and we see it every day: same list, same content, no header – and more complaints. And a complaint sits on domain and IP reputation for months. An unsubscribe? It deletes one record from the database. That is all.

What List-Unsubscribe is and why filters require it

Formally it is an optional message header that gives the mail client an address for cancelling a subscription. There are two variants. The older one is mailto: – the client generates an empty reply to the given address, and the sender has to receive it and process it. The newer one is https:, a link to an endpoint on the sending system side.

One-click unsubscribe is a separate story, built on top of that second variant. It requires an extra header, List-Unsubscribe-Post, with the value List-Unsubscribe=One-Click. Only that header tells the mail client: you can send the request yourself, without opening a browser and without asking the user for anything more.

Why do filters watch this? Because they have hard data on how people react to unwanted messages. If opting out means hunting for a link in the footer, scrolling to the end of the message and going through a page with a form, a good share of recipients will pick the spam report button. It is closer. It works right away. The whole mechanics of List-Unsubscribe comes down to shifting that choice: unsubscribing has to be faster than complaining.

Large providers treat a missing header in bulk sending as a negative signal in itself, regardless of everything else. This is not a matter of good practice. It is the entry ticket for a sender who wants predictable deliverability, alongside the other Gmail and Yahoo requirements for bulk senders.

How it works technically: headers, POST and the server response

In the message you send you place two headers. The first contains the unsubscribe variants in angle brackets, separated by a comma. The order matters in practice: you put the https variant first, mailto as a fallback for older clients. The second header, List-Unsubscribe-Post, takes one allowed value and turns on one-click handling.

The rest happens without the recipient. The mail client sends a POST request to the address from the header. The request body is List-Unsubscribe=One-Click, sent as form data. The user sees no page. There is no browser, no session, no cookies.

So the endpoint has to cope on its own. You record the unsubscribe right away, during that request, and you answer with a code in the 2xx range. A confirmation screen, a redirect to a marketing page or a request to log in break the whole operation – some clients will treat the response as an error and show the recipient a message about a failed unsubscribe.

The recipient is identified by a token in the address. Signed, so that nobody unsubscribes someone else’s address by swapping a parameter, and mapped to exactly one pair: address plus list.

  • POST method – a GET can come from a link scanner, so you do not unsubscribe on it.
  • No authentication – no login, no session token.
  • A 2xx code in the response, no redirects.
  • Idempotency – the second and third request end the same way as the first.
  • HTTPS with a valid certificate, full chain of trust.
  • Short response time – seconds count, not tens of seconds.

Common implementation mistakes and their effect on deliverability

The most common mistake is organisational, not technical: the header reaches only part of the sending. Campaigns have it, and “transactional” messages with an offer glued on do not. But the filter judges the content, not your internal classification. Is there a promotion in the message? Then it is a marketing send.

Second mistake: the https address leads to a normal unsubscribe page with a button to click. The header is there, one-click unsubscribe is not. The mail client will send a POST, get HTML with a form and treat the operation as failed.

The third one concerns domains. An endpoint on a domain unrelated to the one authenticated in DKIM and named in the DMARC policy looks suspicious to the filter and to the recipient who takes a look at the address. Keep it on a subdomain of your own sending domain.

The fourth is a token with the email address written out in plain sight. Addresses then leak through the logs of intermediate servers and through security scanners. Use a random value or a signed identifier.

The fifth hurts most: the unsubscribe is recorded, but the sending queue is already built. The recipient opts out and gets another message. Then they click the spam report – and they are right. The consequences are predictable: complaints instead of unsubscribes, a drop in the reputation of the domain and of the IP addresses, filtering to the spam folder for the whole list. It is one of the most common reasons messages end up in the spam folder.

Tip: open the source of your last send in a mail client, copy the address from the header and send a plain POST request to it with the body List-Unsubscribe=One-Click. Check the response code and whether the record in the database actually changed. Do it before the campaign starts, not after.

Unsubscribe and consent: GDPR, PKE article 398 and B2B

Technical correctness does not replace a legal basis. Consent for commercial sending is required towards companies too. An address found in the business register or on a contact page is not consent – it is only contact data made available for a different purpose. The Polish electronic communications law, PKE, ties direct marketing in article 398 explicitly to the recipient’s prior consent, and GDPR requires that this consent can be demonstrated.

This is where the rule the whole unsubscribe mechanism rests on comes from: withdrawing consent has to be as easy as giving it. Since signing up did not require a login, unsubscribing cannot require one either. A form asking for a password or for the reason for leaving is a breach of that principle, not retention.

Proof of consent is a specific set of data that you keep together with the address:

  • the date and time of sign-up,
  • the source – form, import, integration with an external system,
  • the exact wording of the clause as it stood on the day of sign-up,
  • the IP address at confirmation.

Keep the unsubscribe register as a separate event history, not as a single flag in a column. A flag can be overwritten by an import. An entry in the history shows when and through which channel someone opted out, and it lets you catch an address that came back onto the list from a new CSV file. This is a matter of process, not of code itself. We treat compliance as part of the product: if the platform makes it easy to do something unlawful, that is a flaw in the platform.

The header is one thing, domain authentication is another

One-click unsubscribe does not work in a vacuum. Authentication has to line up first. SPF, DKIM and DMARC have to be consistent with the domain in the From field and with the Return-Path. A mismatch between them is a typical cause of rejections, and one you only see in the recipient’s headers.

Set the Return-Path on your own subdomain, so that bounces come back where the system will process them. Without that, hard bounces get lost and the list swells with mailboxes that do not exist. On top of that, the PTR record for the IP address has to point to the host name of the sending server, and that name has to resolve back to the same address.

From experience with our own fleet: a new IP address has to be warmed up. Volume grows gradually, starting with the most engaged recipients, following a warmup plan spread over eight weeks. A sudden jump in sending on a fresh address ends with throttling or a block at a large provider. I have seen it more than once.

Getting out of such a block always looks similar. You cut sending to a minimum. You clean the list of addresses that do not receive. You switch off hard bounces immediately, not after three attempts. Then you come back with volume slowly. Really slowly.

And the most important thing: the header alone will not fix a list built without consent. The order of work matters. First the legal basis and a clean database, then authentication, and the unsubscribe mechanics at the end.

Step by step implementation in practice

  1. Generate a token for the recipient-list pair, signed with a key on the server side.
  2. Add both headers to every bulk send, with no exceptions for “semi-transactional” messages.
  3. Expose an endpoint that accepts POST over HTTPS, on a subdomain of the sending domain.
  4. Record the unsubscribe in the same transaction in which you answer with a 2xx code.
  5. Hold the queue for that address immediately, including messages already prepared for sending.
  6. Prepare a confirmation page for recipients who reach the link by hand – that is a separate path from the POST.

The visible unsubscribe link in the footer stays. The header does not replace it, because not every mail client will show a button. Two parallel entrances to the same operation, that is all.

If your recipients expect it, split the lists by topic. A global switch is simple in code, but it costs you the whole contact where opting out of one message type would have been enough. Segmentation after an unsubscribe keeps some of the addresses.

Monitor two numbers after every send: the complaint rate in the sender tools at the large providers and the number of unsubscribes. And there it is: a jump in unsubscribes with a stable complaint rate is a good signal, not a bad one.

At the MailCraft email marketing platform sending goes through our own servers, with full domain authentication and bounce handling. Openly about the roadmap: an extended preference centre with topic segmentation is something we are working on, not a feature you will see in the panel today. You will find the full scope of the platform’s capabilities in the feature description.

Summary: unsubscribing as part of sending hygiene

The List-Unsubscribe header and one-click unsubscribe are the minimum for bulk sending. Not a premium feature, not an option to consider next quarter. Easy opting out brings the number of complaints down, and a complaint weighs incomparably more in the assessment of a sender than the loss of one address from the list.

The order of work is always the same: domain authentication, a clean list based on consent, a correct endpoint, monitoring after every send. Reverse it and you get a nice header on a bad foundation.

Check your own sending now. Look at the source of your last campaign, find both headers, send a test POST to your endpoint and see whether the record disappears from the queue right away. Fifteen minutes of work that pays for itself with the first campaign that does not land in the spam folder.