SPAM撃退用PHPスクリプト - Eternity blog 旅行+英語+α

SPAM撃退用PHPスクリプト

2011年11月13日

最近SPAMが増えてきましたので、流行のVPSを使って1分おきにSPAM削除するPHPスクリプトを組んでみました。
サーバによってはSPAM拒否設定があったりしますが、詳細な設定ができない場合が多いので自分でフィルタできるとかなり便利です。

使ったのは

  • さくらのVPS

さて、借りてから基本的な設定をします。PHPのIMAPを使いたいのでそれらをインストールします。
上記の他にFTPやらセキュリティやらアカウントやら設定してますが、それらは割愛。

【メモ】PHPインストールは以下
yum -y install php
yum -y install php-devel php-mbstring php-pear php-gd php-xml php-imap

動きとしては、文字列の部分一致あるいは正規表現による一致で削除することにします。
設定ファイルの1行が設定ひとつとします。行の最初と最後が / であれば正規表現、そうでなければ部分一致とします。

作業用ユーザを作った後、そのホームフォルダに作業用フォルダを作ることにします。
ここでは /home/YourAccountName/spam_buster とします。

その下に以下のファイルを置いて設定にします。
spam_setting_of_subject.txt
spam_setting_of_from.txt
spam_setting_of_body.txt

この中に、「ほげほげ」と書けば文字列部分一致、「/せいきひょうげん/」と書けば正規表現として解釈されるようにします。
IMAPに何度も何度もアクセスすると多少は負荷がかかりますので、
1時間の間はチェック内容をキャッシュして、新規のメールだけチェックするようにします。
1時間ごとに全部チェックし直します。
よって、59分経ったらプロセスを終了し、1時間おきに新規プロセスを(cronで)起動させるようにします。

IMAP関数は以下のようにアクセス

$MAIL_HOST = "pop3.hogehoge.jp"; // 環境に合わせて適宜変更
$MAIL_USER = "username"; // 環境に合わせて適宜変更
$MAIL_PASS = "password"; // 環境に合わせて適宜変更
$mbox = imap_open("{" . $MAIL_HOST . ":110/pop3}INBOX", $MAIL_USER, $MAIL_PASS);

$mboxes = imap_check($mbox);
$overview_list = imap_fetch_overview($mbox,"1:{$mboxes->Nmsgs}",0);

これでメール一覧が取れたので、必要に応じてメールヘッダおよびボディ部分を取得してチェックします。
全部チェックすると負荷がかかるので、メッセージIDでチェック済かどうか確認し、新規のメールのみ詳細を確認します。

また、メールのBODYはMIMEエンコードされていたりしますのでデコードします。
階層は何階層でもいくらでも行くような作りなので、きちんとやるのであれば再帰的にすべてデコードすべきなのかもしれませんが、SPAM業者としては添付ファイルの中にいろいろ書いてもメリットがないと思われますので第一階層(とでも言うのかな)のBODYだけ解釈させています。これで十分。バイナリはチェック不要なので分岐させるべきなのかもしれませんが、ひとまず省略。
テストはコマンドライン上から
php -q spam_buster.php
などと打ってテストします。

テストOKであれば、定期的に実行させるためにcron登録をします。 /etc/crontab 編集して、以下の行を追加します。
08 * * * * YourAccountName /usr/bin/php /home/YourAccountName/spam_buster/spam_buster.php >> /home/YourAccountName/spam_buster/spam_buster.log

これで動作ログが残りますので、メールが届いていないようであればログをチェックできます。
※このままだとログはローテーションしないので、ファイルサイズの肥大に注意です。

ソースファイルはこちら: spam_buster.zip

文字コードはUTF-8にしていますので、うまく動かない場合は文字コードを怪しんで下さい。
POP3で外からチェック&削除していますので、タイミング悪く先にメーラーで読んでしまうとSPAMメールが入ってきてしまうのが難点です。

よもやま話:
私の場合、PCはメール保管用に使っており、普段はAndroid端末でメールチェックしています。PCでは「2日分サーバに残す」設定にしておいて、AndroidではK9というメーラーを使って、サーバとメールを同期してサーバ上にあるメールだけ表示するようにしてあります。こうすることで、PCにはまれにSPAMメールが紛れ込みますが、Android端末では問題になりません。たとえタイミング悪くSPAMが紛れ込んでも、すぐにサーバから消えるのでAndroid上からも自動的に消えます。

続き (2/Dec/2011)

上記だけでは新規設定時にいちいち設定ファイルをアップロードしなくてはいけないので、設定用メアドに送ったら設定を追加/削除/確認できるようにした。
こうすることで、以下のシナリオが可能

  1. SPAMメール受信
  2. SPAMメールを設定用メアドに転送すると、フィルタ候補を自動的に判別した後にフィルタ追加確認メールが返信される。(候補は、メールアドレスとURLの先頭部分(「?」以降は変わりやすいのでSPAMフィルタとして不適切と判断してばっさりと切り捨てている)
  3. フィルタを確認し、フィルタ追加するものに対してそのまま返信するとフィルタ追加される。2番の自動認識によっては通常メールもフィルタされてしまうようになるのでこの確認は確実にする。
  4. 確認メールが届く。本文にはフィルタ一覧が含まれているので、フィルタしたくないパターンが含まれていないか確認する。

識別はメールタイトルで行う。
特定の文字列、例としては「ADD: ほげほげ」とすると「ほげほげ」がフィルタに追加される。
同様のことを、追加/削除に対して行う。削除は、例としては「DELETE: 行番号」とする。行番号は確認メール中に記載してあるのでその番号を入力する。
同パターンに一致しない場合は本文からフィルタ候補を探し出して、フィルタ追加候補(確認)メールを送信する。

上記を45秒おきに実行し、59分実行したら終了、1時間おきに新しいプロセスを起動します。
よって、上と同様にcron登録が必要です。
添付ファイルには含まれていないが、実際には、自分のメアドは自動識別して欲しくないので、添付のソースファイルに加えて、そういった排他処理も入れてある。

ソースファイルはこちら:spam_setting_manager.zip


このために、昔作った「削除用スクリプト」にも若干手を加えた。(こちらのソース提示はなし)

  1. 設定ファイルを毎回読み込むのではなく、スクリプト起動時に一回だけ読み込んで、1時間ループ中はその設定で動作する。
    こうすることで、「確認メール」がSPAM設定とマッチして即座に削除されてしまうことを防ぐ。
  2. 追加フィルタ用ファイルを読み込んでチェックする処理追加

さくらVPNは試用中はメール送信できないようなので本使用後に試した。
尚、さくらVPNのsendmail設定のLOCAL_HOST設定も若干修正したが、省略。

追記:
SPAM設定メールの本文にSPAM設定一覧を貼り付けておくと、それ自体がSPAMパターンと一致してしまってすぐに消されてしまうので、上に添付のソースファイルに加えて、10分間は消さないような遅延を追加。その後、HTMLファイルにてきちんと認識できなかった場合があったのでちょっと変更。www.w3.orgや自分のドメインなど、ホワイトリスト的なものを作ってそれは候補としないようにも変更