#!/usr/bin/perl -w
# POP3 folder cleaner over SSL

package returnPathChecker;

use strict;
use File::Basename;

# variables used globally 
use vars qw(@nullarray @badurl);
use vars qw($pop);
use vars qw($found_nameko);

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

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

# set verbose true if you want to see verbose output.
my $verbose="false";
#my $verbose="true";

# get my own basename on command line.
my $myname = basename($0, ".pl");
my $myconfdirname="$ENV{\"HOME\"}/" . "." . $myname;
my $myConfAccount="$myconfdirname/account";
my $myConfReturnPath="$myconfdirname/rp";
my $myConfSkip="$myconfdirname/skip";
my $myNextNumberToCheck="$myconfdirname/next";

#optional
my $myConfBadUrl="$myconfdirname/badurl";

my $dummy_rphead;

my $rp_idx;
my @reject_rp;

my $badurl_idx;

my $skip_rp_idx;
my @skip_rp;
my $mail_skipped=0;

# read account file
if (-e $myConfAccount)
{
	($mode)=(stat($myConfAccount))[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,$myConfAccount) 
			or die "FATAL: could't chmod the config file $myConfAccount\nDo you own it?";
	}
	open(CONFIG,$myConfAccount)
	or die "FATAL: could't open the config file $myConfAccount\nDo you own it?";
	$i=0;
	$rp_idx=0;
	
	while (<CONFIG>)
	{
		chomp();
		s/^\s+//;
		next if /^\#/;
		next if /^$/;
	
        # set "" in advance to judge availability later. 
        # We can't use null when subs Strice is in use.

		($host[$i]{"host"},$host[$i]{"uid"},$host[$i]{"passwd"},$host[$i]{"address"})=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 "$myname needs the file $myConfAccount in your home directory to work.\n";
	print "$myConfAccount 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;
}


# read rp (return-path) file
if (-e $myConfReturnPath)
{
	open(CONFIG,$myConfReturnPath)
	or die "FATAL: could't open the config file $myConfReturnPath\nDo you own it?";
	$i=0;
	$rp_idx=0;
	
	while (<CONFIG>)
	{
		chomp();
		s/^\s+//;
		next if /^\#/;
		next if /^$/;
	
		# Return-Path:
		if ( /^rp / ) {
			($dummy_rphead, $reject_rp[$rp_idx]) = split(/\s+/, $_, 2);

			$rp_idx++;
			next;
		}
	
	}
	close(CONFIG);
}
else
{
	print "No Return-Path config file found!\n";
	print "$myname needs the file $myConfReturnPath in your home directory to work.\n";
	print "$myConfReturnPath contains the Return-Path definitions to reject.\n ";
	print "One definition per line and in the following form:\n";
	print "rp <Return-Path-to-reject>\n";
	print "The entries in one line may be separated by spaces or tabs,\n";
	print "lines starting with \# are ignored.\n";
	exit 0;
}

if ($verbose eq "true" ) {
	foreach my $rjr (@reject_rp) {
		print "Return-Path: $rjr\n";
	}
}

# read skip  file
if (-e $myConfSkip)
{
	open(CONFIG,$myConfSkip)
	or die "FATAL: could't open the config file $myConfSkip\nDo you own it?";
	$i=0;
	$skip_rp_idx=0;
	
	while (<CONFIG>)
	{
		chomp();
		s/^\s+//;
		next if /^\#/;
		next if /^$/;
	
		# Return-Path:
		if ( /^skip / ) {
			($dummy_rphead, $skip_rp[$skip_rp_idx]) = split(/\s+/, $_, 2);

			$skip_rp_idx++;
			next;
		}
	
	}
	close(CONFIG);
}

if ($verbose eq "true" ) {
	foreach my $skip (@skip_rp) {
		print "skipped Return-Path: $skip\n";
	}
}

# read badurl file
# badurl is optional
if (-e $myConfReturnPath)
{
	open(CONFIG,$myConfBadUrl)
	or warn "FATAL: could't open the config file $myConfBadUrl\nDo you own it?";
	$i=0;
	$badurl_idx=0;
	
	while (<CONFIG>)
	{
		chomp();
		s/^\s+//;
		next if /^\#/;
		next if /^$/;
	
		# Bad URL:
		if ( /^url / ) {
			($dummy_rphead, $badurl[$badurl_idx]) = split(/\s+/, $_, 2);

			$badurl_idx++;
			next;
		}
	
	}
	close(CONFIG);
}


################################
# badurl を検知する関数
# detect inclusion of bad URL (ex. http://nameko.name/) in body.
# if URL is included in @badurl, 
# the mail is deleted

sub badurl_detect($@;){
	my ($msgno, @data_lines) = @_;	
    my $boolean_found_badurl = "false";
    foreach my $burl (@badurl) {
        my @body_line = grep { /$burl/ } @data_lines;
        if ( @body_line != @nullarray ) {
            print "Contains bad URL: $burl\n";
            # mark a message to delete .
            $pop->Delete($msgno);
            $boolean_found_badurl = "true";
            $found_nameko++;
            last;
        }
    }
	return $boolean_found_badurl; 
}

##################################
# POP3 server へ接続し POP3Client Object を生成

my $pop3_hostname = $host[0]{"host"};
my $pop3_user = $host[0]{"uid"};
my $pop3_password = $host[0]{"passwd"};
my $myAddress = "";
if (defined $host[0]{"address"}) {
    $myAddress = $host[0]{"address"} 
}

if ($verbose eq "true" ) {
    print "myAddress is $myAddress\n";
}

## make connection to server
# POP3s
use Mail::POP3Client;

$pop = Mail::POP3Client->new(
	HOST	  => $pop3_hostname,
	USER	  => $pop3_user,
	PASSWORD  => $pop3_password,
	USESSL	=> "true",
	#			   AUTH_MODE => 'PASS',
);
my $count = $pop->Count;

# POP3
if ( $count == -1 ) {
	print "Couldn't connect to POP3s host.\nfalling back to Non SSL connection.\n";

	# fallback to Non-SSL connectoin.
	$pop = Mail::POP3Client->new(
		   HOST	  => $pop3_hostname,
		   USER	  => $pop3_user,
		   PASSWORD  => $pop3_password,
		   USESSL	=> 0,
		   AUTH_MODE => 'PASS',
	);
	$count = $pop->Count; 
    if ( $count == -1 ) {  # Not connected, exit.
        die "Couldn't establish connection to POP3 server.";
    }
}

# 本文が Encode されていた時のための Parser
use MIME::Parser;
use MIME::Decoder;
my $parser = new MIME::Parser;
# don't use temporary file since body lines is limited.
$parser->output_to_core(1);  
my $parsed_entity;
my $decoded_body;
my @decoded_body_lines;

	my @returnpath;
    my @header_lines;
    my @header_and_top_lines;
    my $toplines = 60;

	my @header;
	@nullarray = ();

	my ($dummy, $retpath);
	my $found_pdfspam = 0;
	my @attached_image_line;
	my $found_attachedimage = 0;
	my @charset_line; 
	my @software_title_line;
	my @body_line;
	my @whole_body_is_encoded;
	my $found_x_header = 0;
	my $found_false_unknownIP = 0;
	my $found_koi8r = 0;
	my $found_greeting = 0;
	my $found_windows1250 = 0; 
	my $found_htmlsoftware = 0;
	my $found_pharmacy = 0;
	my $found_stock = 0;
	my $found_oemsoft = 0;
	my $found_menshealth = 0;
	my $found_message = 0;
	my $found_rpcount = 0;
	my $found_manyccodn = 0;
	my $found_fromspam = 0;
	my $found_tospam = 0;
	my $found_midspam = 0;
	my $found_unknown_drive = 0;
	my $found_unknown_cj = 0;
	my $found_impossible_syd = 0;
	my $found_friend = 0;
	my $found_mymy = 0;
	my $found_percentoff = 0;
	my $found_forget = 0;
	$found_nameko = 0;

# get start number from command line or file.
	my $start = 1;
# get end number  from command line if exist.
	my $end = -1;

	if ( @ARGV != @nullarray ) {
		$start = shift @ARGV;
        if ( @ARGV != @nullarray ) {
            $end = shift @ARGV;
        }
	} else {
		if (-e $myNextNumberToCheck) {
			my $nextNumberToCheck=0;

			open(NEXT, $myNextNumberToCheck);
			while(<NEXT>) {
				$nextNumberToCheck=$_;
			}
			close(NEXT);
			print "next number to check read from file= $nextNumberToCheck\n";
			# TODO : check whether number or not?
			if ( $nextNumberToCheck != 0 ) {
				$start = $nextNumberToCheck;
			}
		}
	}



    if ( $end == -1 || $end > $count) {  # not given or exceed
        $end = $count;
    }

	print "given start is $start, ";
	print "mail count is $count, ";
	print "end is $end\n";

# メールボックスのメールをループで処理する
##
## main loop
##

	foreach my $msg ($start..$end) {
# Todo: verbosity is represented in bit composition.
#        if ($verbose eq "true" ) {
            print "[$msg] ";
#        }

		# mail header を取得
		@header_lines = $pop->Head($msg);
		# mail header と TOP の結果を取得 : TODO TOP が有効かどうかの判定が必要
		@header_and_top_lines = $pop->Head($msg, $toplines);

		# mail headerから "Return-Path:" の文字列で始まる要素を抽出
		@returnpath = grep { /^Return-Path: / } @header_lines;
		if ( @returnpath != @nullarray ) {
			($dummy, $retpath) =  split(/-Path:\s+/, $returnpath[0], 2);
            if ($verbose eq "true" ) {
                print "xx" . "$retpath" . "xx\n";
            }


# .*@.*.biz with image attached
			if ( $retpath =~ /\<.*\.biz\>/i ) {
#				print "end with .biz\n";
				@attached_image_line = grep {/Content-Type: image\//} @header_and_top_lines;
				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;
				}
			}

# if Return-Path: (.*) is included in @skip_rp, 
# must be skipped.
			my $found_skip_rp = "false";
			foreach my $skrp (@skip_rp) {
				if ( $retpath =~ /^$skrp$/ ) {
					$found_skip_rp = "true";	
					$mail_skipped++;
					last;
				}
			}
			next if  $found_skip_rp eq "true" ;

# if Return-Path: (.*) is included in @reject_rp, 
# the mail is deleted
			my $found_rp = "false";
			foreach my $rjrp (@reject_rp) {
				if ( $retpath =~ /^$rjrp$/ ) {
					print "reject_rp: $rjrp\n";
					# mark a message to delete .
					$pop->Delete($msg);
					$found_rp = "true";
					$found_rpcount++;
					last;
				}
			}
			next if  $found_rp eq "true" ;


## PDF,FDF spam
            @header = grep {/^Subject: /} @header_lines;
            if ( @header != @nullarray ) {
                $header[0] =~ s/^Subject: //;
                if ( ! ($header[0] eq "") ) {
                    @body_line = grep {/(^Content-Type: .*|\s+)name="?\Q$header[0]\E/} @header_and_top_lines;
                    if ( @body_line != @nullarray ) {
                        $found_pdfspam++;
                        print "PDF spam\n";
                        # mark a message to delete .
                        $pop->Delete($msg);
                        next;
                    }
                }
            }

            @header = grep {/^Subject: .*-(hma|done|hama)$/} @header_lines;
            if ( @header != @nullarray ) {
                @body_line = grep {/^(Content-Type: .*|\s+)name=.*\.[fp]df/} @header_and_top_lines;
                if ( @body_line != @nullarray ) {
                    $found_pdfspam++;
                    print "PDF spam\n";
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                }
            }


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

				@charset_line = grep {/^\s+charset="[Ww]indows-125[012]"/} @header_and_top_lines;
				if ( @charset_line != @nullarray ) {
					print "end with .com, in windows-1250,1251,1252 charset .\n";
					$found_windows1250++;
					# mark a message to delete .
					$pop->Delete($msg);
					next;
				}

				@software_title_line = grep {/^\<title\>Software\<\/title\>/} @header_and_top_lines;
				if ( @software_title_line != @nullarray ) {
					print "end with .com, with html title Software.\n";
					$found_htmlsoftware++;
					# mark a message to delete .
					$pop->Delete($msg);
					next;
				}
			}

		}

# includes Received: from drive.co.jp (unknown [ ....) in header.
		@header = grep { /^Received: from .*drive.co.jp \(unknown / } @header_lines;
		if ( @header != @nullarray ) {
			print "received from unknown .*drive.co.jp.\n";
			$found_unknown_drive++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# includes Received: from cyberonix.co.jp (unknown [ ....) in header.
		@header = grep { /^Received: from cyberonix.co.jp \(unknown / } @header_lines;
		if ( @header != @nullarray ) {
			print "received from unknown cyberonix.co.jp.\n";
			$found_unknown_cj++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# includes Received: from syd.odn.ne.jp ([impossible IP address ]) in header.
		@header = grep { /^Received: from syd.odn.ne.jp \(\[5/ } @header_lines;
		if ( @header != @nullarray ) {
			print "received from impossible syd.odn.ne.jp.\n";
			$found_impossible_syd++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# includes Received: from friend  in header.
#  Too strict??
		@header = grep { /^Received: from friend / } @header_lines;
		if ( @header != @nullarray ) {
			print "received from friend\n";
			$found_friend++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# includes myAddress both in To: and Return-Path:
# I usually don't send to myself.
        if ( ! $myAddress eq "" ) {
			@header = grep { /^To: .*\<?$myAddress\>?/ } @header_lines;
			if ( @header != @nullarray ) {
				if ( $retpath eq "<$myAddress>" ) {
                    print "mymy in header\n";
                    $found_mymy++;
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                } else {
					@header = grep { /^From: .*\<?$myAddress\>?/ } @header_lines;
					if ( @header != @nullarray ) {
						@header = grep { /^Subject: .*(January|February|March|April|May|June|July|August|September|October|November|December).*\%?[0-9]+\%? OFF/ } @header_lines;
						if ( @header != @nullarray ) {
							print "\%off in header\n";
							$found_percentoff++;
							# mark a message to delete .
							$pop->Delete($msg);
							next;
						}
					}
				}
            }
        }

# includes ^x-cr-hashedpuzzle: in header.
		@header = grep { /^x-cr-hashedpuzzle: / } @header_lines;
		if ( @header != @nullarray ) {
			print "header includes ^x-cr-hashedpuzzle: .\n";
			$found_x_header++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# False unknown IP address
		@header = grep { /^Received: from [0-9.]+ / } @header_lines;
		if ( @header != @nullarray ) {
			# use @header again, no harm.
			@header = grep { /^Received: from ([0-9.]+) \(unknown \[\1\]/ } @header_lines;
			if ( @header == @nullarray ) {
				print "received from false unknown IP.\n";
				$found_false_unknownIP++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}

# From and Subject is in koi8-r
		@header = grep { /^From:[\t ]+"?=\?koi8-r\?[BbQq]\?/ } @header_lines;
		if ( @header != @nullarray ) {
			my $isKoi8 = "false";
			@header = grep { /^Subject: =\?koi8-r\?[BbQq]\?/ } @header_lines;
			if ( @header != @nullarray ) {
				$isKoi8 = "true";
			} else {
				@header = grep { /^Subject: Fwd:$/ } @header_lines;
				if ( @header != @nullarray ) {
					$isKoi8 = "true";
				}
			}

			if ( $isKoi8 eq "true" ) {
				print "from and subject in koi8-r.\n";
				$found_koi8r++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}

#
# ここまではヘッダだけで判定できる。
#

# 本文が Base64 または quoted-printable になっているなら、
# デコードしないと読めない
		@whole_body_is_encoded = grep { /^Content-Transfer-Encoding: (quoted-printable|base64)/ } @header_lines;
		if ( @whole_body_is_encoded != @nullarray ) {
			if ($verbose eq "true" ) {
				print "Whole body is encoded\n";
			}

			## デコードして本文を取り出す
			# まず、各行に改行が必要。
			my @header_and_top_lines_with_n;
			for (my $hatlwn_idx=0; $hatlwn_idx < @header_and_top_lines; $hatlwn_idx++) {
				$header_and_top_lines_with_n[$hatlwn_idx] = $header_and_top_lines[$hatlwn_idx] . "\n";	
			}

			# parser に渡す。
			$parsed_entity = $parser->parse_data(\@header_and_top_lines_with_n) || die " couldn't parse_data\n";
			$decoded_body = $parsed_entity->bodyhandle() || die " couldn't get bodyhandle\n";;

			@decoded_body_lines = $decoded_body->as_lines();

			# call a function
			next if  &badurl_detect($msg, @decoded_body_lines) eq "true" ;
		}

# 本文がマルチパートになっているなら、
# デコードしないと読めない
		@whole_body_is_encoded = grep { /^Content-Type: multipart/ } @header_lines;
		if ( @whole_body_is_encoded != @nullarray ) {
			if ($verbose eq "true" ) {
				print "Multipart message.\n";
			}

			## デコードして本文を取り出す
			# まず、各行に改行が必要。
			my @header_and_top_lines_with_n;
			for (my $hatlwn_idx=0; $hatlwn_idx < @header_and_top_lines; $hatlwn_idx++) {
				$header_and_top_lines_with_n[$hatlwn_idx] = $header_and_top_lines[$hatlwn_idx] . "\n";	
			}

			# parser に渡す。
			$parsed_entity = $parser->parse_data(\@header_and_top_lines_with_n) || die " couldn't parse_data\n";
			
			
			my $parsed_part = $parsed_entity->parts(0);;
			while ($parsed_part -> parts != @nullarray) {
			# dig into the multimart dungeon
				$parsed_part = $parsed_part -> parts(0);
			}

			$decoded_body = $parsed_part->bodyhandle() || die " couldn't get bodyhandle\n";;
			@decoded_body_lines = $decoded_body->as_lines();

			# call a function
			next if  &badurl_detect($msg, @decoded_body_lines) eq "true" ;
		}

## attached image part 2.
# [a-z]+.JPG is attached.
        @attached_image_line = grep {/^\tname="[a-z]+\.JPG"/} @header_and_top_lines;
        if ( @attached_image_line != @nullarray ) {
            print "[a-z]+.JPG attached.\n";
            $found_attachedimage++;
            # mark a message to delete .
            $pop->Delete($msg);
            next;
        }

## Greeting card with virus
##
        @body_line = grep {/^Content-Type:\s+application\/x-msdownload;/} @header_and_top_lines;
        if ( @body_line != @nullarray ) {
            @body_line = grep {/^\s*filename="Greeting.*\.exe"/i} @header_and_top_lines;
            if ( @body_line != @nullarray ) {
                $found_greeting++;
                print "greeting card.exe\n";
                # mark a message to delete .
                $pop->Delete($msg);
                next;
            }
        }
## stock recommendations,
##
# include both (Symbol: or Company:) and Current Price: in body
        @body_line = grep {/([Ss]y ?m ?bol|Company):\s+[A-Z][A-Z][A-Z][A-Z]/} @header_and_top_lines;
        if ( @body_line != @nullarray ) {
            @body_line = grep {/^(Long Term Target|Current [Pp]rice):\s+/} @header_and_top_lines;
            if ( @body_line != @nullarray ) {
                $found_stock++;
                print "stock recommendation\n";
                # mark a message to delete .
                $pop->Delete($msg);
                next;
            }
        }

# saying in it's Subject: Read it someone
		@header = grep { /^Subject: .* Read it [A-Za-z]+$/ } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/, will bring big trading for this shares/} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_stock++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

# saying in it's Subject: Happy NW Someone | Someone wrote:
		@header = grep { /^Subject: (Happy NW [A-Za-z]+|[A-Za-z]+ wrote:)$/ } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^\s+Get in right after the New Year./} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_stock++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

# saying in it's Subject: fwd: ...
		@header = grep { /^Subject: fwd: [A-Za-z]+$/ } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^Smart Money Equities would like to /} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_stock++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

## OEM software sales,
##
#
		@body_line = grep { /^ \$79 MS Office Enterprise 2007/i } @header_and_top_lines;
		if ( @body_line != @nullarray ) {
			@body_line = grep { /^ \$79 Adobe Acrobat 8 Pro/ } @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_oemsoft++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

#
		@body_line = grep { /^Microsoft 0ffice 2OO7\s+79\$$/i } @header_and_top_lines;
		if ( @body_line != @nullarray ) {
			@body_line = grep { /^Adobe Acrobat 8 PR0\s+79\$$/ } @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_oemsoft++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

## Ad of Matching site.
##
        if ( ! $myAddress eq "" ) {
            @body_line = grep { /http:\/\/.*(\&|\&amp;)ma=$myAddress/} @header_and_top_lines;
            if ( $retpath =~ /^<.*\@yahoo\..*>$/ ) {
                if ( @body_line != @nullarray ) {
                    print "Yahoo mail CGI\n";
                    $found_nameko++;
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;

                }
            }
        }

		# call a function
        next if  &badurl_detect($msg, @header_and_top_lines) eq "true" ;

## Pharmacy sales,
# include some compromised pharmacy names in it's Body
		@header = grep { /^Subject: Re: / } @header_lines;
		if ( @header != @nullarray ) {
            # Some time no / at tail   
			@body_line = grep {/^http:\/\/www\.(rx.*|.*rx)[\*\.]?[\*\.]?com\/?/} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_pharmacy++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}


# include Pharmacy in it's Subject.
		@header = grep { /^Subject: Pharmacy / } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^VIAGRA/i} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_pharmacy++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}

# Subject: Men's Health Pharmacy BraBra
		@header = grep { /^Subject: Men's Health Pharmacy / } @header_lines;
		if ( @header != @nullarray ) {
            $found_menshealth++;
            # mark a message to delete .
            $pop->Delete($msg);
            next;
		}

# penis enlargement program
		@header = grep { /^Subject: Your programs really work\?/ } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^>> http:\/\/acuac.net\//} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_menshealth++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}

# Subject: Mail Delivery (failure hma (at) syd.odn.ne.jp) with message.scr attached
		@header = grep { /^Subject: Mail Delivery / } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^\tname="message.scr"/} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				$found_message++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
			
		}

# MS-download Trojan attached
		@header = grep { /^User-Agent: Thunderbird 1\.5\.0\.9 \(Windows\/20061207\)/ } @header_lines;
		if ( @header != @nullarray ) {
			@body_line = grep {/^Content-Type: application\/x-msdownload;/} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
                @body_line = grep {/^Content-Type: text\/plain; charset=ISO-8859-1; format=flowed/} @header_and_top_lines;
                if ( @body_line != @nullarray ) {
                    $found_message++;
                    # mark a message to delete .
                    $pop->Delete($msg);
                    next;
                }
			}
			
		}

# If From: includes spam sender's name
		@header = grep { /^From: =\?iso-2022-jp\?B\?GyRCQEZGIz1VSH4bKEI=\?=.*\@yahoo.co.jp\>/ } @header_lines;
		if ( @header != @nullarray ) {
			print "From: spam sender.\n";
			$found_fromspam++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# If Message-ID: includes impossible format
		@header = grep { /^Message-I[Dd]: \<.*\$.*\@cyberonix.co.jp\>/ } @header_lines;
		if ( @header != @nullarray ) {
			print "Message-ID: spam sender.\n";
			$found_midspam++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# If Message-ID: includes spam sender's ID
		@header = grep { /^Message-I[Dd]: \<\%RNDUCCHAR2025\@yahoo.com\>/ } @header_lines;
		if ( @header != @nullarray ) {
			print "Message-ID: spam sender.\n";
			$found_midspam++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# If To: includes d-ogawa@drive.co.jp
		@header = grep { /^:To: d-ogawa\@drive.co.jp/ } @header_lines;
		if ( @header != @nullarray ) {
			$found_tospam++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}

# If Cc: includes many odn addresses
		@header = grep { /^Cc: (.*\@syd.odn.ne.jp, ){5,}/ } @header_lines;
		if ( @header != @nullarray ) {
            print "too many Cc: to odn addresses.\n";
			$found_manyccodn++;
			# mark a message to delete .
			$pop->Delete($msg);
			next;
		}


# If charset is "koi8-r" and mail body includes the text "Forget about sexual problems!".
		@charset_line = grep {/^\tcharset="koi8-r"/} @header_and_top_lines;
		if ( @charset_line != @nullarray ) {
			@body_line = grep {/^Forget about sexual problems!/} @header_and_top_lines;
			if ( @body_line != @nullarray ) {
				print "Forget about ..., in koi8-r charset .\n";
				$found_forget++;
				# mark a message to delete .
				$pop->Delete($msg);
				next;
			}
		}

	}

# pop server から切断
$pop->Close( );

# 各削除数を表示
print "return-path-check: $found_rpcount, ";
print "pdfspam: $found_pdfspam, ";
print "attachedimage: $found_attachedimage, ";
print "win1250 : $found_windows1250, ";
print "titleSoftware : $found_htmlsoftware, ";
print "unknown_drive : $found_unknown_drive, ";
print "impossible_syd : $found_impossible_syd, ";
print "friend : $found_friend, ";
print "mymy : $found_mymy, ";
print "%off : $found_percentoff, ";
print "x-header : $found_x_header, ";
print "false_unknown_IP : $found_false_unknownIP, ";
print "koi8-r : $found_koi8r, ";
print "greeting.exe : $found_greeting, ";
print "nameko: $found_nameko, ";
print "pharmacy: $found_pharmacy, ";
print "stock: $found_stock, ";
print "oemsoft: $found_oemsoft, ";
print "menshealth: $found_menshealth, ";
print "messagevirus: $found_message, ";
print "fromspam: $found_fromspam, ";
print "tospam: $found_tospam, ";
print "midspam: $found_midspam, ";
print "manyccodn: $found_manyccodn, ";
print "forget: $found_forget\n";

# 削除マークしたものの合計
my $totalDeleted = ($found_rpcount 
	+ $found_pdfspam
	+ $found_attachedimage 
	+ $found_manyccodn 
	+ $found_windows1250
	+ $found_htmlsoftware
	+ $found_friend
	+ $found_mymy
	+ $found_percentoff
	+ $found_x_header
	+ $found_false_unknownIP
	+ $found_koi8r
	+ $found_greeting
	+ $found_nameko
	+ $found_pharmacy
	+ $found_stock
	+ $found_oemsoft
	+ $found_menshealth
	+ $found_message
	+ $found_fromspam
	+ $found_midspam
	+ $found_tospam
	+ $found_unknown_drive
	+ $found_unknown_cj
    + $found_impossible_syd
	+ $found_forget
);

# 処理したものの合計
if ( $start == 0 ) {
	$start = 1;  # $processed の計算のため
}
my $processed = $end-$start + 1;
if ( $processed < 0 ) {
	$processed = 0;
}

my $actualRemovalRate = 0;
my $arr_bumbo = $processed - $mail_skipped;
if ( $arr_bumbo > 0) {
	$actualRemovalRate = $totalDeleted *100 / $arr_bumbo;
}
print "total Removed : $totalDeleted / $processed  and Skipped: $mail_skipped";
printf "   Actual Removal Rate: %4.2f%%\n", $actualRemovalRate;

# 次に何番目から始めるかを記録する
my $nextNumberToCheck=$end - $totalDeleted;

open(NEXT, ">$myNextNumberToCheck") 
or die "can't open $myNextNumberToCheck to write.";
print NEXT $nextNumberToCheck+1;

exit;
