#!/usr/bin/perl -w
use strict;
use GN;
my $debug=0;
$debug=1 if(@ARGV and $ARGV[0] eq "-d" and shift @ARGV);
my $delete=0;
$delete=1 if(@ARGV and $ARGV[0] eq "--delete" and shift @ARGV);
die "usage: spamtoss [-d] [--delete] <file> [<file> [..]]\n" if(@ARGV<1);
my $db=dbconnect("test");
my $errors=0;
my ($addit,$body,$date,$file,$firstip,$head,$ip,$lastoctet,$line,$net,%received);

FILE:
foreach $file (@ARGV) {
	open(SPAM,"<",$file) or die "open: $!";
	$date=(stat(SPAM))[9] or die "stat: $!";
	$date=secs2datetime($date);
	$addit=0;
	$firstip=undef;
	$head="";
	$lastoctet=undef;
	$net=undef;
	%received=();
	while(1) {
		die "read($file): $!" unless(defined($line=<SPAM>));
		$head.=$line;
		$line =~ s/\r?\n$//s;
		last unless(length $line);
		next if($line =~ /^\s/s);
		if($line =~ /^Received: from (\S*) (?:\(HELO \S+\) )?.*?[@(](\d+)\.(\d+)\.(\d+)\.(\d+)\)$/i
		or $line =~ /^Received: from (\S*).*?[@(](\d+)\.(\d+)\.(\d+)\.(\d+)\)$/i
		or $line =~ /^Received: from (\S*).*?\(\S+ \[(\d+)\.(\d+)\.(\d+)\.(\d+)\]\)$/i
		or $line =~ /^Received: from (\S*) \(\[(\d+)\.(\d+)\.(\d+)\.(\d+)\]\)$/i
		or $line =~ /^Received: from (\S*) \(\[(\d+)\.(\d+)\.(\d+)\.(\d+)\] ident=\S+\)$/i) {
			next unless($2<256 and $3<256 and $4<256 and $5<256 and $2 != 10 and ($2 != 192 or $3 != 168) and ($2 != 172 or $3<16 or $3>31));
			$ip="$2.$3.$4.$5";
			next if($received{$ip});
			$received{$ip}=$1;
		} elsif($line =~ /^X-SpamCheck-((\d+\.\d+\.\d+)\.(\d+)):\s*(.*)/i) {
			unless($firstip) {
				$firstip=$1;
				$net="$2.0/24";
				$lastoctet=$3;
				$addit=($4 and $4 ne "DNS")?0:1;
			}
		}
	}
	unless($firstip) {
		print STDERR "couldn't find IP for $file\n";
		$errors++;
		next FILE;
	}
	unless(defined($received{$firstip})) {
		print STDERR "couldn't find Received: line for $firstip in $file\n";
		$errors++;
		next FILE;
	}
	$received{$firstip}="" if($received{$firstip} =~ /^(?:unknown|softdnserror|no-rdns-record)$/s);
	defined(read(SPAM,$body,65536)) or die "read($file): $!";
	close(SPAM) or die "close: $!";
	$net="" unless($received{$firstip} =~ /$lastoctet/);
	print "$firstip\t$date\t$net\n" if($debug);
	$db->query("insert into spam (ip,net,host,date,headers,body) values (".join(",",map {dbquote($_)} $firstip,$net,$received{$firstip},$date,$head,$body).")");
	unlink($file) if($delete);
}
exit $errors;
