Python メールに添付されているファイル名のデコードで文字化け |
だったので、自動的に2.4でした
サーバーをlennyで再インストールしたのでPython2.5になったのですが、
どうもメールの解析プログラムで文字が化ける。
化けるというか、iso-2022-jpを上手く解析できない模様。
例えば、
20091201_議事録.zip
という名前の添付ファイルがついているメールを見てみると、
20091201_=?ISO-2022-JP?B?GyRCNUQ7dk8/GyhC?=.zip
こんな文字列にエンコードされています。
これをデコードするロジックは以下の通り。
from email.Header import decode_header
s = '20091201_=?ISO-2022-JP?B?GyRCNUQ7dk8/GyhC?=.zip'
out = u""
for f, c in decode_header(s):
if c:
out += f.decode(c)
else:
out += f
print out
decode_headerを実行すると、デコードが必要な部分とそうでない部分を切り分けてくれます。
ここで期待する動作は、
[('20091201_', None),
('=?ISO-2022-JP?B?GyRCNUQ7dk8/GyhC?=', 'iso-2022-jp'),
('.zip', None)]
こんな風なリストを返してもらうことです。
Python2.4ではこのように動作するのですが、2.5だと
[('20091201_=?ISO-2022-JP?B?GyRCNUQ7dk8/GyhC?=.zip', None)]
が帰ってきて、デコードに失敗します。
調べてみると・・・
decode_header does not follow RFC 2047
http://bugs.python.org/issue1079
これかー。
/usr/lib/python2.5/email/header.py
このファイルの40行目付近
(?P.*?) # non-greedy up to the next ?= is the encoded string
\?= # literal ?=
(?=[ \t]|$) # whitespace or the end of the string
''', re.VERBOSE | re.IGNORECASE | re.MULTILINE)
ここを以下のように修正したら、望みの動作になりました。
#(?P.*?) # non-greedy up to the next ?= is the encoded string
(?P[!->@-~]*?)
\?= # literal ?=
''', re.VERBOSE | re.IGNORECASE)
#(?=[ \t]|$) # whitespace or the end of the string
#''', re.VERBOSE | re.IGNORECASE | re.MULTILINE)
・・めっちゃハマりました。

