#! /usr/bin/perl # spamassassin handling split from spamscan # # unfortunatly we can't use strict; use lib qw(/usr/lib/debbugs); use Mail::CrossAssassin; use Mail::SpamAssassin; use Mail::SpamAssassin::NoMailAudit; my $config_path = '/etc/debbugs'; require "$config_path/config"; # New versions of debbugs will not allow use in /etc/debbugs/config use POSIX qw(strftime); $gSpamMailbox = strftime($gSpamMailbox,gmtime); $gCrossMailbox = strftime($gCrossMailbox,gmtime); umask 002; $| = 1; STDOUT->autoflush(1); sub header_or_empty ($$) { my ($mail, $hdr) = @_; my $value = $mail->get_header($hdr); if (defined $value) { chomp $value; $value =~ tr/\n/\\n/; return $value; } return ''; } my $user_prefs = "$ENV{HOME}/.spamassassin/user_prefs"; my $spam = Mail::SpamAssassin->new({ dont_copy_prefs => 1, site_rules_filename => $gSpamRulesDir, userprefs_filename => $user_prefs, local_tests_only => ($gSpamLocalTestsOnly || 0), debug => ($ENV{DEBBUGS_SPAM_DEBUG} || 0), }); $spam->compile_now(1); # use all user preferences while (my $id = ) { chomp $id; my $nf = or die "Could not read nf: $!"; chomp $nf; unless (rename "incoming/S$id", "incoming/R$id") { die "Could not rename incoming/S$id: $!"; } my $out = "[$nf] $id scanning ...\n"; open MESSAGE, "< incoming/R$id" or die "open incoming/R$id: $!"; my @textarray; # Kludge to work around Received: then From_ weirdness in receive; # remove when receive is fixed? We may continue to need it for # reprocessing old messages. $textarray[0] = ; if ($textarray[0] =~ /^Received:/) { my $maybefrom = ; if ($maybefrom =~ /^From /) { $textarray[1] = $textarray[0]; $textarray[0] = $maybefrom; } else { $textarray[1] = $maybefrom; } } push @textarray, ; close MESSAGE; my $mail = Mail::SpamAssassin::NoMailAudit->new(data => \@textarray); $mail->{noexit} = 1; my $messageid = header_or_empty($mail, 'Message-Id'); $out .= " From: " . header_or_empty($mail, 'From') . "\n"; $out .= " Subject: ". header_or_empty($mail, 'Subject') . "\n"; $out .= " Date: " . header_or_empty($mail, 'Date') . "\n"; $out .= " Message-Id: $messageid\n"; my $keys = ca_keys($mail->get_body); print "$keys\n$messageid\n" or die "Could not send keys: $!"; my $ca_score = or die "Could not read ca_score: $!"; chomp $ca_score; my $todo = 0; my $seen = or die "Child could not read seen: $!"; chomp $seen; my $status; my $nseen = $seen; if ($seen) { $todo = 1; $out .= " spam $seen duplicate\n"; } else { $status = $spam->check($mail); $status->rewrite_mail(); if ($status->is_spam()) { # $mail->accept($gSpamMailbox); # unlink "incoming/R$id" or warn "unlink incoming/R$id: $!"; $todo = 1; my $score = sprintf "%.1f/%.1f %d", $status->get_hits(), $status->get_required_hits(), $ca_score; $out .= " spam $score\n"; $nseen = $score; } elsif ($status->get_hits() > 0 && $ca_score >= $gMaxCross) { # $mail->accept($gCrossMailbox); # unlink "incoming/R$id" or warn "unlink incoming/R$id: $!"; $todo = 2; my $score = sprintf "%.1f/%.1f %d", $status->get_hits(), $status->get_required_hits(), $ca_score; $out .= " spam $score\n"; $nseen = $score; } else { open OUT, "> incoming/I$id" or die "open incoming/I$id: $!"; my @headers = $mail->get_all_headers(); if ($headers[0] =~ /^From /) { my $from = $headers[0]; $headers[0] = $headers[1]; $headers[1] = $from; } print OUT join '', @headers or die "print incoming/I$id: $!"; if ($ca_score > 1) { print OUT "X-CrossAssassin-Score: $ca_score\n" or die "print incoming/I$id: $!"; } print OUT "\n" or die "print incoming/I$id: $!"; print OUT @{$mail->get_body()} or die "print incoming/I$id: $!"; close OUT or die "close incoming/I$id: $!"; unlink "incoming/R$id" or warn "unlink incoming/R$id: $!"; $out .= sprintf " ok %.1f/%.1f %d\n", $status->get_hits(), $status->get_required_hits(), $ca_score; } } print "$todo\n"; my $x = ; if ($todo) { open OUT, '>>', ($todo == 1) ? $gSpamMailbox : $gCrossMailbox or die "Could not open assassinated: $!"; my @headers = $mail->get_all_headers(); print OUT @headers or die "print assassinated: $!"; print OUT "\n" or die "print assassinated: $!"; foreach (@{$mail->get_body()}) { s/^From />From /; print OUT $_ or die "print assassinated: $!"; } close OUT or die "Close assassinated: $!"; } $out =~ tr/\n/\r/; print "$nseen\n$out\n"; $status->finish() unless($seen); }