[Mailman-Developers] [PATCH] Patch for Mailman to use new email i18n mimification

Ben Gertzfield ben@gmo.jp
Mon, 19 Nov 2001 20:42:56 +0900


Here's the promised patch in my previous email, that enables Mailman
to send out properly MIME-ified, localized emails, with the correct
encoding and charset conversion for each language.  This patch is
against Mailman CVS.

Ben

Index: Mailman/Bouncer.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Bouncer.py,v
retrieving revision 2.14
diff -u -r2.14 Bouncer.py
--- Mailman/Bouncer.py	2001/10/15 20:39:56	2.14
+++ Mailman/Bouncer.py	2001/11/19 11:00:14
@@ -208,7 +208,8 @@
             rname = self.real_name
             msg0 = Message.UserNotification(
                 recipient, Utils.get_site_email(self.host_name, '-admin'),
-                _('%(rname)s member %(addr)s bouncing - %(negative)s%(did)s'))
+                _('%(rname)s member %(addr)s bouncing - %(negative)s%(did)s'),
+                lang=self.preferred_language)
             msg0['MIME-Version'] = '1.0'
             msg0['Content-Type'] = 'multipart/mixed'
             msg1 = MIMEText(text,
Index: Mailman/Deliverer.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Deliverer.py,v
retrieving revision 2.10
diff -u -r2.10 Deliverer.py
--- Mailman/Deliverer.py	2001/10/21 06:24:56	2.10
+++ Mailman/Deliverer.py	2001/11/19 11:00:14
@@ -65,7 +65,7 @@
         msg = Message.UserNotification(
             self.GetMemberAdminEmail(name), self.GetRequestEmail(),
             _('Welcome to the "%(realname)s" mailing list%(digmode)s'),
-            text)
+            text, pluser)
         msg['X-No-Archive'] = 'yes'
         msg.send(self)
 
@@ -74,7 +74,7 @@
         msg = Message.UserNotification(
             self.GetMemberAdminEmail(addr), self.GetAdminEmail(),
             _('You have been unsubscribed from the %(realname)s mailing list'),
-            Utils.wrap(self.goodbye_msg))
+            Utils.wrap(self.goodbye_msg), self.GetMemberLanguage(addr))
         msg.send(self)
 
     def MailUserPassword(self, user):
@@ -101,6 +101,7 @@
         cpuser = self.getMemberCPAddress(user)
         recipient = self.GetMemberAdminEmail(cpuser)
         subject = _('%(listfullname)s mailing list reminder')
+        mem_lang = self.getMemberLanguage(user)
         # get the text from the template
         text = Utils.maketext(
             'userpass.txt',
@@ -111,7 +112,8 @@
              'options_url': self.GetOptionsURL(user, absolute=1),
              'requestaddr': requestaddr,
              'owneraddr'  : self.GetOwnerEmail(),
-            }, lang=self.getMemberLanguage(user), mlist=self)
-        msg = Message.UserNotification(recipient, adminaddr, subject, text)
+            }, lang=mem_lang, mlist=self)
+        msg = Message.UserNotification(recipient, adminaddr, subject, text,
+                                       mem_lang)
         msg['X-No-Archive'] = 'yes'
         msg.send(self)
Index: Mailman/ListAdmin.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/ListAdmin.py,v
retrieving revision 2.22
diff -u -r2.22 ListAdmin.py
--- Mailman/ListAdmin.py	2001/11/06 22:49:36	2.22
+++ Mailman/ListAdmin.py	2001/11/19 11:00:14
@@ -30,6 +30,8 @@
 import cPickle
 import email
 from email.MIMEMessage import MIMEMessage
+from email.Encoders import encode_header
+from email.Charset import Charset
 from cStringIO import StringIO
 
 from Mailman import mm_cfg
@@ -281,9 +283,13 @@
             except IOError, e:
                 if e.errno <> errno.ENOENT: raise
                 raise Errors.LostHeldMessage(path)
+            # We have to call email.Encoders.encode_header directly, we
+            # don't want to mess with the message
+            subject = encode_header(_('Forward of moderated  message'),
+                                    Charset(self.preferred_language))
             fmsg = Message.UserNotification(addr,
                                             self.GetAdminEmail(),
-                                            _('Forward of moderated  message'))
+                                            subject)
             fmsg.add_header('Content-Type', 'message/rfc822')
             fmsg.add_payload(copy)
             fmsg.send(self)
@@ -351,7 +357,8 @@
             # This message should appear to come from the <list>-owner so as
             # to avoid any useless bounce processing.
             owneraddr = self.GetOwnerEmail()
-            msg = Message.UserNotification(owneraddr, owneraddr, subject, text)
+            msg = Message.UserNotification(owneraddr, owneraddr, subject, text,
+                                           lang)
             msg.send(self, **{'tomoderators': 1})
 
     def __handlesubscription(self, record, value, comment):
@@ -401,7 +408,8 @@
             # This message should appear to come from the <list>-owner so as
             # to avoid any useless bounce processing.
             owneraddr = self.GetOwnerEmail()
-            msg = Message.UserNotification(owneraddr, owneraddr, subject, text)
+            msg = Message.UserNotification(owneraddr, owneraddr, subject, text,
+                                           self.preferred_language)
             msg.send(self, **{'tomoderators': 1})
 
     def __handleunsubscription(self, record, value, comment):
@@ -441,7 +449,7 @@
                  str(origmsg)
                  ])
         subject = _('Request to mailing list %(realname)s rejected')
-        msg = Message.UserNotification(recip, adminaddr, subject, text)
+        msg = Message.UserNotification(recip, adminaddr, subject, text, lang)
         msg.send(self)
 
 
Index: Mailman/MailCommandHandler.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/MailCommandHandler.py,v
retrieving revision 2.23
diff -u -r2.23 MailCommandHandler.py
--- Mailman/MailCommandHandler.py	2001/10/21 22:11:20	2.23
+++ Mailman/MailCommandHandler.py	2001/11/19 11:00:14
@@ -270,18 +270,16 @@
                         syslog('error',
                                'Unexpected Mailman error:\n%s', tbmsg)
                         # and send the traceback to the user
+                        lang = msgdata.get('lang',
+                                           self.getMemberLanguage(admin))
                         responsemsg = Message.UserNotification(
                             admin, admin, _('Unexpected Mailman error'),
                             _('''\
 An unexpected Mailman error has occurred in
 MailCommandHandler.ParseMailCommands().  Here is the traceback:
 
-''') + tbmsg)
+''') + tbmsg, lang)
                         responsemsg['X-No-Archive'] = 'yes'
-                        lang = msgdata.get('lang',
-                                           self.getMemberLanguage(admin))
-                        responsemsg.add_header('Content-Type', 'text/plain',
-                                               charset=Utils.GetCharSet(lang))
                         responsemsg.send(self)
                         break
         # send the response
@@ -313,7 +311,7 @@
             responsemsg = Message.UserNotification(msg.get_sender(),
                                                    self.GetRequestEmail(),
                                                    subject,
-                                                   self.__respbuf)
+                                                   self.__respbuf, lang)
             responsemsg.add_header('Content-Type', 'text/plain',
                                    charset=Utils.GetCharSet(lang))
             responsemsg.send(self)
Index: Mailman/MailList.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/MailList.py,v
retrieving revision 2.48
diff -u -r2.48 MailList.py
--- Mailman/MailList.py	2001/10/27 01:59:41	2.48
+++ Mailman/MailList.py	2001/11/19 11:00:15
@@ -666,7 +666,7 @@
             msg = Message.UserNotification(
                 recipient, self.GetRequestEmail(),
                 'confirm %s' % cookie,
-                text)
+                text, lang)
             msg['Reply-To'] = self.GetRequestEmail()
             msg.send(self)
             if recipient <> email:
@@ -748,7 +748,7 @@
                  }, lang=lang, mlist=self)
             msg = Message.UserNotification(
                 self.owner, Utils.get_site_email(self.host_name, '-admin'),
-                subject, text)
+                subject, text, lang)
             msg.send(self)
 
     def DeleteMember(self, name, whence=None, admin_notif=0, userack=1):
@@ -786,7 +786,7 @@
                  }, mlist=self)
             msg = Message.UserNotification(
                 self.owner, Utils.get_site_email(self.host_name, '-admin'),
-                subject, text)
+                subject, text, lang)
             msg.send(self)
         if whence:
             whence = "; %s" % whence
@@ -850,7 +850,7 @@
         msg = Message.UserNotification(
             newaddr, self.GetRequestEmail(),
             'confirm %s' % cookie,
-            text)
+            text, self.getMemberLanguage(oldaddr))
         msg['Reply-To'] = self.GetRequestEmail()
         msg.send(self)
 
@@ -994,7 +994,7 @@
         msg = Message.UserNotification(
             addr, self.GetRequestEmail(),
             'confirm %s' % cookie,
-            text)
+            text, lang)
         msg['Reply-To'] = self.GetRequestEmail()
         msg.send(self)
 
Index: Mailman/Message.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Message.py,v
retrieving revision 2.9
diff -u -r2.9 Message.py
--- Mailman/Message.py	2001/10/15 21:38:01	2.9
+++ Mailman/Message.py	2001/11/19 11:00:15
@@ -22,6 +22,9 @@
 
 import email.Message
 import email.Utils
+from email.Encoders import encode_body, encode_header
+from email.Charset import Charset, QP, BASE64
+
 from types import ListType
 
 from Mailman import mm_cfg
@@ -92,8 +95,22 @@
 class UserNotification(Message):
     """Class for internally crafted messages."""
 
-    def __init__(self, recip, sender, subject=None, text=None):
+    def __init__(self, recip, sender, subject=None, text=None, lang=None):
         Message.__init__(self)
+
+        if lang is not None:
+            cset = Charset(Utils.GetCharSet(lang))
+            text = encode_body(text, cset)
+            subject = encode_header(subject, cset)
+            self.add_header('MIME-Version', '1.0')
+            self.add_header('Content-Type', 'text/plain',
+                            charset=cset.output_charset)
+            cte = '7bit'
+            if cset.body_encoding is QP:
+                cte = 'quoted-printable'
+            elif cset.body_encoding is BASE64:
+                cte = 'base64'
+                self.add_header('Content-Transfer-Encoding', cte)
         if text is not None:
             self.set_payload(text)
         if subject is None:
@@ -106,6 +123,7 @@
         else:
             self['To'] = recip
             self.recips = [recip]
+        self.lang = lang
 
     def send(self, mlist, **_kws):
         """Sends the message by enqueuing it to the `virgin' queue.
@@ -117,6 +135,7 @@
         # this is useful for logging to logs/smtp.
         if not self.has_key('message-id'):
             self['Message-ID'] = Utils.unique_message_id(mlist)
+
         # Not imported at module scope to avoid import loop
         from Mailman.Queue.sbcache import get_switchboard
         virginq = get_switchboard(mm_cfg.VIRGINQUEUE_DIR)
Index: Mailman/Cgi/create.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Cgi/create.py,v
retrieving revision 2.13
diff -u -r2.13 create.py
--- Mailman/Cgi/create.py	2001/11/06 23:29:19	2.13
+++ Mailman/Cgi/create.py	2001/11/19 11:00:15
@@ -219,7 +219,7 @@
         msg = Message.UserNotification(
             owner, siteadmin,
             _('Your new mailing list: %(listname)s'),
-            text)
+            text, mlist.preferred_language)
         msg.send(mlist)
 
     # Success!
Index: Mailman/Cgi/subscribe.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Cgi/subscribe.py,v
retrieving revision 2.15
diff -u -r2.15 subscribe.py
--- Mailman/Cgi/subscribe.py	2001/10/12 05:14:25	2.15
+++ Mailman/Cgi/subscribe.py	2001/11/19 11:00:15
@@ -230,7 +230,7 @@
 an attempt is being made to covertly discover whether you are a member of this
 list, and you are worried about your privacy, then feel free to send a message
 to the list administrator at %(listowner)s.
-"""))
+"""), lang)
             msg.send(mlist)
     # These shouldn't happen unless someone's tampering with the form
     except Errors.MMCantDigestError:
Index: Mailman/Handlers/Acknowledge.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Acknowledge.py,v
retrieving revision 2.10
diff -u -r2.10 Acknowledge.py
--- Mailman/Handlers/Acknowledge.py	2001/10/01 16:32:06	2.10
+++ Mailman/Handlers/Acknowledge.py	2001/11/19 11:00:15
@@ -63,7 +63,5 @@
     # queue.
     subject = _('%(realname)s post acknowledgement')
     usermsg = Message.UserNotification(sender, mlist.GetAdminEmail(),
-                                       subject, text)
-    usermsg.add_header('Content-Type', 'text/plain',
-                       charset=Utils.GetCharSet(lang))
+                                       subject, text, lang)
     usermsg.send(mlist)
Index: Mailman/Handlers/Hold.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Hold.py,v
retrieving revision 2.18
diff -u -r2.18 Hold.py
--- Mailman/Handlers/Hold.py	2001/10/15 22:22:08	2.18
+++ Mailman/Handlers/Hold.py	2001/11/19 11:00:15
@@ -217,9 +217,8 @@
         lang = msgdata.get('lang', mlist.getMemberLanguage(sender))
         subject = _('Your message to %(listname)s awaits moderator approval')
         text = Utils.maketext('postheld.txt', d, lang=lang, mlist=mlist)
-        nmsg = Message.UserNotification(sender, adminaddr, subject, text)
-        nmsg.add_header('Content-Type', 'text/plain',
-                        charset=Utils.GetCharSet(lang))
+        nmsg = Message.UserNotification(sender, adminaddr, subject, text,
+                                        lang)
         nmsg.send(mlist)
     # Now the message for the list owners.  Be sure to include the list
     # moderators in this message.  This one should appear to come from
@@ -237,7 +236,8 @@
             d['subject'] = usersubject
             # craft the admin notification message and deliver it
             subject = _('%(listname)s post from %(sender)s requires approval')
-            nmsg = Message.UserNotification(owneraddr, owneraddr, subject)
+            nmsg = Message.UserNotification(owneraddr, owneraddr, subject,
+                                            lang=lang)
             nmsg['Content-Type'] = 'multipart/mixed'
             nmsg['MIME-Version'] = '1.0'
             text = MIMEText(
Index: Mailman/Handlers/Moderate.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Moderate.py,v
retrieving revision 2.0
diff -u -r2.0 Moderate.py
--- Mailman/Handlers/Moderate.py	2001/10/15 22:23:17	2.0
+++ Mailman/Handlers/Moderate.py	2001/11/19 11:00:15
@@ -93,7 +93,8 @@
                   mlist.GetScriptURL('admin', absolute=1)
         nmsg = Message.UserNotification(mlist.GetOwnerEmail(),
                                         mlist.GetAdminEmail(),
-                                        _('Auto-discard notification'))
+                                        _('Auto-discard notification'),
+                                        mlist.preferred_language)
         nmsg['Content-Type'] = 'multipart/mixed'
         nmsg['MIME-Version'] = '1.0'
         text = MIMEText(Utils.wrap(_("""\
Index: Mailman/Handlers/Replybot.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Replybot.py,v
retrieving revision 2.4
diff -u -r2.4 Replybot.py
--- Mailman/Handlers/Replybot.py	2001/07/13 17:00:34	2.4
+++ Mailman/Handlers/Replybot.py	2001/11/19 11:00:15
@@ -48,6 +48,7 @@
     # means always autorespond, as does an "X-Ack: yes" header (useful for
     # debugging).
     sender = msg.get_sender()
+    lang = mlist.getMemberLanguage(sender)
     now = time.time()
     graceperiod = mlist.autoresponse_graceperiod
     if graceperiod > 0 and ack <> 'yes':
@@ -90,7 +91,7 @@
     # Wrap the response.
     text = Utils.wrap(text)
     outmsg = Message.UserNotification(sender, mlist.GetAdminEmail(),
-                                      subject, text)
+                                      subject, text, lang)
     outmsg['X-Mailer'] = _('The Mailman Replybot')
     # prevent recursions and mail loops!
     outmsg['X-Ack'] = 'No'
Index: Mailman/MTA/Manual.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/MTA/Manual.py,v
retrieving revision 2.2
diff -u -r2.2 Manual.py
--- Mailman/MTA/Manual.py	2001/09/04 15:09:56	2.2
+++ Mailman/MTA/Manual.py	2001/11/19 11:00:15
@@ -65,7 +65,7 @@
     msg = Message.UserNotification(
         siteowner, siteowner,
         _('Mailing list creation request for list %(listname)s'),
-        sfp.getvalue())
+        sfp.getvalue(), mlist.preferred_language)
     outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
     outq.enqueue(msg, recips=[siteowner])
 
@@ -108,6 +108,6 @@
     msg = Message.UserNotification(
         siteowner, siteowner,
         _('Mailing list removal request for list %(listname)s'),
-        sfp.getvalue())
+        sfp.getvalue(), mlist.preferred_language)
     outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
     outq.enqueue(msg, recips=[siteowner])
Index: bin/newlist
===================================================================
RCS file: /cvsroot/mailman/mailman/bin/newlist,v
retrieving revision 2.10
diff -u -r2.10 newlist
--- bin/newlist	2001/09/07 23:18:47	2.10
+++ bin/newlist	2001/11/19 11:00:15
@@ -179,7 +179,7 @@
         msg = Message.UserNotification(
             owner_mail, siteadmin,
             _('Your new mailing list: %(listname)s'),
-            text)
+            text, mlist.preferred_language)
         msg.send(mlist)
 
 

-- 
Ben Gertzfield                  $B%Y%s!&%,!<%D%U%#!<%k%I(B
Global Media Online INC.        $B%0%m%P%k%a%G%#%"%*%s%i%$%s3t<02q<R(B
System Division                 $B%7%9%F%`K\It(B
Sysadmin Team Programmer        $B%7%9%"%I%_%K%A!<%`%W%m%0%i%^!<(B