From 248ca38ffb4821a131460c9953aa21d6fe7cec04 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Mon, 18 May 2020 10:01:51 -0700 Subject: Extend REFUSE_SECOND_PENDING to unsubscription as well. --- Mailman/Cgi/options.py | 3 +++ Mailman/Commands/cmd_unsubscribe.py | 11 ++++++++--- Mailman/Defaults.py.in | 2 +- Mailman/MailList.py | 13 +++++++++---- 4 files changed, 21 insertions(+), 8 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Cgi/options.py b/Mailman/Cgi/options.py index ee2293e2..1037f8f9 100644 --- a/Mailman/Cgi/options.py +++ b/Mailman/Cgi/options.py @@ -206,6 +206,7 @@ def main(): # Are we processing an unsubscription request from the login screen? msgc = _('If you are a list member, a confirmation email has been sent.') + msgb = _('You already have a subscription pending confirmation') msga = _("""If you are a list member, your unsubscription request has been forwarded to the list administrator for approval.""") if cgidata.has_key('login-unsub'): @@ -228,6 +229,8 @@ def main(): mlist.ConfirmUnsubscription(user, userlang, remote=ip) doc.addError(msgc, tag='') mlist.Save() + except Errors.MMAlreadyPending: + doc.addError(msgb) finally: mlist.Unlock() else: diff --git a/Mailman/Commands/cmd_unsubscribe.py b/Mailman/Commands/cmd_unsubscribe.py index 9ffa80cd..3a156536 100644 --- a/Mailman/Commands/cmd_unsubscribe.py +++ b/Mailman/Commands/cmd_unsubscribe.py @@ -73,9 +73,14 @@ approval.""")) # No password was given, so we need to do a mailback confirmation # instead of unsubscribing them here. cpaddr = mlist.getMemberCPAddress(address) - mlist.ConfirmUnsubscription(cpaddr) - # We don't also need to send a confirmation to this command - res.respond = 0 + try: + mlist.ConfirmUnsubscription(cpaddr) + except Errors.MMAlreadyPending: + res.results.append( + _('You already have a subscription pending confirmation')) + else: + # We don't also need to send a confirmation to this command + res.respond = 0 else: # No admin approval is necessary, so we can just delete them if the # passwords match. diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index 277e3ab0..e5d8b3cf 100755 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -1128,7 +1128,7 @@ ANONYMOUS_LIST_KEEP_HEADERS = ['^(?!x-)', '^x-mailman-', # pending a subscription confirmation when one is already pending. The down # side to this is if a subscriber loses or doesn't receive the confirmation # request email, she has to wait PENDING_REQUEST_LIFE (default 3 days) before -# she can request another. +# she can request another. This setting also applies to repeated unsubscribes. REFUSE_SECOND_PENDING = No diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 01a5a915..fdd47ae1 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -833,8 +833,8 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, # # Membership management front-ends and assertion checks # - def CheckPending(self, email): - """Check if there is already an unexpired pending subscription for + def CheckPending(self, email, unsub=False): + """Check if there is already an unexpired pending (un)subscription for this email. """ if not mm_cfg.REFUSE_SECOND_PENDING: @@ -846,8 +846,11 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, for k, v in pends.items(): if k in ('evictions', 'version'): continue - if (v[0] == Pending.SUBSCRIPTION and - v[1].address.lower() == email.lower()): + op, data = v[:2] + if (op == Pending.SUBSCRIPTION and not unsub and + data.address.lower() == email.lower() or + op == Pending.UNSUBSCRIPTION and unsub and + data.lower() == email.lower()): return True return False @@ -1476,6 +1479,8 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, assert 0, 'Bad op: %s' % op def ConfirmUnsubscription(self, addr, lang=None, remote=None): + if self.CheckPending(addr, unsub=True): + raise Errors.MMAlreadyPending, email if lang is None: lang = self.getMemberLanguage(addr) cookie = self.pend_new(Pending.UNSUBSCRIPTION, addr) -- cgit v1.2.3