1# Copyright (C) 1998-2018 by the Free Software Foundation, Inc. 2# 3# This program is free software; you can redistribute it and/or 4# modify it under the terms of the GNU General Public License 5# as published by the Free Software Foundation; either version 2 6# of the License, or (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software 15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 16# USA. 17 18 19"""Shared mailman errors and messages.""" 20 21 22# exceptions for problems related to opening a list 23class MMListError(Exception): pass 24class MMUnknownListError(MMListError): pass 25class MMCorruptListDatabaseError(MMListError): pass 26class MMListNotReadyError(MMListError): pass 27class MMListAlreadyExistsError(MMListError): pass 28class BadListNameError(MMListError): pass 29 30# Membership exceptions 31class MMMemberError(Exception): pass 32class MMBadUserError(MMMemberError): pass 33class MMAlreadyAMember(MMMemberError): pass 34class MMAlreadyPending(MMMemberError): pass 35 36# "New" style membership exceptions (new w/ MM2.1) 37class MemberError(Exception): pass 38class NotAMemberError(MemberError): pass 39class AlreadyReceivingDigests(MemberError): pass 40class AlreadyReceivingRegularDeliveries(MemberError): pass 41class CantDigestError(MemberError): pass 42class MustDigestError(MemberError): pass 43class MembershipIsBanned(MemberError): pass 44 45# Exception hierarchy for various authentication failures, can be 46# raised from functions in SecurityManager.py 47class MMAuthenticationError(Exception): pass 48class MMBadPasswordError(MMAuthenticationError): pass 49class MMPasswordsMustMatch(MMAuthenticationError): pass 50class MMCookieError(MMAuthenticationError): pass 51class MMExpiredCookieError(MMCookieError): pass 52class MMInvalidCookieError(MMCookieError): pass 53 54class MMMustDigestError: pass 55class MMCantDigestError: pass 56class MMNeedApproval: 57 def __init__(self, message=None): 58 self.message = message 59 def __str__(self): 60 return self.message or '' 61class MMSubscribeNeedsConfirmation: pass 62class MMBadConfirmation: 63 def __init__(self, message=None): 64 self.message = message 65 def __str__(self): 66 return self.message or '' 67class MMAlreadyDigested: pass 68class MMAlreadyUndigested: pass 69 70MODERATED_LIST_MSG = "Moderated list" 71IMPLICIT_DEST_MSG = "Implicit destination" 72SUSPICIOUS_HEADER_MSG = "Suspicious header" 73FORBIDDEN_SENDER_MSG = "Forbidden sender" 74 75 76 77# New style class based exceptions. All the above errors should eventually be 78# converted. 79 80class MailmanError(Exception): 81 """Base class for all Mailman exceptions.""" 82 pass 83 84 85class MMLoopingPost(MailmanError): 86 """Post already went through this list!""" 87 pass 88 89 90# Exception hierarchy for bad email address errors that can be raised from 91# Utils.ValidateEmail() 92class EmailAddressError(MailmanError): 93 """Base class for email address validation errors.""" 94 pass 95 96class MMBadEmailError(EmailAddressError): 97 """Email address is invalid (empty string or not fully qualified).""" 98 pass 99 100class MMHostileAddress(EmailAddressError): 101 """Email address has potentially hostile characters in it.""" 102 pass 103 104 105# Exceptions for admin request database 106class LostHeldMessage(MailmanError): 107 """Held message was lost.""" 108 pass 109 110 111 112def _(s): 113 return s 114 115# Exceptions for the Handler subsystem 116class HandlerError(MailmanError): 117 """Base class for all handler errors.""" 118 119class HoldMessage(HandlerError): 120 """Base class for all message-being-held short circuits.""" 121 122 # funky spelling is necessary to break import loops 123 reason = _('For some unknown reason') 124 125 def reason_notice(self): 126 return self.reason 127 128 # funky spelling is necessary to break import loops 129 rejection = _('Your message was rejected') 130 131 def rejection_notice(self, mlist): 132 return self.rejection 133 134class DiscardMessage(HandlerError): 135 """The message can be discarded with no further action""" 136 137class SomeRecipientsFailed(HandlerError): 138 """Delivery to some or all recipients failed""" 139 def __init__(self, tempfailures, permfailures): 140 HandlerError.__init__(self) 141 self.tempfailures = tempfailures 142 self.permfailures = permfailures 143 144# multiple inheritance for backwards compatibility 145class LoopError(DiscardMessage, MMLoopingPost): 146 """We've seen this message before""" 147 148class RejectMessage(HandlerError): 149 """The message will be bounced back to the sender""" 150 def __init__(self, notice=None): 151 if notice is None: 152 notice = _('Your message was rejected') 153 if notice.endswith('\n\n'): 154 pass 155 elif notice.endswith('\n'): 156 notice += '\n' 157 else: 158 notice += '\n\n' 159 self.__notice = notice 160 161 def notice(self): 162 return self.__notice 163 164 165# Additional exceptions 166class HostileSubscriptionError(MailmanError): 167 """A cross-subscription attempt was made.""" 168 # This exception gets raised when an invitee attempts to use the 169 # invitation to cross-subscribe to some other mailing list. 170