#!/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] [ [..]]\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=)); $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;