Jered Floyd writes:
Ugh, I had not considered that RFC 8058 breaks the separation of concerns here.
Not your job, but it is ours. :-)
we can at least make this work for Postorius users.
Definitely, that's a reasonable first step. We just need to make sure to do that while allowing others to opt out until they've implemented it themselves. I think I have a suggestion how it could just work for everybody, though.
Are there many who use just Mailman-Core and not the full suite?
I don't know about absolute numbers, but yeah, it's a FAQ. There's the EMWD Affinity application which replaces Postorius for many of the sites they host, and enterprises often ask how to use bespoke scripts to control lists (although they may be using Postorius as well).
The URI path/query is defined as opaque. It probably should be something like list-name/subscribed-address plus a signed hash to avoid unsub-attacks. That means this likely will be a new web application endpoint (although it may be possible to overload the existing "unsubscribe" endpoint -- I haven't looked at the code yet).
RFC 8058 says
The URI SHOULD include an opaque identifier or another hard-to-forge component in addition to, or instead of, the plaintext names of the list and the subscriber. The server handling the unsubscription SHOULD verify that the opaque or hard-to-forge component is valid.
We don't need to have an explicit reference to the subscription in the URI. As I discovered (to my chagrin) Mailman's current simple RFC 2369 List-Unsubscribe field doesn't, even for personalized lists where there might be a personalized link in the footer. So I think we should go with "instead of". Maybe while experimenting it would be useful to have the plain text subscription information in the URI, though.
So ... the existing REST endpoint in core won't change, because the whole REST API assumes that it's talking to the superuser. The "obvious" way to do this is through Postorius, which provides a proxy object backed by a map in Mailman core from tokens in the URL to subscriptions, and use the existing REST endpoint. This is "obvious" because Django already provides an authorization framework for subscription management -- we wouldn't be exposing anything else protected by that framework to mischief. The token would be the encrypted (list, address) pair, possibly dated in clear (to allow expiration of tokens and rotation of encryption keys). Unfortunately RFC 8058 doesn't discuss that, I guess John assumed that people would usually be unsubscribing from the most recent post. On the assumption that unsubscribes would be "rare", you wouldn't have to store the token in the database. (Have to think about that, you might be able to DOS attack by sending lots of fake unsubscribes and attack the encryption with known plaintext attacks. Safety would suggest adding a random nonce and that would need to be saved in the database.)
Alternatively, you could reverse proxy this directly through the front-end webserver to Mailman core with a new REST endpoint. That gives me bad vibes because I can just see naive admins messing up the configuration of the single endpoint, and "fixing" the problem by reverse proxying port 8001 to the Internet. We'd have to be careful that the urlconf not slop over to anything else, maybe something like "listen" on the Internet at (nginx notation):
location /mailman3/rfc8058/ {
proxy_pass http://localhost:8001/3.2/PROXIED/rfc8058;
}
The "PROXIED" part is just to provide a REST namespace that is obviously separate from the domains, addresses, users, lists, etc. Maybe "SELF_AUTHORIZING" would be more accurate. I think that reverse proxy sepcification would be safe enough.
And you could combine the two strategies which would allow sites that don't use Postorius to configure the reverse proxy, while sites that do would get it for "free" since we'd configure Postorius to do it.
Aside: RFC 8058 says
But anti-spam software often fetches all resources in mail header fields automatically, without any action by the user, and there is no mechanical way for a sender to tell whether a request was made automatically by anti-spam software or manually requested by a user.
Weirdly, the RFC doesn't address this problem at all. :-(
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan