メーリングリストサーバを Debian GNU/Linux Wheezy から Jessie にアップデートしたところ、メールが配送されなくなるトラブルに遭遇しました。/var/log/mailman/error を見ると以下のようなエラーが記録されていました。
Jun 10 03:37:40 2017 (159) Uncaught runner exception: 'utf8' codec can't decode byte 0xa5 in position 0: invalid start byte
Jun 10 03:37:40 2017 (159) Traceback (most recent call last):
File "/var/lib/mailman/Mailman/Queue/Runner.py", line 119, in _oneloop
self._onefile(msg, msgdata)
File "/var/lib/mailman/Mailman/Queue/Runner.py", line 190, in _onefile
keepqueued = self._dispose(mlist, msg, msgdata)
File "/var/lib/mailman/Mailman/Queue/IncomingRunner.py", line 130, in _dispose
more = self._dopipeline(mlist, msg, msgdata, pipeline)
File "/var/lib/mailman/Mailman/Queue/IncomingRunner.py", line 153, in _dopipeline
sys.modules[modname].process(mlist, msg, msgdata)
File "/var/lib/mailman/Mailman/Handlers/CookHeaders.py", line 179, in process
i18ndesc = uheader(mlist, mlist.description, 'Reply-To')
File "/var/lib/mailman/Mailman/Handlers/CookHeaders.py", line 65, in uheader
return Header(s, charset, maxlinelen, header_name, continuation_ws)
File "/usr/lib/python2.7/email/header.py", line 183, in __init__
self.append(s, charset, errors)
File "/usr/lib/python2.7/email/header.py", line 267, in append
ustr = unicode(s, incodec, errors)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa5 in position 0: invalid start byte
Jun 10 03:37:40 2017 (159) SHUNTING: 1497033451.22806+bcf182d45533b69b6003c0fb62a3ae3e89350e50
どうやら、http://blog.n-z.jp/blog/2016-04-30-mailman-error.html と同じトラブルで,メーリングリストの解説などの日本語文字列が正しく保存されていないことが原因のようです。上記ページでは、ウェブインタフェースから人手再設定するという手順が紹介されていましたが、私の場合、管理下のメーリングリストが多数になるため人手再設定は現実的ではありません。
最初に、エラーになっているバイト列が、もともとは何の文字コードで格納されていたのかを検討しました。
$ sudo -u list /usr/lib/mailman/bin/withlist testlist
Loading list testlist (unlocked)
The variable `m' is the testlist MailList instance
>>> m.description
'\xa5\xc6\xa5\xb9\xa5\xc8\xcd\xd1'
>>> m.description.decode('euc-jp')
u'\u30c6\u30b9\u30c8\u7528'
>>> m.description.decode('euc-jp').encode('utf-8')
'\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88\xe7\x94\xa8'
>>> sys.stdout.write(m.description.decode('euc-jp').encode('utf-8'))
テスト用
適当に当てずっぽうで EUC-JP なのでは?と考えたら、正解でした。
後は、修正を、全メーリングリストに一括適用する方法があれば良いわけです。
最初に、実際に修正を行うスクリプト /usr/lib/mailman/bin/fix_desc.py を用意します。
def fix_desc(mlist):
mlist.Lock()
try:
desc = mlist.description.decode('euc-jp').encode('utf-8')
info = mlist.info.decode('euc-jp').encode('utf-8')
mlist.description = desc
mlist.info = info
except UnicodeDecodeError:
print("Not encoded in EUC-JP. Ignored.")
mlist.Save()
なお、修正スクリプトの設置場所が重要で、適当な別ディレクトリに配置しても withlist コマンドは見つけてくれません。withlist コマンドと同じディレクトリに配置する必要があります。
次に、withlist コマンドを経由して、上記の修正スクリプトを全メーリングリストに一括適用します。
$ sudo -u list /usr/lib/mailman/bin/withlist -r fix_desc -a
以下のようにメーリングリスト名を指定して、特定のメーリングリストだけを対象として適用することもできます。
$ sudo -u list /usr/lib/mailman/bin/withlist -r fix_desc LISTNAME
2022年8月28日追記
Busterに同梱されているMailmanでは,再びEUC-JPに戻っているらしい.そのため,以下のようにEUC-JPに戻すスクリプトの適用が必要となる.
def fix_desc(mlist):
mlist.Lock()
try:
desc = mlist.description.decode('utf-8').encode('euc-jp')
info = mlist.info.decode('utf-8').encode('euc-jp')
mlist.description = desc
mlist.info = info
except UnicodeDecodeError:
print("Not encoded in EUC-JP. Ignored.")
mlist.Save()