HOME 備忘録 書き込む

Android 端末でのメールの文字化けを防ぐ


Mar 21, 2011

紫藤は、自宅サーバーにあるメールを IMAP で読んでいます。こうするといろいろな端末でメールを読むことができるので大変便利です。

Android 端末で自宅メールサーバのメールを読むとき、メールのヘッダが文字化けして困っていたのですが、 その原因がわかったので対処しておきました。
原因は、日本語のメールのなかには、ヘッダが、MIME 規格に準じていないものがあるということと、 Android 端末では、MIME 規格に沿ったメールしか正しく表示しないと言うことです。 普通の日本のメーラーでは、MIME 規格に沿っていないメールも正しく表示してくれましたが、 Android 端末では、規格に合っていないものは正しく表示されません。

日本語のメールには、ISO-2022-JP でエンコードした日本語を直接ヘッダに書いたものもあります。
例えば、

Subject: (ISO-2022-JP でエンコードした日本語)
です。
普通の日本のメーラーはこれを正しく表示してくれましたが、Android 端末ではこれでは文字化けします。
正しく表示させるためには、次の様に、MIME format に変換する必要があります。
Subject: =?ISO-2022-JP?B?GyRCOGZDbUo4JCIkaiQsJEgkJiQ0JDYkJCReJDkbKEI=?=
なお、MIME 形式のメールヘッダは、ほとんどのメーラーで正しく表示されるので、Android 端末用に変換すると 普通のメーラーで読めなくなるということは起こりません。 メールヘッダの MIME format については MIME(Multipurpose Internet Mail Extensions)〜後編 などを見てください。

この問題を解消するため、次のようなスクリプト (format_header.py) を書き、 maildrop で処理しました。

[format_header.py]

#! /usr/local/bin/python
# coding:utf-8
u"""
ISO-2022-JP で書かれたメールヘッダを MIME フォーマットに変換するスクリプト
"""

from base64 import b64encode
import sys, re

def conv_b64(s0):
    u"""s0 を MIME format に変換 """
    return "=?ISO-2022-JP?B?%s?=" % b64encode(s0)


def format_header(s0):
    u"""ISO-2022-JP で書かれたヘッダのメールを MIME format に変換"""
    # ISO-2022-JP での日本語の正規表現。
    # 日本語は、[ESC](J, [ESC]$@, [ESC]$B で始まり、[ESC](B で終わる
    re_jp = re.compile(r'\033(\(J|\$\@|\$B).+?(\033\(B|$)', re.M)

    # 文字列全体を空白行で分ける。(前半がヘッダ、後半が本文)
    re_sp = re.compile(r'\A(.+?)(?=^$)(.*)\Z', re.M | re.S)

    def f_jp(mobj):
        u"""マッチした文字列を MIME format にする"""
        return conv_b64(mobj.group(0))

    mobj= re_sp.match(s0)
    if mobj:
        return re_jp.sub(f_jp, mobj.group(1)) + mobj.group(2)
    else:
        return re_jp.sub(f_jp, s0)
    


if __name__ == '__main__':
    sys.stdout.write(format_header(sys.stdin.read())) 
以下は .mailfilter (maildrop の設定ファイル) の例です。kakasi, bogofilter と併用しています。
bogofilter をつかったスパムメールのフィルタリングは ここ などを参照してください。

[.mailfilter]

MAILDIR="/home/takafumi/Maildir/"
DEFAULT=$MAILDIR
WAKATI="/usr/local/bin/kakasi -w"
BOGOFILTER="/usr/local/bin/bogofilter"
BOGOFILTER_OPTION="-u -e -p"
FORMAT_HEADER="/home/me/bin/format_header.py"
BOGOJP="${FORMAT_HEADER} | ${WAKATI} | ${BOGOFILTER} ${BOGOFILTER_OPTION}"
SENDMAIL="/usr/sbin/sendmail"

xfilter "${BOGOJP}"
...
(以下省略)
これで Android 端末で自宅メールを見るとき文字化けしなくなり、大変快適になりました。