SpamAssassinのこと(2)
「Perlなら少しわかる」と書きましたが、実はモジュールとかオブジェクト指向的な書き方はよくわかりません。また、それまでSpamAssassinのソースをじっくり見たこともありませんでした。そんな私が取り組めたのは、John Myersさんの"charset normalization support"パッチでした。
日本語の電子メールは、一般的にはJISコード(iso-2022-jp)が使われています。しかしシフトJIS、UTF-8、まれにEUC-JPなどの文字セットを使ったメールもあり、スパムメールではかなりの頻度でシフトJISが使われています。しかも、件名(Subject)などのメールヘッダ部分はMIMEという特別なエンコードを行うことになっていますが、エンコードしていないもの、むちゃくちゃなエンコード(iso-2022-jpだよという宣言があって中身はシフトJISが使われているようなケース)もあります。
Johnさんのパッチは、こういったさまざまな文字セットとエンコーディングに対して正しく動作するものでした。ほとんどの日本語スパムはUTF-8という文字セットに変換され、SpamAssassin内部で統一的に扱えることがわかりました。これはいいものを発見したと思い、実際にいろいろテストしてみました。その結果、次のようなことがわかり、改善課題が見えてきました。
- 内容をチェックするためのルールを日本語で記述できる。これはとても便利。
- わかち書きを行わない限り、ベイズフィルタはうまく動かない。
SpamAssassinでは、メールの内容を吟味してスパムかどうかを判断するために、ヘッダや本文の内容のチェック、過去の判定経験にもとづいてスパムである確率を求めるベイズフィルタ、などの手法が使えます。
内容によって判断する場合、スパムによく出現する単語やフレーズをルールに記述します。従来はiso-2022-jp、シフトJISなどの文字コードごとのルールを書かなければならず、しかも16進表現で書かなければならないなど、大きな制約がありました。ルールを書くのに手間がかかり、ルールの数も増えてしまうのでは、普及の妨げになります。これが、Johnさんのパッチをベースにすると、UTF-8コードを使う必要がありますが、日本語で直接書けるようになり、生産性が大幅に高まります。
ベイズフィルタは、メール中の単語ごとにスパムでの出現頻度を数値化し、これをデータベースに格納します。したがってメールを単語に分割しなければなりません。欧米の言語はスペースや記号で単語が区切られていますが、日本語はKakasi、MeCabなどのわかち書きプログラムを使って単語に区切るのがもっともよさそうです。
ちなみに、Johnさんのパッチを使わない状態では、日本語メールに対してもテキスト中の1バイト記号文字などで機械的に分割されるようなロジックになっています。文字や単語は考慮されていません。その結果、ベイズデータベースは、まったく無意味とまではいえないものの、かなりノイズの多いものになっています。
これらを考慮して、Kakasiによるわかち書きを行うなど、Johnさんのパッチに手を加えたパッチを作り、スパムメールならびにスパムでないメール(「正規メール」と呼ぶことにします)に対してさまざまなテストを行いました。
(つづく)