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 ベン・ガーツフィールド
Global Media Online INC. グロバルメディアオンライン株式会社
System Division システム本部
Sysadmin Team Programmer シスアドミニチームプログラマー