diff options
| author | bwarsaw | 2002-05-02 03:06:58 +0000 |
|---|---|---|
| committer | bwarsaw | 2002-05-02 03:06:58 +0000 |
| commit | 7aab76e13f92357a3b1b789da1d07eb42e8414db (patch) | |
| tree | dfb9664aa8a3ccca0fa01527917b622e6609e869 /Mailman/MailCommandHandler.py | |
| parent | 9c40b0b3bfddfc76a825a5c7262c52ba18271bd5 (diff) | |
| download | mailman-7aab76e13f92357a3b1b789da1d07eb42e8414db.tar.gz mailman-7aab76e13f92357a3b1b789da1d07eb42e8414db.tar.zst mailman-7aab76e13f92357a3b1b789da1d07eb42e8414db.zip | |
Diffstat (limited to 'Mailman/MailCommandHandler.py')
| -rw-r--r-- | Mailman/MailCommandHandler.py | 783 |
1 files changed, 0 insertions, 783 deletions
diff --git a/Mailman/MailCommandHandler.py b/Mailman/MailCommandHandler.py deleted file mode 100644 index c646b5a17..000000000 --- a/Mailman/MailCommandHandler.py +++ /dev/null @@ -1,783 +0,0 @@ -# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -"""Process mailing list user commands arriving via email.""" - -# Try to stay close to majordomo commands, but accept common mistakes. -# Not implemented: get / index / which. - -import os -import sys -import re -import traceback -import email.Iterators -import email.Utils -from cStringIO import StringIO - -from Mailman import mm_cfg -from Mailman import Utils -from Mailman import Errors -from Mailman import Message -from Mailman import Pending -from Mailman import MemberAdaptor -from Mailman.UserDesc import UserDesc -from Mailman.Logging.Syslog import syslog -import Mailman.i18n - - - -MAXERRORS = 5 -MAXCOLUMN = 70 - -NL = '\n' -SPACE = ' ' - -# jcrey: I must to do a trick to make pygettext detect this strings. First we -# define a fake function. Idea taken from Mads. -def _(s): - return s - - - -# Command descriptions - -HIDE = _('''When turned on, your email address is concealed on the Web page -that lists the members of the mailing list.''') - -NOMAIL = _('''When turned on, delivery to your email address is disabled, but -your address is still subscribed. This is useful if you plan on taking a -short vacation.''') - -ACK = _('''When turned on, you get a separate acknowledgement email when you -post messages to the list.''') - -NOTMETOO = _('''When turned on, you do *not* get copies of your own posts to -the list. Otherwise, you do get copies of your own posts (yes, this seems a -little backwards). This does not affect the contents of digests, so if you -receive postings in digests, you will always get copies of your messages in -the digest.''') - -DIGEST = _('''When turned on, you get postings from the list bundled into -digests. Otherwise, you get each individual message immediately as it is -posted to the list.''') - -PLAIN = _("""When turned on, you get `plain' digests, which are actually -formatted using the RFC1154 digest format. This format can be easier to read -if you have a non-MIME compliant mail reader. When this option is turned off, -you get digests in MIME format, which are much better if you have a mail -reader that supports MIME.""") - -NODUPES = _("""When turned on, you do *not* receive list copies of message -which have you as an explicit recipient (i.e. if you're both a member of the -list and in either the To: or Cc: headers).""") - -option_desc = {'hide' : HIDE, - 'nomail' : NOMAIL, - 'ack' : ACK, - 'notmetoo' : NOTMETOO, - 'digest' : DIGEST, - 'plain' : PLAIN, - 'nodupes' : NODUPES, - } - -# jcrey: and then the real one -_ = Mailman.i18n._ - -option_info = {'hide' : mm_cfg.ConcealSubscription, - 'nomail' : mm_cfg.DisableDelivery, - 'ack' : mm_cfg.AcknowledgePosts, - 'notmetoo': mm_cfg.DontReceiveOwnPosts, - 'digest' : 0, - 'plain' : mm_cfg.DisableMime, - 'nodupes' : mm_cfg.DontReceiveDuplicates - } - -# ordered list -options = ('hide', 'nomail', 'ack', 'notmetoo', 'digest', 'plain', 'nodupes') - -# strip just the outer layer of quotes -quotecre = re.compile(r'["\'`](?P<cmd>.*)["\'`]') - - - -class MailCommandHandler: - def __init__(self): - self.__errors = 0 - self.__respbuf = '' - self.__dispatch = None - self.__noresponse = 0 - - def __makedispatch(self): - self.__dispatch = { - 'subscribe' : self.ProcessSubscribeCmd, - 'join' : self.ProcessSubscribeCmd, - 'confirm' : self.ProcessConfirmCmd, - 'unsubscribe' : self.ProcessUnsubscribeCmd, - 'remove' : self.ProcessUnsubscribeCmd, - 'leave' : self.ProcessUnsubscribeCmd, - 'who' : self.ProcessWhoCmd, - 'info' : self.ProcessInfoCmd, - 'lists' : self.ProcessListsCmd, - 'help' : self.ProcessHelpCmd, - 'set' : self.ProcessSetCmd, - 'options' : self.ProcessOptionsCmd, - 'password' : self.ProcessPasswordCmd, - } - - def AddToResponse(self, text, trunc=MAXCOLUMN, prefix=''): - # Strip final newline - if text and text[-1] == '\n': - text = text[:-1] - for line in text.split('\n'): - line = prefix + line - if trunc and len(line) > trunc: - line = line[:trunc-3] + '...' - self.__respbuf += line + '\n' - - def AddError(self, text, prefix='>>>>> ', trunc=MAXCOLUMN): - self.__errors += 1 - self.AddToResponse(text, trunc=trunc, prefix=prefix) - - def ParseMailCommands(self, msg, msgdata): - if self.__dispatch is None: - self.__makedispatch() - self.__noresponse = 0 - # Break any infloops. If this has come from a Mailman server then - # it'll have this header. It's still possible to infloop between two - # servers because there's no guaranteed way to know it came from a - # bot. - if msg['x-beenthere'] or msg['list-id']: - return - # Check the autoresponse stuff - if self.autorespond_requests: - # BAW: this is a hack and is not safe with respect to errors in - # the Replybot module. It should be redesigned to work with the - # robust delivery scheme. - from Mailman.Handlers import Replybot - # BAW: Replybot doesn't currently support multiple languages - Replybot.process(self, msg, msgdata={'torequest':1}) - if self.autorespond_requests == 1: - # Yes, auto-respond and discard - return - subject = msg.get('subject', '') - sender = msg.get_sender().lower().split('@')[0] - # - # XXX: why 'orphanage'? - if sender in mm_cfg.LIKELY_BOUNCE_SENDERS: - # This is for what are probably delivery-failure notices of - # subscription confirmations that are, of necessity, bounced - # back to the -request address. - syslog('bounce', '''\ -%s: Mailcmd rejected -Reason: Probable bounced subscribe-confirmation -From: %s -Subject: %s''', self.internal_name(), msg['from'], subject) - return - if subject: - subject = subject.strip() - # remove quotes so "help" works - mo = quotecre.search(subject) - if mo: - subject = mo.group('cmd') - - # We must have a real list because of the way we insert an element and - # iterate over it. In email 0.x (pre-Python 2.2) body_line_iterator() - # returns a real list, but in email 1.x (Python 2.2), it returns a - # generator. This is the only way to coerce it to a concrete list - # object in both cases. - lines = list(email.Iterators.body_line_iterator(msg)) - - # Find out if the subject line has a command on it - subjcmd = [] - if subject: - cmdfound = 0 - for word in subject.split(): - word = word.lower() - if cmdfound: - subjcmd.append(word) - elif self.__dispatch.has_key(word): - cmdfound = 1 - subjcmd.append(word) - if subjcmd: - lines.insert(0, SPACE.join(subjcmd)) - else: - self.AddError(_('Subject line ignored:\n ') + subject) - processed = {} # For avoiding redundancies. - maxlines = mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES - for linecount in range(len(lines)): - if linecount > maxlines: - self.AddError(_( -"Maximum command lines (%(maxlines)d) encountered, ignoring the rest...")) - for line in lines[linecount:]: - self.AddToResponse("> " + line, trunc=0) - break - line = lines[linecount].strip() - if not line: - continue - args = line.split() - cmd = args[0].lower() - # remove quotes so "help" or `help' works - mo = quotecre.search(cmd) - if mo: - cmd = mo.group('cmd') - args = args[1:] - if cmd in ['end', '--']: - self.AddToResponse('\n***** ' + _('End: ') + line + '\n' + - _('The rest of the message is ignored:')) - for line in lines[linecount+1:]: - self.AddToResponse(line, trunc=0, prefix='> ') - break - if not self.__dispatch.has_key(cmd): - self.AddError(line, prefix=_('Command? ')) - if self.__errors >= MAXERRORS: - self.AddError(_( -'\nToo many errors encountered; the rest of the message is ignored:')) - for line in lines[linecount+1:]: - self.AddToResponse(line, trunc=0, prefix='> ') - break - else: - # We do not repeat identical commands. (Eg, it's common - # with other mlm's for people to put a command in the - # subject and the body, uncertain which one has effect...) - isdup = 0 - if not processed.has_key(cmd): - processed[cmd] = [] - else: - for did in processed[cmd]: - if args == did: - isdup = 1 - break - if not isdup: - processed[cmd].append(args) - self.AddToResponse('\n***** ' + line) - try: - # note that all expected exceptions must be handled by - # the dispatch function. We'll globally collect any - # unexpected (e.g. uncaught) exceptions here. Such an - # exception stops parsing of email commands - # immediately - self.__dispatch[cmd](args, line, msg) - except: - admin = self.GetOwnerEmail() - sfp = StringIO() - traceback.print_exc(file=sfp) - tbmsg = sfp.getvalue() - errmsg = Utils.wrap(_('''\ -An unexpected Mailman error has occurred. - -Please forward your request to the human list administrator in charge of this -list at <%(admin)s>. The traceback is attached below and will be forwarded to -the list administrator automatically.''')) - self.AddError(errmsg, trunc=0) - self.AddToResponse('\n' + tbmsg, trunc=0) - # log it to the error file - syslog('error', - 'Unexpected Mailman error:\n%s', tbmsg) - # and send the traceback to the user - lang = msgdata.get('lang', self.preferred_language) - responsemsg = Message.UserNotification( - admin, self.GetBouncesEmail(), - _('Unexpected Mailman error'), - _('''\ -An unexpected Mailman error has occurred in -MailCommandHandler.ParseMailCommands(). Here is the traceback: - -''') + tbmsg, lang=lang) - responsemsg['X-No-Archive'] = 'yes' - responsemsg.send(self) - break - # send the response - if not self.__noresponse: - adminaddr = self.GetOwnerEmail() - requestaddr = self.GetRequestEmail() - if self.__errors > 0: - header = Utils.wrap(_('''This is an automated response. - -There were problems with the email commands you sent to Mailman via the -administrative address %(requestaddr)s. - -To obtain instructions on valid Mailman email commands, send email to -%(requestaddr)s with the word "help" in the subject line or in the body of the -message. - -If you want to reach the human being that manages this mailing list, please -send your message to %(adminaddr)s. - -The following is a detailed description of the problems. - -''')) - self.__respbuf = header + self.__respbuf - # send the response - realname = self.real_name - subject = _('Mailman results for %(realname)s') - sender = msg.get_sender() - lang = msgdata.get('lang', self.getMemberLanguage(sender)) - responsemsg = Message.UserNotification(msg.get_sender(), - self.GetRequestEmail(), - subject, - self.__respbuf, lang) - responsemsg.send(self) - self.__respbuf = '' - self.__errors = 0 - - def ProcessPasswordCmd(self, args, cmd, mail): - if len(args) <> 0 and len(args) <> 2: - self.AddError(_("Usage: password [<oldpw> <newpw>]")) - return - sender = mail.get_sender() - if not args: - # Mail user's password to user - try: - password = self.getMemberPassword(sender) - except Errors.NotAMember: - password = None - if self.isMember(sender) and password: - user = self.getMemberCPAddress(sender) - self.AddToResponse(_( - 'You are subscribed as %(user)s, with password: %(password)s'), - trunc=0) - else: - self.AddError(_('Found no password for %(sender)s'), trunc=0) - return - # Try to change password - try: - oldpw = self.getMemberPassword(sender) - if oldpw <> args[0]: - self.AddError(_('You gave the wrong password.')) - else: - self.setMemberPassword(sender, args[1]) - self.AddToResponse(_('Succeeded.')) - except Errors.NotAMemberError: - self.AddError(_("%(sender)s is not a member of this list."), - trunc=0) - - def ProcessOptionsCmd(self, args, cmd, mail): - sender = mail.get_sender() - if not self.isMember(sender): - self.AddError(_("%(sender)s is not a member of this list."), - trunc=0) - return - for option in options: - # We handle disabled delivery differently now - if option == 'nomail': - status = self.getDeliveryStatus(sender) - if status == MemberAdaptor.ENABLED: - value = _('off') - else: - reason = { - MemberAdaptor.BYUSER: _('by your configuration'), - MemberAdaptor.BYADMIN: _('by list admin'), - MemberAdaptor.BYBOUNCE: _('by bounce'), - MemberAdaptor.UNKNOWN : _('for unknown reasons'), - }[status] - value = _('on (%(reason)s') - elif self.getMemberOption(sender, option_info[option]): - value = 'on' - else: - value = 'off' - self.AddToResponse('%8s: %s' % (option, value)) - self.AddToResponse(_("""\ -To change an option, do: set <option> <on|off> <password> - -Option explanations: --------------------- -""")) - for option in options: - self.AddToResponse(option + ':') - self.AddToResponse(Utils.wrap(_(option_desc[option])) + '\n', - trunc=0, prefix=" ") - - def __setcmd_usage(self): - options = option_desc.keys() - options.sort() - text = [] - for option in options: - text.append('%12s: %s' % (option, _(option_desc[option]))) - self.AddError(_('''\ -Usage: set <option> <on|off> <password> -Valid options are: -''') + NL.join(text), trunc=0) - - def ProcessSetCmd(self, args, cmd, msg): - sender = msg.get_sender() - if len(args) <> 3: - self.__setcmd_usage() - return - if args[1] == 'on': - value = 1 - elif args[1] == 'off': - value = 0 - else: - self.__setcmd_usage() - return - # Check the command - option = args[0] - # Backwards compatibility - if option == 'norcv': - option = 'notmetoo' - if not option_info.has_key(option): - self.__setcmd_usage() - return - # Confirm the password - try: - password = self.getMemberPassword(sender) - except Errors.NotAMemberError: - self.AddError(_("%(sender)s is not a member of this list."), - trunc=0) - return - if password <> args[2]: - self.AddError(_('You gave the wrong password.')) - return - - # Set the option - try: - # delivery disable is handled separately now - if option == 'nomail': - self.setDeliveryStatus(sender, MemberAdaptor.BYUSER) - else: - self.setMemberOption(sender, option_info[option], value) - self.AddToResponse(_('Succeeded.')) - except Errors.AlreadyReceivingDigests: - self.AddError(_('You are already receiving digests.')) - except Errors.AlreadyReceivingRegularDeliveries: - self.AddError(_('You already have digests off.')) - except Errors.MustDigestError: - self.AddError(_('List only accepts digest members.')) - except Errors.CantDigestError: - self.AddError(_("List doesn't accept digest members.")) - except Errors.MMNeedApproval: - self.AddApprovalMsg(cmd) - - def ProcessListsCmd(self, args, cmd, mail): - if len(args) != 0: - self.AddError(_("Usage: lists")) - return - lists = Utils.list_names() - lists.sort() - hostname = self.host_name - self.AddToResponse(_( - "\nPublic mailing lists run by mailman@%(hostname)s"), - trunc=0) - for listname in lists: - if listname == self._internal_name: - listob = self - else: - try: - from Mailman import MailList - listob = MailList.MailList(listname, lock=0) - except Errors.MMListError, e: - # TBD: better error reporting - continue - # We can mention this list if you already know about it. - if not listob.advertised and listob <> self: - continue - self.AddToResponse(listob.real_name + ':') - self.AddToResponse(_('\trequests to: ') + listob.GetRequestEmail(), - trunc=0) - if listob.description: - self.AddToResponse(_('\tdescription: ') + listob.description, - trunc=0) - - def ProcessInfoCmd(self, args, cmd, mail): - if len(args) != 0: - self.AddError(_(""" -Usage: info -To get info for a particular list, send your request to -the `-request' address for that list, or use the `lists' command -to get info for all the lists.""")) - return - - if self.private_roster and not self.isMember(mail.get_sender()): - self.AddError(_("Private list: only members may see info.")) - return - - listname = self.real_name - url = self.GetScriptURL('listinfo', absolute=1) - msg = Utils.wrap(_(''' -For more complete info about the %(listname)s mailing list, including -background and instructions for subscribing to and using it, visit: - - %(url)s - -''')) - self.AddToResponse(msg, trunc=0) - - if not self.info: - self.AddToResponse(_("No other details are available.")) - else: - self.AddToResponse(Utils.wrap(self.info), trunc=0) - - def ProcessWhoCmd(self, args, cmd, mail): - if len(args) != 0: - self.AddError(_("""\ -Usage: who -To get subscribership for a particular list, send your request -to the `-request' address for that list.""")) - return - if self.private_roster == 2: - self.AddError(_("Private list: No one may see subscription list.")) - return - if self.private_roster and not self.isMember(mail.get_sender()): - self.AddError(_( - "Private list: only members may see list of subscribers.")) - return - digestmembers = self.getDigestMemberKeys() - members = self.getRegularMemberKeys() - if not digestmembers and not members: - self.AddToResponse(_("NO MEMBERS.")) - return - - def AddTab(str): - return '\t' + str - def NotHidden(x, s=self, v=mm_cfg.ConcealSubscription): - return not s.getMemberOption(x, v) - - if len(digestmembers): - digestmembers.sort() - self.AddToResponse(_("Digest Members:\n") + - NL.join(map(AddTab, filter(NotHidden, - digestmembers))), - trunc=0) - if len(members): - members.sort() - self.AddToResponse(_("Non-Digest Members:\n") + - NL.join(map(AddTab, filter(NotHidden, - members))), - trunc=0) - - def ProcessUnsubscribeCmd(self, args, cmd, msg): - password = None - if not args: - # No password and no address. We can sniff the address, and we - # will do a confirmation notice. - addr = msg.get_sender() - elif len(args) == 1: - # We only got one argument, so we're not sure if that's the user's - # address or password. If the argument is a subscribed user, then - # assume its the address and send a confirmation notice. - # Otherwise, assume it's a password. This could seem weird if - # they're using their address as their password, but even still, - # it's not too bad. - if self.isMember(args[0]): - addr = args[0] - else: - addr = msg.get_sender() - password = args[0] - elif len(args) == 2: - password = args[0] - addr = args[1] - else: - self.AddError(Utils.wrap( - _("""\ -Usage: unsubscribe [password] [email-address] -To unsubscribe from a particular list, send your request to -the `-request' address for that list."""), - honor_leading_ws = 0), - trunc = 0) - return - try: - if self.unsubscribe_policy: - # If we're doing admin-approved unsubs, then don't worry about - # the password. - try: - self.DeleteMember(addr, 'mailcmd') - except Errors.MMNeedApproval: - self.AddToResponse( - _("""\ -Your unsubscription request has been forwarded to the list administrator for -approval."""), trunc=0) - elif password is None: - # If no password was given, we need to do a mailback - # confirmation instead of unsubscribing them here. - cpaddr = self.getMemberCPAddress(addr) - self.ConfirmUnsubscription(cpaddr) - self.AddToResponse( - _('A removal confirmation message has been sent.')) - else: - # No admin approval is necessary, so we can just delete them - # if the passwords match.a - oldpw = self.getMemberPassword(addr) - if oldpw <> password: - self.AddError(_('You gave the wrong password.')) - else: - self.ApprovedDeleteMember(addr, 'mailcmd') - self.AddToResponse(_("Succeeded.")) - # FIXME: we really need to make these exceptions sane! - except (Errors.MMNoSuchUserError, Errors.MMNotAMemberError, - Errors.NotAMemberError): - # For compatibility with similar strings above :( - sender = addr - self.AddError(_("%(sender)s is not a member of this list."), - trunc=0) - - def ProcessSubscribeCmd(self, args, cmd, mail): - """Parse subscription request and send confirmation request.""" - digest = self.digest_is_default - password = '' - address = '' - fullname = '' - done_digest = 0 - if not len(args): - password = Utils.MakeRandomPassword() - elif len(args) > 3: - self.AddError(_("""\ -Usage: subscribe [password] [digest|nodigest] [address=<email-address>]"""), - trunc=0) - return - else: - for arg in args: - if arg.lower() == 'digest' and not done_digest: - digest = 1 - done_digest = 1 - elif arg.lower() == 'nodigest' and not done_digest: - digest = 0 - done_digest = 1 - elif arg.lower()[:8] == 'address=' and not address: - address = Utils.LCDomain(arg[8:]) - elif not password: - password = arg - else: - self.AddError(_("""\ -Usage: subscribe [password] [digest|nodigest] [address=<email-address>]""")) - return - if not password: - password = Utils.MakeRandomPassword() - if not address: - sender = mail['from'] - if not sender: - sender = mail.get_sender() - fullname, addr = email.Utils.parseaddr(sender) - subscribe_address = Utils.LCDomain(addr) - else: - subscribe_address = address - remote = mail.get_sender() - try: - # FIXME: extract fullname - userdesc = UserDesc(address=subscribe_address, - fullname=fullname, - password=password, - digest=digest) - self.AddMember(userdesc, remote) - self.Save() - except Errors.MembershipIsBanned: - listowner = self.GetOwnerEmail() - self.AddToResponse(_("""\ -The email address you supplied is banned from this mailing list. -If you think this restriction is erroneous, please contact the list -owners at %(listowner)s.""")) - except Errors.MMSubscribeNeedsConfirmation: - # - # the confirmation message that's been sent takes place - # of the results of the mail command message - # - self.__noresponse = 1 - except Errors.MMNeedApproval: - adminemail = self.GetOwnerEmail() - self.AddToResponse(_("""\ -Your subscription request has been forwarded to the list administrator -at %(adminemail)s for review."""), trunc=0) - except Errors.MMBadEmailError: - self.AddError(_("""\ -Mailman won't accept the given email address as a valid address. -(E.g. it must have an @ in it.)""")) - except Errors.MMListNotReadyError: - self.AddError(_("\ -The list is not fully functional, and can not accept subscription requests.")) - except Errors.MMHostileAddress: - self.AddError(_("""\ -Your subscription is not allowed because -the email address you gave is insecure.""")) - except Errors.MMAlreadyAMember: - self.AddError(_("You are already subscribed!")) - except Errors.MMCantDigestError: - self.AddError( - _("No one can subscribe to the digest of this list!")) - except Errors.MMMustDigestError: - self.AddError(_("This list only supports digest subscriptions!")) - else: - # - # if the list sends a welcome message, we don't need a response - # from the mailcommand handler. - # - if self.send_welcome_msg: - self.__noresponse = 1 - else: - self.AddToResponse(_("Succeeded")) - - def ProcessConfirmCmd(self, args, cmd, msg): - """Validate confirmation and carry out the subscription.""" - if len(args) <> 1: - self.AddError(_("Usage: confirm <confirmation string>\n")) - return - try: - results = self.ProcessConfirmation(args[0], msg) - op = results[0] - except Errors.MMBadConfirmation, e: - # Express in approximate days - days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1) + 0.5) - self.AddError(Utils.wrap( - _('''\ -Invalid confirmation string. Note that confirmation strings expire -approximately %(days)s days after the initial subscription request. If your -confirmation has expired, please try to re-submit your original request or -message.'''), - honor_leading_ws=0), - trunc=0) - except Errors.MMNeedApproval, admin_addr: - self.AddToResponse(Utils.wrap( - _('''\ -Your request has been forwarded to the list moderator for approval.'''), - honor_leading_ws=0), - trunc=0) - except Errors.MMAlreadyAMember: - # Some other subscription request for this address has - # already succeeded. - self.AddError(_('You are already subscribed.')) - except Errors.MMNoSuchUserError: - # They've already been unsubscribed - self.AddError(Utils.wrap( - _('''You are not a member. Have you already unsubscribed?'''), - honor_leading_ws=0), - trunc=0) - else: - # Send the response unless this was a subscription confirmation, - # and the list sends a welcome message. - if op == Pending.SUBSCRIPTION and self.send_welcome_msg: - self.__noresponse = 1 - else: - self.AddToResponse(_("Succeeded")) - - def AddApprovalMsg(self, cmd): - text = Utils.maketext( - 'approve.txt', - {'requestaddr': self.GetRequestEmail(), - 'cmd' : cmd, - 'adminaddr' : self.GetOwnerEmail(), - }, mlist=self) - self.AddError(text, trunc=0) - - def ProcessHelpCmd(self, args, cmd, mail): - text = Utils.maketext( - 'help.txt', - {'listname' : self.real_name, - 'version' : mm_cfg.VERSION, - 'listinfo_url': self.GetScriptURL('listinfo', absolute=1), - 'requestaddr' : self.GetRequestEmail(), - 'adminaddr' : self.GetOwnerEmail(), - }, mlist=self) - self.AddToResponse(text, trunc=0) - |
