diff options
Diffstat (limited to 'Mailman')
-rw-r--r-- | Mailman/Cgi/subscribe.py | 3 | ||||
-rw-r--r-- | Mailman/Commands/cmd_subscribe.py | 4 | ||||
-rwxr-xr-x | Mailman/Defaults.py.in | 8 | ||||
-rw-r--r-- | Mailman/Errors.py | 1 | ||||
-rw-r--r-- | Mailman/MailList.py | 21 |
5 files changed, 37 insertions, 0 deletions
diff --git a/Mailman/Cgi/subscribe.py b/Mailman/Cgi/subscribe.py index ce7940f9..795fc81b 100644 --- a/Mailman/Cgi/subscribe.py +++ b/Mailman/Cgi/subscribe.py @@ -291,6 +291,9 @@ your subscription.""") Your subscription request was deferred because %(x)s. Your request has been forwarded to the list moderator. You will receive email informing you of the moderator's decision when they get to your request.""") + except Errors.MMAlreadyPending: + # User already has a subscription pending + results = _('You already have a subscription pending confirmation') except Errors.MMAlreadyAMember: # Results string depends on whether we have private rosters or not if not privacy_results: diff --git a/Mailman/Commands/cmd_subscribe.py b/Mailman/Commands/cmd_subscribe.py index abe8b762..098740c8 100644 --- a/Mailman/Commands/cmd_subscribe.py +++ b/Mailman/Commands/cmd_subscribe.py @@ -128,6 +128,10 @@ the email address you gave is insecure.""")) except Errors.MMAlreadyAMember: res.results.append(_('You are already subscribed!')) return STOP + except Errors.MMAlreadyPending: + res.results.append( + _('You already have a subscription pending confirmation')) + return STOP except Errors.MMCantDigestError: res.results.append( _('No one can subscribe to the digest of this list!')) diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index b45abf7b..277e3ab0 100755 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -1122,6 +1122,14 @@ ANONYMOUS_LIST_KEEP_HEADERS = ['^(?!x-)', '^x-mailman-', '^x-ack:', '^x-beenthere:', '^x-list-administrivia:', '^x-spam-', ] +# +# It is possible to mailbomb a third party by repeatrdly posting the subscribe +# form. You can prevent this by setting the following to Yes which will refuse +# 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. +REFUSE_SECOND_PENDING = No diff --git a/Mailman/Errors.py b/Mailman/Errors.py index f4895248..b502ffbf 100644 --- a/Mailman/Errors.py +++ b/Mailman/Errors.py @@ -31,6 +31,7 @@ class BadListNameError(MMListError): pass class MMMemberError(Exception): pass class MMBadUserError(MMMemberError): pass class MMAlreadyAMember(MMMemberError): pass +class MMAlreadyPending(MMMemberError): pass # "New" style membership exceptions (new w/ MM2.1) class MemberError(Exception): pass diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 12d75aff..9e6bbcb6 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -833,6 +833,25 @@ 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 + this email. + """ + if not mm_cfg.REFUSE_SECOND_PENDING: + return False + pends = self._Pending__load() + # Save and reload the db to evict expired pendings. + self._Pending__save(pends) + pends = self._Pending__load() + for k, v in pends.items(): + if k in ('evictions', 'version'): + continue + op, data = v + if (op == Pending.SUBSCRIPTION and + data.address.lower() == email.lower()): + return True + return False + def InviteNewMember(self, userdesc, text=''): """Invite a new member to the list. @@ -919,6 +938,8 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, Utils.ValidateEmail(email) if self.isMember(email): raise Errors.MMAlreadyAMember, email + if self.CheckPending(email): + raise Errors.MMAlreadyPending, email if email.lower() == self.GetListEmail().lower(): # Trying to subscribe the list to itself! raise Errors.MMBadEmailError |