diff options
| -rw-r--r-- | Mailman/Deliverer.py | 248 |
1 files changed, 38 insertions, 210 deletions
diff --git a/Mailman/Deliverer.py b/Mailman/Deliverer.py index 1f0649076..7789b6809 100644 --- a/Mailman/Deliverer.py +++ b/Mailman/Deliverer.py @@ -17,202 +17,35 @@ """Mixin class with message delivery routines.""" +import os +import string -import string, os, sys -import operator -import errno -import mm_cfg -import Errors -import Utils +from Mailman import mm_cfg +from Mailman import Errors +from Mailman import Utils +from Mailman import Message +from Mailman.Handlers import HandlerAPI -# Note that the text templates for the various messages have been moved into -# the templates directory. - -# We could abstract these two better... + class Deliverer: - def AddNonStandardHeaders(self, headers, zaplist=None): - # Add headers like Precedence: and other useful headers. None of - # these are standard and finding information on some of them are - # fairly difficult. Some are just common practice, and we'll add more - # here as they become necessary. A good place to look is - # http://www.dsv.su.se/~jpalme/ietf/jp-ietf-home.html - # - # None of these headers are added if they already exist - d = {} - if zaplist is None: - zaplist = headers - for h in zaplist: - i = string.find(h, ':') - key = string.lower(h[:6]) - d[key] = key - if not d.has_key('x-mailman-version'): - headers.append('X-Mailman-Version: %s\n' % mm_cfg.VERSION) - # semi-controversial: some don't want this included at all, others - # want the value to be `list' - if not d.has_key('precedence'): - headers.append('Precedence: bulk\n') - # Other list related non-standard headers. Defined in: - # - # Grant Neufeld and Joshua D. Baer: The Use of URLs as Meta-Syntax for - # Core Mail List Commands and their Transport through Message Header - # fields, draft-baer-listspec-01.txt, September 1997. - # - # Referenced in - # - # http://www.dsv.su.se/~jpalme/ietf/mail-attributes.html - if not d.has_key('list-id'): - headers.append('List-Id: %s\n' % self.GetListIdentifier()) - # These currently seem like overkill. Maybe add them in later when - # the draft gets closer to a standard - # List-Subscribe - # List-Unsubscribe - # List-Owner - # List-Help - # List-Post - # List-Archive - # List-Software - # X-Listserver - - # This method assumes the sender is list-admin if you don't give one. - def SendTextToUser(self, subject, text, recipient, sender=None, - add_headers=None): - if add_headers is None: - add_headers = [] - if not sender: - sender = self.GetAdminEmail() - self.AddNonStandardHeaders(add_headers) - Utils.SendTextToUser(subject, text, recipient, sender, - add_headers=add_headers) - - def DeliverToUser(self, msg, recipient): - # This method assumes the sender is the one given by the message. - add_headers = [] - self.AddNonStandardHeaders(add_headers, msg.headers) - add_headers.append('Errors-To: %s\n' % self.GetAdminEmail()) - Utils.DeliverToUser(msg, recipient, add_headers=add_headers) - - def QuotePeriods(self, text): - return string.join(string.split(text, '\n.\n'), '\n .\n') - - # - # This function is used to deliver messages - # that are sent to <listname>-admin. The sender - # of the Mailman-originating message is the admin address - # of the list -- otherwise, if both incoming sender and the - # list's admin address(es) were non-local, many MTAs - # wouldn't accept the message as it would be considered - # improper relaying. - # The recipients arg is a list of the current list - # owners. We don't mess with adding list specific - # headers on body modifications so that the address - # will work just like a normal forwarding address - # - def DeliverToOwner(self, msg, recipients): - if not (len(recipients)): - return - cmd = "%s %s" % (mm_cfg.PYTHON, - os.path.join(mm_cfg.SCRIPTS_DIR, "deliver")) - cmdproc = os.popen(cmd, 'w') - - cmdproc.write("%d\n" % self.num_spawns) - cmdproc.write("%s\n" % self.GetAdminEmail()) - for r in recipients: - # Mustn't send blank lines before end of recipients: - if not r: continue - cmdproc.write(r + "\n") - cmdproc.write('\n') - cmdproc.write(string.join(msg.headers, '') + "\n") - cmdproc.write(self.QuotePeriods(msg.body)) - status = cmdproc.close() - if status: - self.LogMsg('deliverer', - 'Non-zero exit status: %d\nCommand: %s' - (status >> 8), cmd) - - def DeliverToList(self, msg, recipients, - header="", footer="", remove_to=0, tmpfile_prefix = ""): - if not(len(recipients)): + def SendSubscribeAck(self, name, password, digest): + if not self.send_welcome_msg: return - # Massage the headers. - if remove_to: - del msg['to'] - del msg['x-to'] - msg.headers.append('To: %s\n' % self.GetListEmail()) - if self.reply_goes_to_list: - del msg['reply-to'] - msg.headers.append('Reply-To: %s\n' % self.GetListEmail()) - # these can be used to surreptitiously gather membership info - del msg['return-receipt-to'] - del msg['disposition-notification-to'] - del msg['x-confirm-reading-to'] - # get rid of duplicate fields - del msg['sender'] - del msg['errors-to'] - msg.headers.append('Sender: %s\n' % self.GetAdminEmail()) - msg.headers.append('Errors-To: %s\n' % self.GetAdminEmail()) - self.AddNonStandardHeaders(msg.headers) - msg.headers.append('X-BeenThere: %s\n' % self.GetListEmail()) - - cmd = "%s %s" % (mm_cfg.PYTHON, - os.path.join(mm_cfg.SCRIPTS_DIR, "deliver")) - cmdproc = os.popen(cmd, 'w') - - cmdproc.write("%d\n" % self.num_spawns) - cmdproc.write("%s\n" % self.GetAdminEmail()) - for r in recipients: - # Mustn't send blank lines before end of recipients: - if not r: continue - cmdproc.write(r + "\n") - cmdproc.write("\n") # Empty line for end of recipients. - cmdproc.write(string.join(msg.headers, '') + "\n") - if header: # The *body* header: - cmdproc.write(header + "\n") - cmdproc.write(self.QuotePeriods(msg.body)) - if footer: - cmdproc.write(footer) - - status = cmdproc.close() - if status: - self.LogMsg('deliverer', - 'Non-zero exit status: %d\nCommand: %s', - (status >> 8), cmd) - - def SendPostAck(self, msg, sender): - subject = msg.getheader('subject') - if not subject: - subject = '[none]' - else: - sp = self.subject_prefix - if (len(subject) > len(sp) - and subject[0:len(sp)] == sp): - # Trim off subject prefix - subject = subject[len(sp):] - # get the text from the template - body = Utils.maketext( - 'postack.txt', - {'subject' : subject, - 'listname' : self.real_name, - 'listinfo_url': self.GetAbsoluteScriptURL('listinfo'), - }) - self.SendTextToUser('%s post acknowlegement' % self.real_name, - body, sender) - - def CreateSubscribeAck(self, name, password): if self.welcome_msg: welcome = Utils.wrap(self.welcome_msg) + '\n' else: welcome = '' if self.umbrella_list: - umbrella = Utils.wrap( - "(Since this is a list of mailing lists, administrative" - " notices like the password reminder will be sent to" - " your membership administrative address, %s.)\n" - % self.GetMemberAdminEmail(name)) + umbrella = Utils.wrap('''\ +Note: Since this is a list of mailing lists, administrative +notices like the password reminder will be sent to +your membership administrative address, %s. +''' % self.GetMemberAdminEmail(name)) else: umbrella = '' # get the text from the template - body = Utils.maketext( + text = Utils.maketext( 'subscribeack.txt', {'real_name' : self.real_name, 'host_name' : self.host_name, @@ -223,26 +56,24 @@ class Deliverer: 'optionsurl' : self.GetAbsoluteOptionsURL(name), 'password' : password, }) - return body - - - def SendSubscribeAck(self, name, password, digest): - if not self.send_welcome_msg: - return if digest: - digest_mode = '(Digest mode)' + digmode = ' (Digest mode)' else: - digest_mode = '' - self.SendTextToUser(subject = 'Welcome To "%s"! %s' % (self.real_name, - digest_mode), - recipient = self.GetMemberAdminEmail(name), - text = self.CreateSubscribeAck(name, password)) + digmode = '' + msg = Message.UserNotification( + self.GetMemberAdminEmail(name), self.GetAdminEmail(), + 'Welcome to the "%s" mailing list%s' % (self.real_name, digmode), + text) + HandlerAPI.DeliverToUser(self, msg) + def SendUnsubscribeAck(self, name): - self.SendTextToUser(subject = 'Unsubscribed from "%s"\n' % - self.real_name, - recipient = self.GetMemberAdminEmail(name), - text = Utils.wrap(self.goodbye_msg)) + msg = Message.UserNotification( + self.GetMemberAdminEmail(name), self.GetAdminEmail(), + 'Unsubscribed from "%s" mailing list' % self.real_name, + Utils.wrap(self.goodbye_msg)) + HandlerAPI.DeliverToUser(self, msg) + def MailUserPassword(self, user): listfullname = '%s@%s' % (self.real_name, self.host_name) @@ -252,7 +83,8 @@ class Deliverer: if user and self.passwords.has_key(user): cpuser = self.GetUserSubscribedAddress(user) recipient = self.GetMemberAdminEmail(cpuser) - subj = '%s mailing list reminder\n' % listfullname + subject = '%s mailing list reminder\n' % listfullname + adminaddr = self.GetAdminEmail() # get the text from the template text = Utils.maketext( 'userpass.txt', @@ -261,23 +93,19 @@ class Deliverer: 'password' : self.passwords[user], 'options_url': self.GetAbsoluteOptionsURL(user), 'requestaddr': self.GetRequestEmail(), - 'adminaddr' : self.GetAdminEmail(), + 'adminaddr' : adminaddr, }) else: ok = 0 recipient = self.GetAdminEmail() - subj = '%s user %s missing password!\n' % (listfullname, user) + subject = '%s user %s missing password!\n' % (listfullname, user) text = Utils.maketext( 'nopass.txt', {'username' : `user`, - 'internal_name': self._internal_name, + 'internal_name': self.internal_name(), }) - self.SendTextToUser(subject = subj, - recipient = recipient, - text = text, - add_headers=["Errors-To: %s" - % self.GetAdminEmail(), - "X-No-Archive: yes", - "Precedence: bulk"]) + msg = Message.UserNotification(recipient, adminaddr, subject, text) + msg['X-No-Archive'] = 'yes' + HandlerAPI.DeliverToUser(self, msg) if not ok: raise Errors.MMBadUserError |
