Skip to content

Commit d48cf95

Browse files
author
Richard Jones
committed
email charset fixes
1 parent 8fcd40e commit d48cf95

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

doc/upgrading.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ Removed Database.curuserid attribute. Any code referencing this attribute
3131
should be replaced with a call to Database.getuid().
3232

3333

34+
0.7.0 Email character set
35+
-------------------------
36+
37+
The default character set for sending email is UTF-8 (ie. Unicode). If you
38+
have users whose email clients can't handle UTF-8 (eg. Eudora) then you
39+
will need to edit the new config.py variable ``EMAIL_CHARSET``.
40+
41+
3442
0.7.0 ZRoundup changes
3543
----------------------
3644

roundup/mailer.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Sending Roundup-specific mail over SMTP.
22
"""
33
__docformat__ = 'restructuredtext'
4-
# $Id: mailer.py,v 1.6 2004-02-23 05:29:05 richard Exp $
4+
# $Id: mailer.py,v 1.7 2004-02-29 00:35:55 richard Exp $
55

66
import time, quopri, os, socket, smtplib, re
77

@@ -24,20 +24,41 @@ def __init__(self, config):
2424
self.debug = os.environ.get('SENDMAILDEBUG', '')
2525

2626
def get_standard_message(self, to, subject, author=None):
27+
'''Form a standard email message from Roundup.
28+
29+
"to" - recipients list
30+
"subject" - Subject
31+
"author" - (name, address) tuple or None for admin email
32+
33+
Subject and author are encoded using the EMAIL_CHARSET from the
34+
config (default UTF-8).
35+
36+
Returns a Message object and body part writer.
37+
'''
38+
# encode header values if they need to be
39+
charset = getattr(self.config, 'EMAIL_CHARSET', 'utf-8')
40+
tracker_name = self.config.TRACKER_NAME
41+
if charset != 'utf-8':
42+
tracker = unicode(tracker_name, 'utf-8').encode(charset)
2743
if not author:
28-
author = straddr((self.config.TRACKER_NAME,
29-
self.config.ADMIN_EMAIL))
44+
author = straddr((tracker_name, self.config.ADMIN_EMAIL))
45+
else:
46+
name = author[0]
47+
if charset != 'utf-8':
48+
name = unicode(name, 'utf-8').encode(charset)
49+
author = straddr((encode_header(name, charset), author[1]))
50+
3051
message = StringIO()
3152
writer = MimeWriter(message)
32-
writer.addheader('Subject', encode_header(subject,
33-
self.config.EMAIL_CHARSET))
53+
writer.addheader('Subject', encode_header(subject, charset))
3454
writer.addheader('To', ', '.join(to))
3555
writer.addheader('From', author)
3656
writer.addheader('Date', time.strftime("%a, %d %b %Y %H:%M:%S +0000",
3757
time.gmtime()))
3858

3959
# Add a unique Roundup header to help filtering
40-
writer.addheader('X-Roundup-Name', self.config.TRACKER_NAME)
60+
writer.addheader('X-Roundup-Name', encode_header(tracker_name,
61+
charset))
4162
# and another one to avoid loops
4263
writer.addheader('X-Roundup-Loop', 'hello')
4364
# finally, an aid to debugging problems
@@ -54,7 +75,7 @@ def standard_message(self, to, subject, content, author=None):
5475
- to: a list of addresses usable by rfc822.parseaddr().
5576
- subject: the subject as a string.
5677
- content: the body of the message as a string.
57-
- author: the sender as a string, suitable for a 'From:' header.
78+
- author: the sender as a (name, address) tuple
5879
"""
5980
message, writer = self.get_standard_message(to, subject, author)
6081

roundup/roundupdb.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: roundupdb.py,v 1.98 2004-02-23 05:29:05 richard Exp $
18+
# $Id: roundupdb.py,v 1.99 2004-02-29 00:35:55 richard Exp $
1919

2020
"""Extending hyperdb with types specific to issue-tracking.
2121
"""
@@ -207,10 +207,11 @@ def send_message(self, nodeid, msgid, note, sendto, from_address=None):
207207
self.db.config.MAIL_DOMAIN)
208208
messages.set(msgid, messageid=messageid)
209209

210-
# send an email to the people who missed out
210+
# compose title
211211
cn = self.classname
212212
title = self.get(nodeid, 'title') or '%s message copy'%cn
213213

214+
# figure author information
214215
authid = messages.safeget(msgid, 'author')
215216
authname = users.safeget(authid, 'realname')
216217
if not authname:
@@ -248,7 +249,11 @@ def send_message(self, nodeid, msgid, note, sendto, from_address=None):
248249
m.append(self.email_signature(nodeid, msgid))
249250

250251
# encode the content as quoted-printable
251-
content = cStringIO.StringIO('\n'.join(m))
252+
charset = getattr(self.db.config, 'EMAIL_CHARSET', 'utf-8')
253+
m = '\n'.join(m)
254+
if charset != 'utf-8':
255+
m = unicode(m, 'utf-8').encode(charset)
256+
content = cStringIO.StringIO(m)
252257
content_encoded = cStringIO.StringIO()
253258
quopri.encode(content, content_encoded, 0)
254259
content_encoded = content_encoded.getvalue()
@@ -268,18 +273,21 @@ def send_message(self, nodeid, msgid, note, sendto, from_address=None):
268273
if from_tag:
269274
from_tag = ' ' + from_tag
270275

271-
subject = '[%s%s] %s' % (cn, nodeid, encode_header(title,
272-
self.db.config.EMAIL_CHARSET))
273-
author = straddr((encode_header(authname, self.db.config.EMAIL_CHARSET)
274-
+ from_tag, from_address))
276+
subject = '[%s%s] %s'%(cn, nodeid, title)
277+
author = (authname + from_tag, from_address)
275278

276279
# create the message
277280
mailer = Mailer(self.db.config)
278281
message, writer = mailer.get_standard_message(sendto, subject, author)
279282

280-
tracker_name = encode_header(self.db.config.TRACKER_NAME,
281-
self.db.config.EMAIL_CHARSET)
283+
# set reply-to to the tracker
284+
tracker_name = self.db.config.TRACKER_NAME
285+
if charset != 'utf-8':
286+
tracker = unicode(tracker_name, 'utf-8').encode(charset)
287+
tracker_name = encode_header(tracker_name, charset)
282288
writer.addheader('Reply-To', straddr((tracker_name, from_address)))
289+
290+
# message ids
283291
if messageid:
284292
writer.addheader('Message-Id', messageid)
285293
if inreplyto:
@@ -290,7 +298,7 @@ def send_message(self, nodeid, msgid, note, sendto, from_address=None):
290298
part = writer.startmultipartbody('mixed')
291299
part = writer.nextpart()
292300
part.addheader('Content-Transfer-Encoding', 'quoted-printable')
293-
body = part.startbody('text/plain; charset=utf-8')
301+
body = part.startbody('text/plain; charset=%s'%charset)
294302
body.write(content_encoded)
295303
for fileid in message_files:
296304
name = files.get(fileid, 'name')
@@ -318,7 +326,7 @@ def send_message(self, nodeid, msgid, note, sendto, from_address=None):
318326
writer.lastpart()
319327
else:
320328
writer.addheader('Content-Transfer-Encoding', 'quoted-printable')
321-
body = writer.startbody('text/plain; charset=utf-8')
329+
body = writer.startbody('text/plain; charset=%s'%charset)
322330
body.write(content_encoded)
323331

324332
mailer.smtp_send(sendto, message)

0 commit comments

Comments
 (0)