RFC 8058

Signaling One-Click Functionality for List Email Headers

πŸ“… published January 2017, from ietf

RFC 8058: Signaling One-Click Functionality for List Email Headers πŸ’Œ

okay bestie, let's talk about RFC 8058 πŸ¦‹ it's a Standards Track document from January 2017 (ISSN 2070-1721), written by J. Levine of Taughannock Networks and T. Herkula of optivo GmbH. it's literally the spec that lets mail senders say "hey, this unsubscribe link is one-click, no confirmation page needed" πŸ–±οΈβœ¨ the header block doesn't list anything it obsoletes, and it updates nothing either, except that section 3.1 says it doesn't change [RFC2369] 🫢 so everything about list unsubscribes that isn't one-click stays exactly the same πŸ’…

Abstract ✨

this doc describes a way to signal the one-click function for the List-Unsubscribe email header field πŸ’– we need it because mail software sometimes fetches URLs sitting in mail headers, and that can accidentally trigger unsubscriptions 😭 like, the mail app was just being nosy and suddenly you're off the list πŸ’€

Status of This Memo 🌸

this is an Internet Standards Track document πŸŽ€

it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community 🫢 it got public review and was approved for publication by the Internet Engineering Steering Group (IESG) πŸ‘‘ for more on Internet Standards, check Section 2 of RFC 7841 ✨

info about the current status, any errata, and how to send feedback lives at http://www.rfc-editor.org/info/rfc8058 πŸ”—

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ’œ

this document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as in effect on the publication date πŸ“œ please actually read those, because they spell out your rights and restrictions πŸ™ˆ and if you pull code components out of this document, they must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Simplified BSD License πŸ“

Table of Contents πŸ—‚οΈ

1.  Introduction and Motivation . . . . . . . . . . . . . . . . .   2
2.  Definitions . . . . . . . . . . . . . . . . . . . . . . . . .   3
3.  Implementation  . . . . . . . . . . . . . . . . . . . . . . .   4
  3.1.  Mail Senders  . . . . . . . . . . . . . . . . . . . . . .   4
  3.2.  Mail Receivers  . . . . . . . . . . . . . . . . . . . . .   5
4.  Additional Requirements . . . . . . . . . . . . . . . . . . .   5
5.  Header Syntax . . . . . . . . . . . . . . . . . . . . . . . .   5
6.  Security Considerations . . . . . . . . . . . . . . . . . . .   5
7.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .   6
8.  Examples  . . . . . . . . . . . . . . . . . . . . . . . . . .   7
  8.1.  Simple  . . . . . . . . . . . . . . . . . . . . . . . . .   7
  8.2.  Complex . . . . . . . . . . . . . . . . . . . . . . . . .   7
  8.3.  Complex with 'multipart/form-data'  . . . . . . . . . . .   7
9.  Normative References  . . . . . . . . . . . . . . . . . . . .   8
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .   8

1. Introduction and Motivation πŸ’…

okay so a List-Unsubscribe email header field [RFC2369] can hold HTTPS [RFC7230] URIs 🌈 the HTTPS URI in that header is meant to unsubscribe the recipient from the list πŸ“¬ but here's the drama: anti-spam software often fetches every resource in mail headers automatically, with zero user action 😭 and a sender has no mechanical way to tell whether a request came from anti-spam software or a real human clicking πŸ™ˆ

so senders started returning landing pages with a confirmation step to finish the unsubscribe πŸ’… a live user sees that step and clicks it, but an automated system just... doesn't πŸ’€ which makes unsubscribing way more complicated than one click, and nobody wants that πŸ₯²

broadcast marketing list operators care a LOT about deliverability ✨ like, will the mail reach people, and will it land in the primary inbox or the junk folder πŸ“₯ lots of mail systems let recipients report spam or junk, and senders whose mail gets reported as junk tend to have rough deliverability πŸ’€ so mailers really want unsubscribing to be as easy as possible πŸŽ€ because if it's too hard, the recipient's backup plan is to report the mail as junk until it stops showing up in their inbox 😡

recipient mail system operators know their users don't clearly separate "unsubscribe" from "junk" 🫠 some of them let trusted mailers ask to be notified when mail is reported as junk, so they can unsubscribe that person πŸ’œ but figuring out who's trustworthy and notifying them doesn't scale to tons of small mailers 😩 this spec gives recipient systems a way to notify the mailer automatically, using only info inside the mail message, with no prearrangement needed πŸ¦‹ some recipient systems might send an unsubscription notice whenever a user reports a message as junk, or they might offer the user a choice of reporting and unsubscribing together 🌸

when a recipient manually unsubscribes and the process needs confirmation, the web page shows up and they click the right button πŸ–±οΈ but when the unsubscribe is bundled with a junk report, there's zero direct interaction with the mailer's site 😳 same deal if a mail system auto-unsubscribes mailboxes that were closed or abandoned, because nobody's there to interact πŸͺ¦ so in those cases the unsubscribe has to work without manual intervention, and software shouldn't have to interpret a confirmation page at all 🧠

this doc handles that piece of the problem with an HTTPS POST action for mail receivers πŸŽ€ mail senders can tell this action apart from other unsubscribe requests and treat it as a one-click unsubscription, no manual step from the recipient needed ✨

this document has two goals:

  • Allow email senders to signal that a List-Unsubscribe header field [RFC2369] has one-click functionality. πŸ’–
  • Allow MUA (Mail User Agent) users to unsubscribe from mailing lists in a familiar environment and without leaving the MUA context. A receiving system can process an unsubscription request in the background without further interaction and know that it can be fully processed by the mail sender's system. 🧚

2. Definitions πŸ“–

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] when written in all capital letters. 🫢 these are the official BCP 14 power words, so when you see them in caps, they're doing real work πŸ‘‘

3. Implementation ✨

3.1. Mail Senders πŸ’Œ

a mail sender that wants one-click unsubscriptions puts one List-Unsubscribe header field and one List-Unsubscribe-Post header field in the message πŸŽ€ the List-Unsubscribe header field MUST contain one HTTPS URI πŸ”— it MAY also contain other non-HTTP/S URIs, like MAILTO: 🌈 and the List-Unsubscribe-Post header MUST contain the single key/value pair List-Unsubscribe=One-Click πŸ’… as described below, the message MUST have a valid DomainKeys Identified Mail (DKIM) signature that covers at least the List-Unsubscribe and List-Unsubscribe-Post headers πŸ” no skipping that part, bestie πŸ™…β€β™€οΈ

the URI in the List-Unsubscribe header MUST contain enough info to identify the mail recipient and the list they're being removed from, so the unsubscribe can finish automatically πŸ€– there's no provision for extra POST arguments, so any info about the message or recipient gets encoded right in the URI 🧩 which means one-click has no way to ask the user what address or which list they want to leave 🫠

the POST request MUST NOT include cookies, HTTP authorization, or any other context information πŸ™…β€β™€οΈ the unsubscribe is logically unrelated to any earlier web activity, and context info could improperly link the unsubscribe to that activity πŸ•΅οΈβ€β™€οΈ

the URI SHOULD include an opaque identifier or another hard-to-forge component, either in addition to or instead of the plaintext names of the list and subscriber πŸ”’ and the server handling the unsubscription SHOULD verify that the opaque or hard-to-forge component is valid πŸ›‘οΈ this helps stop attacks where a bad actor sends spam with List-Unsubscribe links for a victim list, hoping users who report the spam will accidentally unsubscribe that list, or where the attacker POSTs directly to the mail sender's unsubscription server 😀

the mail sender needs to provide the infrastructure to handle POST requests to the URI in the List-Unsubscribe header, and to handle the unsubscribe requests its mail will provoke πŸ—οΈ

the mail sender MUST NOT return an HTTPS redirect 🚫 redirected POST actions have historically not worked reliably, and lots of browsers have turned redirected HTTP POSTs into GETs 😭

this document does not update [RFC2369], so List-Unsubscribe URIs used for anything other than one-click stay exactly the same πŸ’–

3.2. Mail Receivers πŸ“₯

a mail receiver can do a one-click unsubscription by sending an HTTPS POST to the HTTPS URI in the List-Unsubscribe header πŸš€ it sends the key/value pair from the List-Unsubscribe-Post header as the request body 🎁

the POST content SHOULD be sent as 'multipart/form-data' [RFC7578] or MAY be sent as 'application/x-www-form-urlencoded' 🧁 these are the encodings web browsers use when they send forms 🌸 the target of the POST action is the same as the one in the GET action for a manual unsubscription, so the same server code can handle both πŸ‘―β€β™€οΈ

the mail receiver MUST NOT perform a POST on the HTTPS URI without user consent πŸ™‹β€β™€οΈ when and how that consent gets obtained is not part of this specification πŸ€·β€β™€οΈ

4. Additional Requirements πŸ”

the message needs at least one valid authentication identifier πŸͺͺ in this version of the spec, the only supported identifier type is DKIM [RFC6376], so senders MUST apply at least one valid DKIM signature to the message πŸ”

the List-Unsubscribe and List-Unsubscribe-Post headers MUST be covered by the signature and included in the "h=" tag of a valid DKIM-Signature header field 🧾

if the message doesn't have the required DKIM signature, the mail receiver SHOULD NOT offer a one-click unsubscribe for that message πŸ™…β€β™€οΈ no signature, no one-click, periodt πŸ’€

5. Header Syntax 🧩

the following ABNF imports fields, WSP, and CRLF from [RFC5322] πŸŽ€

fields =/ list-unsubscribe-post

list-unsubscribe-post = "List-Unsubscribe-Post:" 0*1WSP postarg CRLF

postarg = "List-Unsubscribe=One-Click"

6. Security Considerations πŸ”

okay bestie, the List-Unsubscribe header can hold a plaintext or encoded version of the recipient address πŸ“¬, but that address is usually sitting right there in the To: header too πŸ‘€. This spec lets anyone with access to a message unsubscribe the recipient of it. ngl that's kinda how regular List-Unsubscribe already works, it's just with more steps πŸ™„

A sneaky mailer could send spam with content designed to make people hit unsubscribe a bunch 😈 and headers crafted to send POST requests to servers that maybe don't want them. but GET requests could already be provoked in a similar way for ages (and way easier, thanks to spam filter auto-fetches πŸ€–), so the chances of a significant jump in annoyance seem low πŸ’… The content of the List-Unsubscribe-Post header is limited to a single known key/value pair πŸ”’. That's on purpose, so an attacker can't build a message where the POST would act like someone filling in an arbitrary form on a victim's website. not on my watch πŸ™…β€β™€οΈ

The unsubscribe operation gives the mailer a strong hint that the address the message was sent to is valid πŸ‘€, and in principle someone could use that to test whether an email address is real. in practice though, there are simpler ways, like embedding image links in the HTML of a message and seeing whether the recipient fetches the images πŸ–ΌοΈ

Since the mailer's server receiving the POST request generally can't tell where the request is coming from 🫣, the URI SHOULD contain an opaque identifier or another hard-to-forge component to identify the list and recipient address. that's what makes sure the request came from the List-Unsubscribe and List-Unsubscribe-Post headers in a message the mailer actually sent πŸ¦‹ Also, the request MUST NOT include cookies or other context information, so the server can't link it to previous web requests πŸͺ🚫


7. IANA Considerations 🌸

IANA has added a new entry to the "Permanent Message Header Field Names" registry ✨ The entry looks like this:

Header field name: List-Unsubscribe-Post

Applicable protocol: mail

Status: standard

Author/Change controller: IETF

Specification document: RFC 8058

8. Examples πŸŽ€

8.1. Simple

Header in Email

List-Unsubscribe: <https://example.com/unsubscribe/opaquepart>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Resulting POST request

POST /unsubscribe/opaquepart HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 26

List-Unsubscribe=One-Click

8.2. Complex

Header in Email

List-Unsubscribe:
    <mailto:listrequest@example.com?subject=unsubscribe>,
    <https://example.com/unsubscribe.html?opaque=123456789>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Resulting POST request

POST /unsubscribe.html?opaque=123456789 HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 26

List-Unsubscribe=One-Click

8.3. Complex with 'multipart/form-data'

Header in Email

List-Unsubscribe:
    <mailto:listrequest@example.com?subject=unsubscribe>,
    <https://example.com/unsubscribe.html/opaque123456789>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Resulting POST request

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--

9. Normative References πŸ“š


Authors' Addresses πŸ’Œ

John Levine
Taughannock Networks
PO Box 727
Trumansburg, NY  14886
United States of America

Phone: +1 831 480 2300
Email: standards@taugh.com
URI:   http://jl.ly


Tobias Herkula
optivo GmbH
Wallstrasse 16
Berlin  10179
Germany

Phone: +49 30 768078 129
Email: t.herkula@optivo.com
URI:   https://www.optivo.com

That's the whole spec, bestie 🌈✨ we did it 😭🫢

πŸ“¦ where this page comes from