これは、寝込んでいたあいだに送られてきた迷惑メールの多さに頭に来た筆者が、財団法人日本データ通信協会迷惑メール相談センターへの自動報告のために記述したPerlスクリプトのメモ。
寝込んでたんですよ。で、やっと回復してメール見たら…送ってきた奴ら、必ず痛い目見させてやる。
平成20年12月1日
特定商取引法改正に伴い、従来の mailagain@nissankyo.jp より spam-in@nissankyo.jp に変更となりました。
公の機関で迷惑メールの報告を行えるところが2箇所あります。
日本データ通信協会の方は、報告に際して問題のメールを添付の形式で一括送信OKのようです。
日本産業協会の方は、転送しろ、としか書かれていないので基本、一件ずつの報告になるようです。
一つずつ手で処理してられないので、添付メールを生成するスクリプトを書くことにしました。
うちの場合、メールはすべて FreeBSDのサーバ機でさばいています。ですのでPerlのスクリプトを書いて処理させるのが楽であろうと判断。
で、ちょっとWebを見ると、MIME-tools を使った例をたくさん見ることができたのでこれを使うことにしました。
portsで p5-MIME-tools をさっくり導入。
Perlのバージョンは 5.8.8。
所要時間は、調べものをして約2時間です。…あ、手作業で送ったほうが早かったんじゃない?とおっしゃる方、後で
スクリプトにした旨みを説明しますよ。
Perl5.8.8であれば多国語対応しているので、昔のようにJcode.plやら何やらをそろえる必要が無いねー、とか考えていたら。
やっぱり色々ありました。以下のリンクを見て何とか解決。感謝。
何に嵌ったかというと、EUC→JISへの変換です。
ちょっと癖があるというか。
ちゃんと理解していないとまったく訳が分からない現象に悩まされることになります。
まずは日本データ通信協会へは一括添付の形式でメールを送ることにしました。
#!/usr/bin/perl
use Encode;
use MIME::Entity;
use MIME::Words qw (:all);
my $maildir = "$ENV{HOME}/Maildir/.WORK.TEIKYO/cur";
my $from = 'hogehoge@hogehoge.jp';
my $to = 'meiwaku@dekyo.or.jp';
my $Subject = "表示義務に違反するメールがありましたので、情報提供いたします";
my $messageText = "財団法人 日本データ通信協会"."\n"
."迷惑メール相談センター" . "\n"
."担当者 様" . "\n"
."\n"
."\n"
." 表示義務に違反するメールを受信しましたので情報提供いたします。" . "\n"
."本メールに添付したものが提供させていただきます表示義務違反メールです。" . "\n"
."\n"
."大変お手数ではありますが対応いただきたく、よろしくお願いいたします。" . "\n";
my $mailmsg;
$Subject = encode( "jis", decode("jis",$Subject) );
$messageText = encode( "jis", decode("jis",$messageText) );
## メール枠生成
$mailmsg = MIME::Entity->build(
From => $from
,Sender => $from
,To => $to
,Subject => encode_mimeword( $Subject, 'B','iso-2022-jp')
,Type => 'multipart/mixed'
);
## 本文
$mailmsg->attach(
Type => 'text/plain; charset="iso-2022-jp"'
,Encoding => '7bit'
,Data => $messageText
);
## 添付処理
opendir(DH, $maildir);
@maillist = readdir(DH);
closedir(DH);
$cnt=1;
while(<@maillist>) {
if (($_ ne ".")&&($_ ne "..")) {
$mailmsg->attach(
Type => 'message/rfc822'
,Encoding => '7bit'
,Description => "attachment"
,Path => "$maildir/$_"
,Filename => sprintf("mwkmail%03i.eml",$cnt)
);
$cnt++;
}
}
## メール送信
$mailmsg->send('sendmail');
$maildir で指定するディレクトリ(ここでは$HOME/Maildir/.WORK.TEIKYO/cur)中のメールファイルを全て添付とし、 $to で示すあて先(迷惑メール相談センターの受付メールアドレス)に送信します。
$from は、送信者(筆者)のメールアドレスになります。
テストする際には$fromも$toも自分のメールアドレスにするように。受信結果が正しいことを必ず確認しなければいけません。
筆者はqmail+Maildir形式を使っているので、1メール1ファイルになります。
mbox形式の場合は適宜メールを切り出す形にする必要があります。
あ、ひと頃昔なら$fromに詐称したアドレスを書けたかもしれませんが、最近ではそれやるとメール送信できないプロバイダが多いかもしれません。
場合によっては記録をとられてしまうかもしれません。
ちなみに、このスクリプトをそのまま使ったわけではないです。
例えば添付が100個とか付いたメールはとても重くて開くことが困難だと思います。
そういう事態を避けるような処理を追加したり、同じ送信元同じ内容のメール(重複したメール)は添付対象からはずす、などがいりますね。
やっていることは日本データ通信協会用とほとんど同じ。
違いは、迷惑メールと同じ数だけ報告メールが送信されるということ。
#!/usr/bin/perl
use Encode;
use MIME::Entity;
use MIME::Words qw (:all);
my $maildir = "$ENV{HOME}/Maildir/.WORK.TEIKYO/cur";
my $from = 'hogehoge@hogehoge.jp';
my $to = 'mailagain@nissankyo.jp';
my $Subject = "表示義務に違反するメールがありましたので、情報提供いたします";
my $messageText = "財団法人 日本産業協会"."\n"
."迷惑メール情報提供受付" . "\n"
."担当者 様" . "\n"
."\n"
."\n"
." 表示義務に違反するメールを受信しましたので情報提供いたします。" . "\n"
."本メールに添付したものが提供させていただきます表示義務違反メールです。" . "\n"
."\n"
."大変お手数ではありますが対応いただきたく、よろしくお願いいたします。" . "\n";
my $mailmsg;
$Subject = encode( "jis", decode("jis",$Subject) );
$messageText = encode( "jis", decode("jis",$messageText) );
## 添付の数だけループする
opendir(DH, $maildir);
@maillist = readdir(DH);
closedir(DH);
$cnt=1;
while(<@maillist>) {
if (($_ ne ".")&&($_ ne "..")) {
## メール枠生成
$mailmsg = MIME::Entity->build(
From => $from
,Sender => $from
,To => $to
,Subject => encode_mimeword( $Subject, 'B','iso-2022-jp')
,Type => 'multipart/mixed'
);
## 本文
$mailmsg->attach(
Type => 'text/plain; charset="iso-2022-jp"'
,Encoding => '7bit'
,Data => $messageText
);
## 添付
$mailmsg->attach(
Type => 'message/rfc822'
,Encoding => '7bit'
,Description => "inline"
,Path => "$maildir/$_"
,Filename => sprintf("mwkmail%03i.eml",$cnt)
);
## メール送信
$mailmsg->send('sendmail');
$cnt++;
}
}
こちらも、このスクリプトをそのまま使ったわけではないです。
例えば100個連続送信なんて嫌がらせですよねぇ。
そういう事態を避けるような処理を追加しました。
完全ではないですが、スクリプトにする事で、少ない負担で報告(情報提供)の自動化が可能になります。
例えば、筆者の場合、bogofilter + Maildrop でSPAMのフィルタリングを行っています。
現在は
SPAM判定したメールを特定のディレクトリへ移動:サーバ
誤ってSPAM判定されたメールをサルベージ:人間
週末までディレクトリに残ったメールをSPAM(不要メール)と判断してアーカイブ:サーバ
しています。
ほとんど誤判定が無いくらいに学習が進んだbogofilterのおかげで、放置していても問題ないレベルになっています。
SPAMを消さずにアーカイブしているのは、bogofilterの辞書がおかしくなってしまった時に備えての再学習用です。
とはいっても、やっぱり誤判定は発生するわけで、あまりに大量にSPAMがあると誤判定されたメールを探すのが一苦労なのです…
で。この 3 のアーカイブする直前に、残ったメールを迷惑メールであるとみなし、今回作ったスクリプトで報告させるわけです。
まぁ、誤ったメールをSPAMとさせないため人間の目視確認は無くす事ができませんが、報告用メールを手で一つずつ作る作業を行うよりはずっと簡単になります。
筆者にSPAMを送り続ける限り、お上の組織へ報告が続くことになる。
きっとその中の一つくらいは対応してもらえるに違いない、と勝手に思っています。
そういえば最近、迷惑メール中のURLを抽出して、フィルタリングサービスの業者に提供する、って話を聞きました。
業者がメールを送れば送るほど、使えるドメインが減っていく事になります。なかなかうまい手かも。