#!/usr/bin/perl -w use strict; use MIME::Parser; use File::Temp "tempfile"; #----------------------------------------------------------------------------- sub debug { print "@_ \n" if ( defined $ENV{debugging} ); } #----------------------------------------------------------------------------- sub find_parts { my $found_arr_ref = $_[0]; my $given_part = $_[1]; my $num_parts = $given_part->parts; if ( $num_parts == 0 ){ if ( $given_part->effective_type =~ m/message\/rfc822/ ){ debug "added a part"; push @$found_arr_ref, $given_part; } else { debug "part is not an attachment"; } # if rfc822 } else { for (my $i=0; $i < $num_parts; $i++) { debug "recursing into parts"; my $part = $given_part->parts($i); find_parts( $found_arr_ref, $part ); } } # if else } #----------------------------------------------------------------------------- sub bogoclassify { my $m_ref = $_[0]; my $to_spam = $_[1]; my $flags = ""; my $success = 0; my $logline = ""; if ( $to_spam == 1 ){ debug "running in enspamming mode"; $flags = "-sN"; #$flags = "-p"; $success = 0; $logline = "enspamed message, runs = "; } else { debug "running in despamming mode"; $flags = "-Ns"; #$flags = "-p"; $success = 1; $logline = "despamed message, runs = "; } (my $tmpf, my $tmpname) = tempfile(UNLINK =>1); print $tmpf $$m_ref or die "can't write to tempfile\n"; my $iterations = 10; my $retval = $success+10; # something that doesn't match $success while ($iterations > 0 && $retval != $success ){ system("cat $tmpname | bogofilter $flags"); $retval = $?>>8; $iterations--; } if ( $success == $retval ){ print "attbogo: $logline " . (10-$iterations) . "\n"; } else { print "attbogo: NOT $logline " . (10-$iterations) . "\n"; } #print "\n\nMESSAGE:\n\n" . $$m_ref . "\n"; } #----------------------------------------------------------------------------- my $to_spam = 1; # classify as spam $to_spam = 0 if ( defined $ARGV[0] && ($ARGV[0] eq '-d') ); # declassify message marked as spam my @messagelines = ; my $message = ""; foreach (@messagelines){ $message .= $_; } my $marr_ref = []; my $parser = new MIME::Parser; $parser->output_to_core(1); $parser->extract_nested_messages(0); my $pmessage = $parser->parse_data($message); $pmessage->dump_skeleton() if ( defined $ENV{debugging} ); find_parts( $marr_ref, $pmessage ); debug "rfc822 count is " . scalar(@$marr_ref) . "\n"; if ( scalar(@$marr_ref) == 0 ){ #message doesn't have mime attached messages debug "message does not have attachments, stripping the header"; my $max_sig = 6; my $found_body = 0; my $thebody = ""; my $found_signature = 0; my $signature = ""; my $siglines = 0; foreach (@messagelines) { $found_body = 1 if ( !$found_body && m/^$/ ); if ( $found_body && !$found_signature && m/^--\s*$/ ) { # first signature $found_signature = 1; $signature = $_; next; } elsif ( $found_body && $found_signature && m/^--\s*$/ && $siglines > $max_sig ){ # next signature $thebody .= $signature; $signature = $_; $siglines = 0; next; } if ($found_body && !$found_signature) { $thebody .= $_; } elsif ( $found_body && $found_signature ){ $signature .= $_; $siglines++; } } $thebody .= $signature if ($siglines > $max_sig ); bogoclassify( \$thebody, $to_spam); } else { # classify each attachment separately foreach my $i ( @$marr_ref ){ my $for_bogo = $i->stringify_body; bogoclassify( \$for_bogo, $to_spam); } } # if has attachments exit 0;