2007/06/30

trac通知メールのJIS(ISO2022JP)化

tracの通知機能はUTF-8 + Base64でメールを送るんだけど、古いメーラーで読めなかったり、SPAMと判別されやすかったりするらしいので、JIS化。
ここにあったパッチではうまくいかなかった(デフォルトエンコーディングがUTF-8だからかな)ので、自作。
なかなかうまくいかなくて、ものすごく強引なコーディングになってますが、今のところ正常に動いてます。今見るともっと効率的にかける部分もあるので、も一回見直さないといけないかも。

trac 0.10.4-ja-1向けです。自己責任でどうぞ。

--- notification.py.orig 2006-12-09 19:06:16.000000000 +0900
+++ notification.py 2007-06-29 17:50:38.000000000 +0900
@@ -172,7 +172,13 @@
self._charset = Charset()
self._charset.input_charset = 'utf-8'
pref = self.env.config.get('notification', 'mime_encoding').lower()
- if pref == 'base64':
+ if pref == 'iso-2022-jp':
+ self._charset.header_encoding = BASE64
+ self._charset.body_encoding = None
+ self._charset.output_charset = 'iso-2022-jp'
+ self._charset.input_codec = 'utf-8'
+ self._charset.output_codec = 'iso-2022-jp'
+ elif pref == 'base64':
self._charset.header_encoding = BASE64
self._charset.body_encoding = BASE64
self._charset.output_charset = 'utf-8'
@@ -289,6 +295,7 @@
def send(self, torcpts, ccrcpts, mime_headers={}):
from email.MIMEText import MIMEText
from email.Utils import formatdate, formataddr
+ from email import base64MIME
body = self.hdf.render(self.template_name)
projname = self.config.get('project', 'name')
public_cc = self.config.getbool('notification', 'use_public_cc')
@@ -297,7 +304,7 @@
headers['X-Trac-Version'] = __version__
headers['X-Trac-Project'] = projname
headers['X-URL'] = self.config.get('project', 'url')
- headers['Subject'] = self.subject
+ headers['Subject'] = base64MIME.header_encode(self.subject.encode('iso-2022-jp'), 'iso-2022-jp', maxlinelen=1024)
headers['From'] = (projname, self.from_email)
headers['Sender'] = self.from_email
headers['Reply-To'] = self.replyto_email
@@ -345,7 +352,10 @@
headers['Cc'] = ', '.join(pcc)
headers['Date'] = formatdate()
# sanity check
- if not self._charset.body_encoding:
+ if self._charset.output_charset == 'iso-2022-jp':
+ body = unicode(body, 'utf-8').replace(u'\uff5e', u'\u301c')
+ body = body.encode('utf-8')
+ elif not self._charset.body_encoding:
try:
dummy = body.encode('ascii')
except UnicodeDecodeError: