I'm having a lot of problems with GMail delivery due to lack of "one-click unsubscribe" -- however that is quantified, which is not clear.
In particular, there is an issue with the fact that Google ignores dots in email addresses. So I have many (MANY!) subscribers who try to use the List-Unsubscribe header target, but because they are subscribed as "idiotsubscriber@gmail.com" rather than "idiot.subscriber@gmail.com" (which they have since changed their sender to) they get a reject that they are not subscribed. These people are also far too unobservant to read the footer of every message that reads "You are subscribed as idiotsubscriber@gmail.com".
Is there any way to provide personalized List-Unsubscribe header links, or have Mailman ignore dots in gmail.com addresses... or... anything? I'm finding reported spam percentages in the Google Postmaster Dashboard exceeding 0.1%, which causes massive delivery blocking to GMail-based subscribers.
While I would gladly ban everyone who uses gmail, that sadly accounts for about half of the Internet today and would be incredibly unproductive.
Thanks, --Jered
Jered Floyd writes:
Is there any way to provide personalized List-Unsubscribe header links,
Google should do it in their implementation -- they know which of dozens of equivalent addresses the post was sent to, and it's quite likely to be available in the header of the delivered post (and if not it's easy to add).
For Mailman, not without adding a new feature. The current approach takes the sender of the "unsubscribe" message as the address to unsubscribe. While this is not currently hard to spoof, it does cut down on mere mischief. If spoofing becomes a problem, it would be sraightforward to check for From alignment, which should make spoofing very hard, as the overwhelming majority of users use providers who DKIM sign and check the login. An URL which specifies the address to unsubscribe would need to be authenticated in a different way, requiring a different command for a MAILTO URL, or a different scheme such as HTTPS.
or have Mailman ignore dots in gmail.com addresses...
I think we already canonicalize addresses to lowercase, and I'm unaware of problems with that, as apparently essentially all providers ignore case. Theoretically we could do that, but ... catering to Google breakage?! I'll do it for money, maybe somebody else will volunteer.
If we're talking about a new feature, I think the most straightforward approach is to use RFC 8058[1] "one click" URLs. I believe it is already implemented by Gmail and Yahoo, I don't know about Outlook or the open source MUAs. This would require a substantial (but straightforward[2]) addition of code, and of course personalized delivery (I don't know if anyone balks at that any more, though).
or... anything? I'm finding reported spam percentages in the Google Postmaster Dashboard exceeding 0.1%, which causes massive delivery blocking to GMail-based subscribers.
That's obnoxious. If they can get reported spam rates down to 0,1%, almost certainly 90% of reports are subscriber malfeasance or incompetence!
While I would gladly ban everyone who uses gmail, that sadly accounts for about half of the Internet today and would be incredibly unproductive.
Aw, c'mon, be a hero! (^^) Gmail has gotten so enshittified, but it just doesn't seem to matter, does it.
Footnotes: [1] https://datatracker.ietf.org/doc/html/rfc8058
[2] That is, we'd need to add a new location in Postorius and code to accept POST access to it, encrypt/decrypt functionality to handle an opaque token (to prevent automated denial of service by folks without access to the person's email) or a table of one-time tokens with expiration (same purpose, and expiring so the database doesn't grow infinitely). What we wouldn't need to do is to change any exsting code.
Reviving this thread I started in February because delivery rates continue to decline, and I get this threat from Google any time I check their Dashboard:
"One-click Unsubscribe: Needs work — Ensure one-click unsubscribe is correctly implemented for your subscription messages One-click unsubscribe allows recipients to easily unsubscribe instead of marking your messages as spam"
Having recently implemented "Feedback-ID" (Google's proprietary-but-required Feedback Loop mechanism) at my MTA, all this has done is confirm that 0.05-0.10% of subscribers report messages as spam and would probably rather be unsubscribed but cannot be bothered to figure this out. Having the headers that make Google/Yahoo/Apple/etc ask "Would you like to unsubscribe from this?" when they hit the "Junk" button will most likely resolve the problem.
I'm pretty sure, as below, that we need to implement RFC 8058 headers in order to maintain deliverability to GMail. The only tracker issue I can find related to this is https://gitlab.com/mailman/mailman/-/issues/1099 -- is that the best place to discuss implementation?
--Jered
----- On Feb 5, 2025, at 3:36 AM, Stephen J. Turnbull turnbull@sk.tsukuba.ac.jp wrote: [..]
If we're talking about a new feature, I think the most straightforward approach is to use RFC 8058[1] "one click" URLs. I believe it is already implemented by Gmail and Yahoo, I don't know about Outlook or the open source MUAs. This would require a substantial (but straightforward[2]) addition of code, and of course personalized delivery (I don't know if anyone balks at that any more, though). [..] Footnotes: [1] https://datatracker.ietf.org/doc/html/rfc8058
[2] That is, we'd need to add a new location in Postorius and code to accept POST access to it, encrypt/decrypt functionality to handle an opaque token (to prevent automated denial of service by folks without access to the person's email) or a table of one-time tokens with expiration (same purpose, and expiring so the database doesn't grow infinitely). What we wouldn't need to do is to change any exsting code.
H Jered,
On Sat, Nov 29, 2025 at 5:14 PM Jered Floyd <jered@convivian.com> wrote:
Having the headers that make Google/Yahoo/Apple/etc ask "Would you like to unsubscribe from this?" when they hit the "Junk" button will most likely resolve the problem.
As far as I can tell, this already works this way in Gmail even without 1-click unsubscribe headers. Regular Mailman headers seem sufficient for this functionality to work.
Actually, Gmail requires RFC 8058 implementation only if you send more than 5000 emails to Gmail daily, see
https://support.google.com/a/answer/81126?sjid=10190244125288951896-EU#zippy...
Danil
Hi Danil,
I don't believe that this is the case -- at least, I don't see the "magic unsubscribe" button on Mailman3 list messages in my GMail account. GMail doesn't really have the information necessary to auto-unsubscribe from a mailman list because it's not obvious what the subscribed address is for any given list/message -- this is a problem that RFC 8058 solves, and I touch on one example of how this goes wrong up-thread (in February).
I do frequently send more than 5000 messages/day to GMail on busy lists with many subscribers. It's hard to overstate what a huge percentage of the consumer mailbox market that Google has. From my sample, they own more than 60% of subscribed addresses.
Looking a the Google Postmaster Tools I see upwards of 99% deliveries TempFailed and I have special-cased retries in my MTA to be every 5 minutes to GMail to try and get vaguely timely message deliveries. Google are always mysterious, but the only big red exclamation mark on their dashboard is lack of one-click unsubscribe.
--Jered
----- On Nov 29, 2025, at 3:07 PM, Danil Smirnov via Mailman-users mailman-users@mailman3.org wrote:
H Jered,
On Sat, Nov 29, 2025 at 5:14 PM Jered Floyd <jered@convivian.com> wrote:
Having the headers that make Google/Yahoo/Apple/etc ask "Would you like to unsubscribe from this?" when they hit the "Junk" button will most likely resolve the problem.
As far as I can tell, this already works this way in Gmail even without 1-click unsubscribe headers. Regular Mailman headers seem sufficient for this functionality to work.
Actually, Gmail requires RFC 8058 implementation only if you send more than 5000 emails to Gmail daily, see
https://support.google.com/a/answer/81126?sjid=10190244125288951896-EU#zippy...
Danil
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at: https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to jered@convivian.com
Hi Jered,
On Sun, Nov 30, 2025 at 1:25 AM Jered Floyd <jered@convivian.com> wrote:
Hi Danil,
I don't believe that this is the case -- at least, I don't see the "magic unsubscribe" button on Mailman3 list messages in my GMail account. GMail doesn't really have the information necessary to auto-unsubscribe from a mailman list because it's not obvious what the subscribed address is for any given list/message -- this is a problem that RFC 8058 solves, and I touch on one example of how this goes wrong up-thread (in February).
You piqued my curiosity, and I've run a test (since we maintain RFC 8058 implementation at Mailman3.com) to see how Gmail treats messages from a mailing list with regular Mailman headers vs. RFC 8058 headers.
As per my tests, it treats them equally indifferently - when I click the "Move to spam" button, it just moves them without any additional questions, unfortunately. Also, I don't see any smart "Unsubscribe" button in my Gmail UI.
Perhaps this is because I'm not a heavy sender on this mailing list...
On the other hand, Yahoo (I know that friends don't let friends use it) offers an unsubscribe option even without the RFC 8058 headers, and it sends a valid unsubscribe request by email to the mailing list "leave" address when you click it.
However, I'm going to extend my tests to check how Google Postmaster Tools v2 treats traffic from the particular server with and without RFC 8058 headers. Probably the former will be rendered as "healthier".
I'll share the results in this list.
Sincerely, Danil Smirnov
I do frequently send more than 5000 messages/day to GMail on busy lists
with many subscribers. It's hard to overstate what a huge percentage of the consumer mailbox market that Google has. From my sample, they own more than 60% of subscribed addresses.
Looking a the Google Postmaster Tools I see upwards of 99% deliveries TempFailed and I have special-cased retries in my MTA to be every 5 minutes to GMail to try and get vaguely timely message deliveries. Google are always mysterious, but the only big red exclamation mark on their dashboard is lack of one-click unsubscribe.
--Jered
----- On Nov 29, 2025, at 3:07 PM, Danil Smirnov via Mailman-users mailman-users@mailman3.org wrote:
H Jered,
On Sat, Nov 29, 2025 at 5:14 PM Jered Floyd <jered@convivian.com> wrote:
Having the headers that make Google/Yahoo/Apple/etc ask "Would you like to unsubscribe from this?" when they hit the "Junk" button will most likely resolve the problem.
As far as I can tell, this already works this way in Gmail even without 1-click unsubscribe headers. Regular Mailman headers seem sufficient for this functionality to work.
Actually, Gmail requires RFC 8058 implementation only if you send more than 5000 emails to Gmail daily, see
https://support.google.com/a/answer/81126?sjid=10190244125288951896-EU#zippy...
Danil
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at:
https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to jered@convivian.com
Danil,
You piqued my curiosity, and I've run a test (since we maintain RFC 8058 implementation at Mailman3.com) to see how Gmail treats messages from a mailing list with regular Mailman headers vs. RFC 8058 headers.
Are you saying I should see RFC 8058 headers on this list? (mailman-users@mailman3.org) If so, I am not...
On the other hand, Yahoo (I know that friends don't let friends use it) offers an unsubscribe option even without the RFC 8058 headers, and it sends a valid unsubscribe request by email to the mailing list "leave" address when you click it.
Yes, I've noticed Yahoo and others do some automation with the RFC 2369 ("List-Unsubscribe") headers. It looks to be like Google does require "List-Unsubscribe-Post" headers, which require List-Unsubscribe include an HTTPS (and not just a MAILTO) URI.
Regards, --Jered
Jered Floyd writes:
Reviving this thread I started in February because delivery rates continue to decline, and I get this threat from Google any time I check their Dashboard:
"One-click Unsubscribe: Needs work — Ensure one-click unsubscribe is correctly implemented for your subscription messages One-click unsubscribe allows recipients to easily unsubscribe instead of marking your messages as spam"
This is a LIE. Most Mailman lists already implement the RFC 2369 header fields, which already contain the necessary "click to unsubscribe" information. What RFC 8058 provides is a shortcut for the user that burdens the list. "Friends don't let friends use Gmail" (or Yahoo! or AOL or Hotmail or O365 or ...).
Now that I've got that off my chest ...
I'm pretty sure, as below, that we need to implement RFC 8058 headers in order to maintain deliverability to GMail.
That's easy enough. Just configure your MTA to DKIM sign that field (if Mailman is doing the signing you can configure it in mailman/config/schema.cfg), and insert before line 22 of mailman/handlers/rfc_2369.py
from base64 import base85
and change line 68 to
('List-Unsubscribe',
'<mailto:{}?{}>'.format(mlist.leave_address,
b85_encode(mlist.leave_address))),
('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click'),
Actually implementing the protocol requires a lot more effort across up to a dozen files, of course. I'm not in a hurry to do that work (I'm not a Postorius or database person, I'd have to do a fair amount of study), but I'd be happy to review merge request.
You could just treat all POSTs to that URI as one-click unsubscribes (ignore the query value), which should be enough to fool Google but risks a DOS attack on your lists.
The only tracker issue I can find related to this is https://gitlab.com/mailman/mailman/-/issues/1099 -- is that the best place to discuss implementation?
Yes. Between this message, my earlier message that you quoted, and Danil Smirnov's comment in the issue you should be much of the way to implementation.
I see in your later message that you haven't enabled personalization in Mailman. If you want to avoid the computation costs etc in Mailman, you can have MTA do it more efficiently I suspect. You'll want to have the MTA DKIM sign the List-Post-Unsubscribe field as well as the List-Unsubscribe field anyway, so you'll be fiddling that config in any case. However, that's not the main cost IMO -- it's the cost of sending each message individually when you'd like to just stuff 5000 addresses into RCPT TO and send DATA once. I suspect Google will throttle you if you try to send that many messages in one connection, so you probably will need to check that and tune your MTA.
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan
"One-click Unsubscribe: Needs work — Ensure one-click unsubscribe is correctly implemented for your subscription messages One-click unsubscribe allows recipients to easily unsubscribe instead of marking your messages as spam"
This is a LIE. Most Mailman lists already implement the RFC 2369 header fields, which already contain the necessary "click to unsubscribe" information. What RFC 8058 provides is a shortcut for the user that burdens the list.
I'm not going to defend Google's implementations and policies here, but the RFC 2369 fields are regularly insufficient. Several times a month I have people asking to unsubscribe because they don't remember what address they are subscribed as across aliases, ignored-dots, and forwarding. (Yes, I include the subscriber address in the footer of every message.) At least as many people are going to just be marking every message as spam rather than contacting the -owner address, and that hurts deliverability.
Regardless of that, the little box that says "this message is from a mailing list; would you like to unsubscribe?" that appears on my iDevice is extremely useful and a great user affordance. The purpose of list management software is to meet the needs of list administrators and list subscribers, and this definitely qualifies. RFC 8058 is a standard; there's no reason for us to be needlessly hostile to implementing it. (That's independent from prioritizing it or finding someone with the time, of course.)
I'm pretty sure, as below, that we need to implement RFC 8058 headers in order to maintain deliverability to GMail.
That's easy enough. Just configure your MTA to DKIM sign that field (if Mailman is doing the signing you can configure it in mailman/config/schema.cfg), and insert before line 22 of mailman/handlers/rfc_2369.py [..]
Are you suggesting just adding bogus RFC 8058 headers to appease GMail? That's likely to anger them more. Section 3.1 of RFC 8058 says: The URI in the List-Unsubscribe header MUST contain enough information to identify the mail recipient and the list from which the recipient is to be removed, so that the unsubscription process can complete automatically.
The leave address is not sufficient for this, and as per up-thread cannot be applied in rfc_2369.py because it is pre-personalization.
The only tracker issue I can find related to this is https://gitlab.com/mailman/mailman/-/issues/1099 -- is that the best place to discuss implementation?
Yes. [...]
OK; great. That's what I was looking for. I may have some time at the end of the year to look at this since we have winter shutdown PTO.
I see in your later message that you haven't enabled personalization in Mailman. [...]
I don't see where I've given that impression; if I did it was in error. All of my list messages have full personalization enabled. It's necessary to add the subscription address to the footer and do proper bounce tracking.
don't think there's really any case in which personalization should be disabled in the modern internet mail world, and would argue (but not very strongly) that the options to turn this off probably ought be removed from Mailman. (At the very least, personalization ought be the default.)
Regards, --Jered
Jered Floyd writes:
I'm not going to defend Google's implementations and policies here,
I'm not asking anybody to do it one way or the other, I'm just generally pissed off that mailing lists have to bear the burden of the abuse of mail protocols by large monopolistic companies, who won't impose sensible restrictions on their users (a domain with p=reject should not be sending to mailing lists).
but the RFC 2369 fields are regularly insufficient.
You're right. I misread the code to say that the List-Unsubscribe field would contain the subscribed address if the distributed post was personalized, but it doesn't. We can fix that (in the case of a personalized list), and we should fix it with RFC 8058.
I'll need to check, but I think we want to add a full configuration section on Postorius for all the List-* fields (RFCs 2369, 2919, and now 8058). Besides the options to include the fields and set their content, there should be options for "Mailman standard" mailto and http(s) URIs, as well as an option to edit the http(s) URI for folks who use something other than Postorius.
I need to go back and read RFC 8058, but I think that the address information in the RFC 8058 URI can be completely opaque. I'm not sure if that's the best approach.
Regardless of that, the little box that says "this message is from a mailing list; would you like to unsubscribe?" that appears on my iDevice is extremely useful and a great user affordance.
RFC 2369 is a standard. Every serious MUA should provide that button for every list that provides a List-Unsubscribe field, along with help for the case where the address to unsubscribe is not provided.
RFC 8058 is a standard; there's no reason for us to be needlessly hostile to implementing it. (That's independent from prioritizing it or finding someone with the time, of course.)
I haven't noticed needless hostility. It's a LOT of work to do properly, though. Among other things, RFC 8058 requires "The List-Unsubscribe header field MUST contain one HTTPS URI." We don't necessarily control the implementation of that -- Postorius is an optional component, and Mailman core does not expose an HTTP port to the Internet by design. It's going to require changing several schemas in Mailman configuration, data models, and databases.
Are you suggesting just adding bogus RFC 8058 headers to appease GMail?
No, as explained above, I thought that Mailman was already adding subscription information to the "leave" field. The risk in what I was thinking was entirely DOS attacks on the list's subscribers via an insecure 1-click implementation.
The leave address is not sufficient for this, and as per up-thread cannot be applied in rfc_2369.py because it is pre-personalization.
That doesn't matter, since it's an easy-to-implement personalization. Just go to the end of the field, backspace past the ">", and insert a query providing the address and/or RFC 8058 token.
I see in your later message that you haven't enabled personalization in Mailman. [...]
Again, this was from misreading the code. My bad, I apologize.
don't think there's really any case in which personalization should be disabled in the modern internet mail world, and would argue (but not very strongly) that the options to turn this off probably ought be removed from Mailman.
I would oppose that. There are use cases where broadcast of generic messages make sense and unsubscribe does not, such as addresses and lists provided as a condition of organization membership.
(At the very least, personalization ought be the default.)
That's plausible.
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan
I'll need to check, but I think we want to add a full configuration section on Postorius for all the List-* fields (RFCs 2369, 2919, and now 8058). Besides the options to include the fields and set their content, there should be options for "Mailman standard" mailto and http(s) URIs, as well as an option to edit the http(s) URI for folks who use something other than Postorius.
Ugh, I had not considered that RFC 8058 breaks the separation of concerns here. The mail world keeps getting messily dragged into other infrastructure (MTA-STS, anyone?) -- we can at least make this work for Postorius users. Are there many who use just Mailman-Core and not the full suite?
I need to go back and read RFC 8058, but I think that the address information in the RFC 8058 URI can be completely opaque. I'm not sure if that's the best approach.
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).
--Jered
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
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.
My understanding from up-thread is that the RFC 2369 headers are added pre-personalization.
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.
I don't think we can assume that it will be the most recent post, but it would likely be _a_ recent post. If we add a timestamp to the encrypted token I suggest there should be a pretty broad window allowed (i.e. several months).
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.)
Do you just mean a salt? Or are you suggesting adding a per-subscription nonce stored in the DB? (In which case, that could simply be the URI token...) I agree with your analysis, but this would be a very specialized attack, especially if we don't provide direct feedback on if the request was successful (which we are not required to do). I have trouble constructing a practical threat here and I think the encrypted tuple, or a plaintext tuple and truncated HMAC (like how SRS works) would be sufficient.
The real risk without a per-subscription random unique identifier would be a replay attack -- the user is unsubscribed multiple times? That feels outside of the threat model.
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.
I hadn't considered this -- I definitely like this approach because it means the same function need not be implemented twice, differently. I guess the big question is now just what the simplest content of the URI should be.
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. :-(
This has always been the risk with single-click anything. Given how common this is as a use case, I believe that the anti-spam/anti-phishing systems have stopped clicking links willy-nilly, or at least special case List-Unsubscribe URIs. I also see that inbound mail filters these days are more likely to rewrite clickable links to bounce through a redirector so the scan happens at access (rather than receipt) time -- so the link is only proxy-clicked when the user does intend to do so.
A bigger threat might be web archives that include the list headers and clickable links. The GenAI companies are absolutely _hammering_ anything they can get a hold of with spiders that ignore all robots.txt or rate limit indicators. I have to keep blocking user agents and IP ranges because I'm spending $100s/month in excess egress fees on badly-written LLM spiders. The Internet is an increasingly hostile place.
Regardless, not something we can do much about.
--Jered
Jered Floyd writes:
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.
My understanding from up-thread is that the RFC 2369 headers are added pre-personalization.
They are. It would also be trivial to personalize them; they just aren't.
If we add a timestamp to the encrypted token I suggest there should be a pretty broad window allowed (i.e. several months).
I guess it would be a matter of keeping 2 tokens in the database.
Safety would suggest adding a random nonce and that would need to be saved in the database.)
Do you just mean a salt? Or are you suggesting adding a per-subscription nonce stored in the DB? (In which case, that could simply be the URI token...)
Per-subscription and it would be the URI token.
I agree with your analysis, but this would be a very specialized attack, especially if we don't provide direct feedback on if the request was successful (which we are not required to do).
I think we do need to provide feedback, at least when the request fails due to an expired token.
I have trouble constructing a practical threat here
I don't know if there's a practical threat. I don't think the known plaintext attack on the key is practical if we use a key dedicated to this purpose. You'd need at least a large university's collection of tokens, and what could you do with it that would be worth the effort? The DOS attack is practical if encryption is expensive enough. But storing the token would make that a single database lookup.
and I think the encrypted tuple, or a plaintext tuple and truncated HMAC (like how SRS works) would be sufficient.
Checking the encrypted tuple is cheaper and simpler.
The real risk without a per-subscription random unique identifier would be a replay attack -- the user is unsubscribed multiple times? That feels outside of the threat model.
The identifier has to be unique to the subscription. If there are multiple valid unsubscriptions, the later ones won't have an existing subscription to unsubscribe. That does argue for the nonce -- that would stop the attack in the case where the user resubscribes.
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.
I hadn't considered this -- I definitely like this approach because it means the same function need not be implemented twice, differently.
OK, that's part of the design we'll start with.
guess the big question is now just what the simplest content of the URI should be.
I think there should be just an opaque token plus an optional expiration date for sites paranoid enough to have a rotation policy for the keys. We need to do some thinking about how to implement "several months validity" in case of a sudden key change. The expiration date is irrelevant to the implementation of 8058, it's just for the benefit of the user (and data collection for how old the token is, I guess).
This is shaping up pretty well, I think.
The Internet is an increasingly hostile place.
True enough.
Regardless, not something we can do much about.
There's hope. When Yahoo! and AOL broke the Internet in 2014 by setting p=reject DMARC policies, the Ministry of Education issued "administrative guidance" that *yahoo.* addresses should not be used for school business, and my university sent them all to spam. ;-) Including yahoo.jp which did not have a p=reject policy.
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan
If we add a timestamp to the encrypted token I suggest there should be a pretty broad window allowed (i.e. several months).
I guess it would be a matter of keeping 2 tokens in the database.
In the case we sign/encrypt a tuple of (list, subscriber, timestamp) we don't need to store anything in the database. We just check timestamp against our validity period and remove the subscriber for the list. This is simple, but I agree as discussed later that just having a random opaque UUID that corresponds per subscription-instance in the database provides a lot more flexibility/safety overall.
Option 1: signed/encrypted tuple (list, subscriber, timestamp) Option 2: UUID referencing a unique subscription in the database
Sounds like you are favoring the 2nd option?
I agree with your analysis, but this would be a very specialized attack, especially if we don't provide direct feedback on if the request was successful (which we are not required to do).
I think we do need to provide feedback, at least when the request fails due to an expired token.
RFC 8058 doesn't specify response codes or really any behavior in response to the POST request. The user never sees this interaction.
On the other hand, in Postorius we probably want to support a GET interaction against the same URI which provides a page with a button that generates the equivalent POST. That means that the same URI can be used in a personalized footer as a (two-click) unsubscribe link. In that case, we will want the POST to generate a response that indicates success or failure.
Incidentally, I imagine 8058 defines this as a POST interaction to avoid the mail-scanner issue we talked about last message. Mail scanners may follow links with GET requests, but are unlikely to generate POSTs.
The real risk without a per-subscription random unique identifier would be a replay attack -- the user is unsubscribed multiple times? That feels outside of the threat model.
The identifier has to be unique to the subscription. If there are multiple valid unsubscriptions, the later ones won't have an existing subscription to unsubscribe. That does argue for the nonce -- that would stop the attack in the case where the user resubscribes.
Yes, exactly -- I didn't mean multiple valid subscriptions at the same time, but rather serial subscriptions by the same subscriber (if they are maliciously unsubscribed).
Regardless, not something we can do much about.
There's hope. When Yahoo! and AOL broke the Internet in 2014 by setting p=reject DMARC policies, the Ministry of Education issued "administrative guidance" that *yahoo.* addresses should not be used for school business, and my university sent them all to spam. ;-) Including yahoo.jp which did not have a p=reject policy.
Ah, to be outside the US, where the concept of consumer protections still exists...
--Jered
Jered Floyd writes:
I guess it would be a matter of keeping 2 tokens in the database.
In the case we sign/encrypt a tuple of (list, subscriber, timestamp) we don't need to store anything in the database.
True, but I'm concerned with the computation cost of validation. That shouldn't matter ordinarily, legit unsubscribes will be rare, but it could be a vulnerability to a DOS attack.
Option 1: signed/encrypted tuple (list, subscriber, timestamp) Option 2: UUID referencing a unique subscription in the database
Sounds like you are favoring the 2nd option?
Yes, with explicit timestamp. The concerned party has knowledge of the first two. None of that is anybody else's business. Nerds like me would be pleased to be told the third component, and if expiration times are going to be "several months" as you suggested, I figure they should last as long as the signing key does.
RFC 8058 doesn't specify response codes or really any behavior in response to the POST request. The user never sees this interaction.
Probably not. It's a little surprising that they said almost nothing (except some dark mutterings about hints that the address is valid). Maybe it's not necessary. If the list wants to they can provide a goodbye message, and if it fails the subscriber will get a valid token. :-) I just think it would be kind of rude not to give a response in the case of an expired token, because the subscriber did everything right as far as they can see.
On the other hand, in Postorius we probably want to support a GET interaction against the same URI which provides a page with a button that generates the equivalent POST.
I don't think so. We can already put the list and address in the footer's unsubscribe link.[1] That would likely involve a login interaction.[2] The token alone wouldn't be sufficient credentials, because the footer is extremely likely to leak into public spaces.
Incidentally, I imagine 8058 defines this as a POST interaction to avoid the mail-scanner issue we talked about last message.
Ah, good point. I've worked with John Levine, he's that smart and definitely that WG is that smart.
Ah, to be outside the US, where the concept of consumer protections still exists...
Lina Khan lives!
Footnotes: [1] Of course this would require changing GET processing of the unsubscribe link, it doesn't work that way now. But this should be a separate feature from RFC 8058 processing.
[2] If the user has a Postorius session active, they'll be whisked on through. But most users won't.
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan
Spammers have been registering and not subscribing. I want to turn off the user self registration at https://lists.ccalternatives.org/mailman3/ .
I edited /etc/mailman3/settings.py adding ACCOUNT_ALLOW_REGISTRATION = False and restarted the services, but the ' Sign Up' option remains. I assume /etc/mailman3/settings.py is my active settings file.
What am I doing wrong?
On 12/7/25 07:46, Christian Stalberg via Mailman-users wrote:
Spammers have been registering and not subscribing. I want to turn off the user self registration at https://lists.ccalternatives.org/mailman3/ .
I edited /etc/mailman3/settings.py adding ACCOUNT_ALLOW_REGISTRATION = False and restarted the services, but the ' Sign Up' option remains. I assume /etc/mailman3/settings.py is my active settings file.
What am I doing wrong?
Web searches may find reference to a django-allauth setting ACCOUNT_ALLOW_REGISTRATION, but this setting doesn't exist in current django-allauth
The setting you want is
ACCOUNT_ADAPTER = ‘django_mailman3.views.user_adapter.DisableSignupAdapter’
See https://docs.mailman3.org/en/latest/faq.html#how-to-disable-signup or https://docs.mailman3.org/projects/mailman-web/en/latest/settings.html#mailm...
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
That worked. Thank you!
-----Original Message----- From: Mark Sapiro <mark@msapiro.net> Sent: Sunday, December 7, 2025 9:26 AM To: mailman-users@mailman3.org Subject: [MM3-users] Re: user self registration
On 12/7/25 07:46, Christian Stalberg via Mailman-users wrote:
Spammers have been registering and not subscribing. I want to turn off the user self registration at https://lists.ccalternatives.org/mailman3/ .
I edited /etc/mailman3/settings.py adding ACCOUNT_ALLOW_REGISTRATION = False and restarted the services, but the ' Sign Up' option remains. I assume /etc/mailman3/settings.py is my active settings file.
What am I doing wrong?
Web searches may find reference to a django-allauth setting ACCOUNT_ALLOW_REGISTRATION, but this setting doesn't exist in current django-allauth
The setting you want is
ACCOUNT_ADAPTER = ‘django_mailman3.views.user_adapter.DisableSignupAdapter’
See https://docs.mailman3.org/en/latest/faq.html#how-to-disable-signup or https://docs.mailman3.org/projects/mailman-web/en/latest/settings.html#mailm...
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at: https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to csa@web-analysts.net
Something strange is now going on. Now when a user tries to subscribe themself and they get the ' Please check your inbox for further instructions' no such email arrives in their mailbox.
Relatedly, if I as an admin try adding someone to a list via the Mass Subscribe, they are not added to the list, but they do appear in the listing of all Users.
Help!
-----Original Message----- From: Christian Stalberg via Mailman-users <mailman-users@mailman3.org> Sent: Monday, December 8, 2025 6:16 AM To: mailman-users@mailman3.org Cc: 'Mark Sapiro' <mark@msapiro.net> Subject: [MM3-users] Re: user self registration
That worked. Thank you!
-----Original Message----- From: Mark Sapiro <mark@msapiro.net> Sent: Sunday, December 7, 2025 9:26 AM To: mailman-users@mailman3.org Subject: [MM3-users] Re: user self registration
On 12/7/25 07:46, Christian Stalberg via Mailman-users wrote:
Spammers have been registering and not subscribing. I want to turn off the user self registration at https://lists.ccalternatives.org/mailman3/ .
I edited /etc/mailman3/settings.py adding ACCOUNT_ALLOW_REGISTRATION = False and restarted the services, but the ' Sign Up' option remains. I assume /etc/mailman3/settings.py is my active settings file.
What am I doing wrong?
Web searches may find reference to a django-allauth setting ACCOUNT_ALLOW_REGISTRATION, but this setting doesn't exist in current django-allauth
The setting you want is
ACCOUNT_ADAPTER = ‘django_mailman3.views.user_adapter.DisableSignupAdapter’
See https://docs.mailman3.org/en/latest/faq.html#how-to-disable-signup or https://docs.mailman3.org/projects/mailman-web/en/latest/settings.html#mailm...
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at: https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to csa@web-analysts.net
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at: https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to csa@web-analysts.net
Christian Stalberg via Mailman-users writes:
Something strange is now going on. Now when a user tries to subscribe themself and they get the ' Please check your inbox for further instructions' no such email arrives in their mailbox.
Please check your mail server and Mailman logs to see whether mail is being sent. The most relevant Mailman log is smtp.log (or possibly virgin.log, but almost nobody uses the latter any more). Also check that all the runners are running.
Relatedly, if I as an admin try adding someone to a list via the Mass Subscribe, they are not added to the list, but they do appear in the listing of all Users.
I don't see how the setting ACCOUNT_ADAPTER = ‘django_mailman3.views.user_adapter.DisableSignupAdapter’ could have either of the effects above. It effectively sets a flag that is used internally by Django, but nowhere in the mailmanweb code. That is all it does. But once Django hands off the subscription request to the Postorius code, Django is no longer involved. So I am quite sure that the ACCOUNT_ADAPTER change did not cause either issue.
I seem to recall that you have tried a number of things to disable the sign-in. Please review all changes made in the last couple of months to mailman.cfg, settings.py, and your mail server to see if any of those have been left in place, or whether apparently unrelated changes were made. Also, are you sure these problems started immediately after making the change to ACCOUNT_ADAPTER? If you can determine when these issues started accurately, it may help in localizing the issue to a particular change or set of changes.
-- GNU Mailman consultant (installation, migration, customization) Sirius Open Source https://www.siriusopensource.com/ Software systems consulting in Europe, North America, and Japan
On 2/4/25 20:24, Jered Floyd wrote:
I'm having a lot of problems with GMail delivery due to lack of "one-click unsubscribe" -- however that is quantified, which is not clear.
See the footer of this message which contains
To unsubscribe send an email to mailman-users-leave@mailman3.org
This is produced by
To unsubscribe send an email to ${short_listname}-leave@${domain}
in the template which is also in the default template. This seems sufficient for Google, as I don't see mail bounced for this reason.
You might try adding a link to Postorius. You can't really link to an immediate unsubscribe as that requires the user be logged in (and the user may not even have an account) and it also required POST data, but for Mailman >= 3.3.10, you could add
To unsubscribe send an email to ${short_listname}-leave@${domain} or go to $mailinglist_url
This requires the domain have a base_url set. See <https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/rest/docs/d...> and this is not yet exposed in Postorius. See https://gitlab.com/mailman/postorius/-/issues/594
In particular, there is an issue with the fact that Google ignores dots in email addresses. So I have many (MANY!) subscribers who try to use the List-Unsubscribe header target, but because they are subscribed as "idiotsubscriber@gmail.com" rather than "idiot.subscriber@gmail.com" (which they have since changed their sender to) they get a reject that they are not subscribed. These people are also far too unobservant to read the footer of every message that reads "You are subscribed as idiotsubscriber@gmail.com".
Is there any way to provide personalized List-Unsubscribe header links, or have Mailman ignore dots in gmail.com addresses... or... anything? I'm finding reported spam percentages in the Google Postmaster Dashboard exceeding 0.1%, which causes massive delivery blocking to GMail-based subscribers.
The List-Unsubscribe: header is added in the handler pipeline by mailman/handlers/rfc_2369.py. At his point in the process the message is still generic so the header can't be personalized. The mailman/handlers/decorate.py handler can add personalized content so could modify the List-Unsubscribe: header to add the recipient's email address except at least at present this won't work because emails to listname-leave or listname-request with a leave or unsubscribe command currently only look at the sender of the email for the address to unsubscribe.
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
On 2/4/25 20:24, Jered Floyd wrote:
I'm having a lot of problems with GMail delivery due to lack of "one-click unsubscribe" -- however that is quantified, which is not clear.
One other thing. Gmail in its, to paraphrase Steve, "enshittifiedness"
while publishing a DMARC policy of none, treats mail From: gmail.com as
though the DMARC policy is reject. This means you need to add
^.*@gmail\.com$ to your list's setting for DMARC Addresses (requires
Postorius >= 1.3.9).
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
As normal civilians go, I know a lot about email. As mailman admins go, I know very little.
I manage a set of < 10 small email lists, mostly used by residents in an over-55 community. The biggest list has about 150 subscribers. Many of whom use gmail.
Anything I can do to drive up the reliability of such email will be greatly appreciated. In particular, I think it would help to implement "one-click unsubscribe". Is that something mailman3 will be doing?
Thanks!
On Tue, Feb 4, 2025 at 11:24 PM Jered Floyd <jered@convivian.com> wrote:
I'm having a lot of problems with GMail delivery due to lack of "one-click unsubscribe" -- however that is quantified, which is not clear.
In particular, there is an issue with the fact that Google ignores dots in email addresses. So I have many (MANY!) subscribers who try to use the List-Unsubscribe header target, but because they are subscribed as " idiotsubscriber@gmail.com" rather than "idiot.subscriber@gmail.com" (which they have since changed their sender to) they get a reject that they are not subscribed. These people are also far too unobservant to read the footer of every message that reads "You are subscribed as idiotsubscriber@gmail.com".
Is there any way to provide personalized List-Unsubscribe header links, or have Mailman ignore dots in gmail.com addresses... or... anything? I'm finding reported spam percentages in the Google Postmaster Dashboard exceeding 0.1%, which causes massive delivery blocking to GMail-based subscribers.
While I would gladly ban everyone who uses gmail, that sadly accounts for about half of the Internet today and would be incredibly unproductive.
Thanks, --Jered
Mailman-users mailing list -- mailman-users@mailman3.org To unsubscribe send an email to mailman-users-leave@mailman3.org https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/ Archived at: https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/...
This message sent to swd@pobox.com
participants (7)
-
Christian Stalberg -
Danil Smirnov -
Jered Floyd -
Mark Sapiro -
Stephen Daniel -
Stephen J. Turnbull -
Stephen J. Turnbull