メッセージのMD5を保存しておいて、複数来たやつは省くスクリプト。

ヽ( ・∀・)ノくまくまー(2006-03-31) - 舞波デコヒーレンスの話ね。

qmailだと.qmailにこんなのを入れておいて、

/var/qmail/bin/condredirect spam@example.com /var/qmail/alias/filter/message_md5.pl

下にあるスクリプト(message_md5.pl)を動かす。

とりあえず、これで複数のアドレスに来るspamをある程度減らせる。

もし、最初の2通も含めて処理したい*1のであれば、
適当なMaildirに一旦格納して、10分間隔くらいでfetchmailして、
転送先のアドレスに関する.qmail

/var/qmail/bin/condredirect spam@example.com /var/qmail/alias/filter/message_md5.pl checkonly

すればだいたい排除できるんでないかな?

#!/usr/bin/perl

#init
use strict;
use Digest::MD5;
use MIME::Parser;
my $dir = '/var/qmail/alias/filter/'; #ログ等の保存先
my $maxcount = 2; #しきい値
my $file ="haches.in";	#ログファイル
my $blacklistfile = "haches.bl";	#ブラックリスト

#parse mail
my $parse = MIME::Parser->new;
$parse->output_under("/tmp");
my $entity= $parse->parse(\*STDIN);

#make MD5
my $md5= Digest::MD5->new;
my $hash = $md5->add(join("",@{$entity->body}))->hexdigest;
my $from = $entity->head->get('From');
$from =~ s/\n//g;
$from =~ s/\t//g;
$parse->filer->purge;
rmdir($parse->output_dir);

#check blacklist
if(open(FILE,$dir.$blacklistfile))
{
    while(my $line=<FILE>)
    {
        chomp($line);
        my ($last_from,$last_hash) = split(/\t/,$line);
        if($last_hash eq $hash)
        {
            print "found in blacklist\n";
            close(FILE);
            exit(0);
        }
    }
    close(FILE);
}
exit(-1) if($ARGV[0] eq 'checkonly');

# check email-count;
my $count = 1;
if(open(FILE,$dir.$file))
{
    while(my $line=<FILE>)

    {
        chomp($line);
        my ($last_from,$last_hash) = split(/\t/,$line);
        if($last_hash eq $hash)
        {
            $count++;
        }
        if($count > $maxcount)
        {
            if(open(OUT,">>".$dir.$blacklistfile))
            {
                print OUT $from."\t".$hash."\n";
                close(OUT);
                close(FILE);
                print "seen over $maxcount\n";
                exit(0);
            }
            last;
        }
    }
    close(FILE);
}

# write log
if(open(FILE,">>".$dir.$file))
{
    print FILE $from."\t".$hash."\n";
    close(FILE);
}
exit(-1);

perl詳しくないので、もっと奇麗な書き方とか
モジュール使わないやり方とかあったらフォローしてもらえると。

*1:自分はやったことないけど