Menu
更新状況
2008年07月14日 2008年03月27日 2008年03月04日 2008年02月14日 2008年01月07日 2007年12月10日 2007年10月01日 2007年09月26日 2007年09月03日 2007年08月07日 2007年07月06日 2007年06月03日 2007年05月08日 2007年04月10日

PerlのPOP3Client を使ったスパムメール対策(旧)

その気になったら、Vector の方にでも真面目にページを書きます。
→ Vector にページを作りました。 http://hp.vector.co.jp/authors/VA014481/return-path-checker/index.html

以下の内容は古いものです。


2006年5月7日 15:00 時点のもの。

目的:POP3 over SSL 通信で、プロバイダのメールボックスにあるスパムメールを除去する。

  • ローカルのディスクにメールをダウンロードする前に、プロバイダ側にあるうちに片付けたい。
    1. ローカルに取り込んだメールは sssendmail のデータバックアップとして保管しているが、スパムメールのためにこのスペースを確保するのはもったいないし、煩わしい。
    2. スパムメールでも、ディスク書き込みのための時間を必要とする。
  • ダウンロードした後のメールについては、procmail, annoyance-filter を使用して振り分け、判定を行っている。

スパムメール判定のためのパターン

幸い、無条件で(読まずに)消していいスパムメール判定のためのパターンをいくつか特定することができた。
  1. Return-Path: だけで判定できるもの
    1. info@.*.com
  2. 内容との組合せ
    1. .biz からくるもので、画像が添付されているもの
    2. .*@ocn.ne.jp からくるもので、特定のサイトの URL が書かれていもの

効果:プロバイダメールボックスに着信するメールの 2割程度は、読まずに除去できる。

  • ローカルに取り込む時間の節約になる
  • HDD 領域の節約になる。
  • スパムメールの 2割 ではない。全体の2割。スパムメールに占める割合はもっと大きくなる。

使う物:Perl, Mail::POP3Client

使った物:

  • Perl で書かれた pop3browser から、設定ファイルの読み込み部分をもらった。
  • Mail::POP3Client について日本語で解説したサイト。
  • Googleで探してみると、いくつかみつかります。助かりました。

ライセンス

GPL とするので、好きにしてください。

設定ファイル

  • 名前 $HOME/.return-path-readerrc
  • 書式
  • サーバ名 ユーザ名 パスワード
    

ソースコード

システムの制限で表示されない部分が一部あるので、添付もしておきます
#!/usr/bin/perl -w
# POP3 folder cleaner over SSL

use strict;

#read config data
# this part is almost copy from pop3browser.

my $nhosts;
my @host;
my $i;
my $mode;

if (-e "$ENV{\"HOME\"}/.return-path-readerrc")
{
    ($mode)=(stat("$ENV{\"HOME\"}/.return-path-readerrc"))[2];
    if ($mode != 0100600)
    {
        print "The configuration file was readable for other users than the file owner.\n";
        print "Correcting it...\n";
        #this file should only be read by the owner
        chmod(0600,"$ENV{\"HOME\"}/.return-path-readerrc") 
            or die "FATAL: could't chmod the configfile. Do you own it?";
    }
    open(CONFIG,"$ENV{\"HOME\"}/.return-path-readerrc")
        or die "FATAL: could't open the configfile. Do you own it?";
    $i=0;
    
    while ()
    {
        chomp();
        s/^\s+//;
        next if /^\#/;
        next if /^$/;
        
        
        ($host[$i]{"host"},$host[$i]{"uid"},$host[$i]{"passwd"},$host[$i]{"protocol"})=split(/\s+/, $_, 4);

        $i+=1;  
    }
    $nhosts=$i;
    close(CONFIG);
    if ($nhosts==0)
    {
        print "No host definitions found in configuration file!\n";
        exit 0;
    }
}
else
{
    print "No config file found!\n";
    print "return-path-reader needs the file .return-path-readerrc in your home directory to work.\n";
    print ".return-path-readerrc contains the definitions for your pop3 accounts.\n";
    print "One definition per line and in the following form:\n";
    print "hostname userid password\n";
    print "The entries in one line may be separated by spaces or tabs,\n";
    print "lines starting with \# are ignored.\n";
    exit 0;
}


# POP3 server へ接続し Return-Path の一覧を読みとる

my $pop3_hostname = $host[0]{"host"};
my $pop3_user = $host[0]{"uid"};
my $pop3_password = $host[0]{"passwd"};

#POP3Client Object を生成

use Mail::POP3Client;

my $pop = Mail::POP3Client->new(
               HOST      => $pop3_hostname,
               USER      => $pop3_user,
               PASSWORD  => $pop3_password,
               USESSL    => "true",
#               AUTH_MODE => 'PASS',
);
                                                                               
# メールボックス全てのメールを処理する

    my $count = $pop->Count;

    print "mail count $count \n";

    my @returnpath;
    my @subject;
    my @nullarray = ();

    my ($dummy, $retpath);
    my $found_infocom = 0;
    my $found_apacheinfo = 0;
    my @attached_image_line;
    my $found_attachedimage = 0;
    my @body_line;
    my $found_deai_site = 0;
    my $found_messagescr = 0;

    foreach my $msg (1..$pop->Count) {
    # mail headerから "Return-Path:" の文字列で始まる要素を抽出、表示
        @returnpath = grep { /^Return-Path: / } $pop->Head($msg);
        if ( @returnpath != @nullarray ) {
#            print "$msg $returnpath[0]";

# .*@.*.biz with image attached
            if ( $retpath =~ /\<.*\.biz\>/i ) {
#                print "end with .biz\n";
                @attached_image_line = grep {/Content-Type: image\//} $pop->Body($msg);
                if ( @attached_image_line != @nullarray ) {
                    print "end with .biz, with image attached.\n";
                    $found_attachedimage++;
#                    print "@attached_image_line\n";
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                }
            }

# .*@.*.com with image attached
            if ( $retpath =~ /\<.*\.com\>/i ) {
                @attached_image_line = grep {/^\tname="top\.jpg"/} $pop->Body($msg);
                if ( @attached_image_line != @nullarray ) {
                    print "end with .com, with top.jpg attached.\n";
                    $found_attachedimage++;
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                }
            }

# apache@*.info
            if ( $retpath =~ /\/i ) {
                print "apache@*.info!!\n";
                $found_apacheinfo++;
                # mark a message to delete .
                $pop->Delete($msg);
                next;
            }

# info@.*.com
            if ( $retpath =~ /\/i ) {
                print "infocom!!\n";
                $found_infocom++;
                # mark a message to delete .
                $pop->Delete($msg);
                next;
            }

# .*@.*.ocn.ne.jp inclues http://www.meguriai-max.net/
            if ( $retpath =~ /\<.*\@ocn.ne.jp\>/i ) {
                @body_line = grep {/http:\/\/www\.(meguriai-max|gyakuten6)\.net\//} $pop->Body($msg);
                if ( @body_line != @nullarray ) {
                    $found_deai_site++;
#                    print "@body_line\n";
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                }
            }
        }

# Subject: Mail Delivery (failure hma@syd.odn.ne.jp) with message.scr attached
        @subject = grep { /^Subject: Mail Delivery / } $pop->Head($msg);
        if ( @subject != @nullarray ) {
            @body_line = grep {/^\tname="message.scr"/} $pop->Body($msg);
            if ( @body_line != @nullarray ) {
                $found_messagescr++;
                # mark a message to delete .
                $pop->Delete($msg);
                next;
            }
            
        }
    }
# pop server から切断
$pop->Close( );
    print "infocom: $found_infocom / $count, ";
    print "attachedimage: $found_attachedimage / $count, ";
    print "deai-site: $found_deai_site / $count, ";
    print "apacheinfo: $found_apacheinfo / $count, ";
    print "messagescr: $found_messagescr / $count\n ";
exit;


protected [hama] 著者: hama 作成日: 2006年07月26日16時29分30秒
markreturn-path-reader.pl
COPYRIGHT(C) 2002-2004 BSPACE ONLINE
このページに関する問い合わせはbunmei@bspace.infoまでお願い致します。 powerd by PADDLE