dovecotのantispamプラグインで迷惑メールフィルタの学習をコントロールする

先日のトラブルでIMAP環境の組み直しになった。それ自体はたいした話ではない。パッケージをいれてデータを戻すだけ。

悩ましいのは迷惑メールの処理。MUAでの判定でも十分ではあるのだが、複数のマシンで読み書きするのでちょっとめんどくさい。トラブル以前は自作ツールをぐるぐるまわしてbsfilterで処理していたのだが、再び自作ツールをぐるぐるまわす気にはなれない。かといってまともにdaemon化するなどさらにいじる元気もない。sieveでなんとかできないものかと思ったけども、やはり振り分けくらいにしか使えないようで、この手の目的には向かない。

antispamプラグイン

そういえばdovecotにプラグインがあったのだったっけ。探してみたらそれらしいプラグインが見付かった。dovecot antispamという。

これ自体で迷惑メールの判定を行うものではなく、外部の迷惑メールフィルタの学習をコントロールするためのものだ。特定のフォルダを使って迷惑メールフィルタの学習をコントロールしようとする。つまり、MUAからのフォルダ操作で学習させることができる。自作スクリプトでやっていたのと考え方は同じ。debパッケージもあるようだ――がdebは使えなかった。

dovecot本体とプラグインとのバージョン整合性が行われていて、dovecot-antispam.debは古いdovecotでbuildされている。それがバレてはねられる。うーん、と、ちょっと迷ったが、rebuildして試してみることにした。

antispamの動作

説明からは動きがいまひとつわからず、かつ、実際に動かしてみもよくわからなかったのだが、上のrebuildのついでにdebugログを出力するようにして試してみるとわかってきた。

  • コマンドを起動して学習させるのにはantispam_mail_sendmailを使う。もともとantispam_mail_sendmailは迷惑メールと判定されたかどうかに応じてメールを転送するものだったようだが、内部では指定されたコマンドにメール本文を与えて実行しているだけ。したがって任意のコマンド(sa-learnやbsfilterなど)を実行できる。
  • 注目するフォルダはantispam_trashとantispam_spamで指定する二種類。それぞれゴミ箱と迷惑メール箱をの名前を指定する。
  • ゴミ箱との間でのメールの移動は無視される。
  • ゴミ箱以外と迷惑メール箱の間のメールの移動があると、その方向に応じた引数を指定してコマンド実行される(antispam_mail_sendmailの場合)。
    • どこか→迷惑メール箱 - そのメールを迷惑メールとして学習させるためantispam_mail_spamで指定したオプションを付けてコマンドが実行される
    • 迷惑メール箱→どこか - 迷惑メールでないとして学習させてためantispam_mail_notspamで指定したオプションを付けてコマンドが実行される

設定方法

antispamプラグインはIMAPのためのプラグインである。利用するには以下のような設定にする。

protocol imap {
  ...
  mail_plugins = antispam ...
  ...
}

プラグイン自体の設定は以下のようにpluginブロックでする。

plugin {
  ...
  antispam_trash = Trash
  antispam_spam = Junk
  antispam_mail_sendmail = /usr/bin/sa-learn
  antispam_mail_spam = --spam
  antispam_mail_notspam = --ham
  ...
}

dovecotを起動して、IMAPでアクセスし、迷惑メール箱とのやり取りをさせるとコマンドが実行されるはずだ。

なお、MUAの設定で迷惑メールを迷惑メール箱送りにする設定にしている場合、いきなり多数のメールがantispam処理にまわってしまうことがあるので注意が必要だ。そのあたりの設定をいったん止めて、あまり影響が出ないようにしてから動作確認したほうがよいだろう。

ただ、ちょっと気掛かりな点がある

だいたいのところ思った通りに動いているのだが、たまにsa-learnが終了値9で終了してしまい、何やらおかしなことになる場合があった。エラー出力などとっていなかったので簡単なwrapperを書いてみたりしたのだが、それから現象が起きなくなってしまった。

検索すると同じ現象がよそでも起きてはいるようなのだけど、結論が出ていないような感じである。(きちんと見ていない。)