Pythonでの日本語メールはUTF-8がベストかも

 Study Mailの開発で日本語メールの問題にぶつかりましたので、その解決方法を公開します。結論としては、Pythonの場合はUTF-8エンコードしてしまうのがベストのようです。

Dajngo EmailMessageで文字コードを指定する

 よく知られているように、日本語で書かれたメールを送信する場合はiso2022でエンコードするのが一般的です。二バイト文字のエンコードに問題の多いことで知られるPythonですが、幸いエンコードそのものについては部品として切り出して使えるwebアプリケーションフレームワークDjangoを利用することで問題なく行うことができます。
 Djangoには電子メールのメッセージを表現するEmailMessageクラスがあり、メールとしてのメッセージの組み立てを簡易化してくれます。文字コードについてもドキュメント化こそされていませんがソースを読むとencodingというメンバ変数があり、そこで指定できることがわかります。
 Django1.2以降におけるもっとも単純な日本語メールの送信方法は以下のようになります。

from django.core.mail import EmailMessage,get_connection

email = EmailMessage(subject, message, from_email ,to = recipient_list)
email.encoding = 'iso-2022-jp'
connection = get_connection(backend = 'django.core.mail.backends.smtp.EmailBackend' ,host = {ホスト},port = 25, username = {smtpのユーザー名},password = {パスワード})
connection.open()
connection.send_messages([email])

 ここで問題となるのはエンコードに使う文字コードです。Pythonの場合はエンコードできない場合は送信できないので、実際のところは単純にiso2022では対応できません。

UTF-8を最初から使うという選択肢

 元の入力がUTF-8の場合、iso2022では以下の文字に対応していません。

  1. 〜(波線)
  2. ノーブレークスペースをはじめとするUTF-8特有の空白文字
  3. 半角カナ
  4. 「はしご高」等のIBM拡張文字列

 このうち、前の二つまでは比較的単純な文字列置換で対応できます。

body = body.replace(u'\uff5e', u'\u301c').replace(u'\xa0',u'').replace(u'\u2028',u'').replace(u'\u2029',u'')

 また半角カナについては拡張iso2022で対応可能です。
ただし最後のIBM拡張文字列に対しては大規模な対応テーブルを作成する必要があり、非常に手間がかかります。さらには最近のスマートフォンのメールクライアントには拡張iso2022に対応していないものがあります。このことに気がついたのは私の使用しているAndroid携帯のデフォルトメーラーがきっかけでしたので、現状では全てのAndroidのデフォルトメーラーで拡張iso2022が表示できない可能性があります。
 将来的にいわゆるガラケーは退場してスマートフォンが主流になっていくことを考えると、現実的には最初からUTF-8で送信してしまうのが確実でシンプルでしょう。