2 # spamassassin handling split from spamscan
5 # unfortunatly we can't use strict;
10 use lib qw(/usr/lib/debbugs);
12 use Mail::CrossAssassin;
13 use Mail::SpamAssassin;
14 use Mail::SpamAssassin::Logger;
16 use Debbugs::Config qw(:config);
17 # New versions of debbugs will not allow use in /etc/debbugs/config
18 use POSIX qw(strftime);
19 my $spam_mailbox = strftime($config{spam_mailbox},gmtime);
20 my $cross_mailbox = strftime($config{spam_crossassassin_mailbox},gmtime);
26 sub header_or_empty ($$) {
27 my ($mail, $hdr) = @_;
28 my $value = $mail->get_header($hdr);
31 # replace newlines with '\n'
38 my $spam = Mail::SpamAssassin->new({
39 #dont_copy_prefs => 1,
41 #site_rules_filename => $config{spam_rules_dir},
42 #userprefs_filename => $config{spam_user_prefs},
43 # local_tests_only => ($config{spam_local_tests_only} || 0),
44 # debug => ($ENV{DEBBUGS_SPAM_DEBUG} || 0),
46 #Mail::SpamAssassin::Logger::add(method => 'file',filename => "/home/debbugs/.spamassassin/debuglog_".time."_$$");
47 # wait longer for a lock
48 $spam->init_learner({wait_for_lock => 1});
50 $spam->compile_now(1); # use all user preferences
52 while (my $id = <STDIN>) {
55 if (not defined $nf) {
56 die "Could not read nf: $!";
59 unless (rename "incoming/S$id", "incoming/R$id") {
60 die "Could not rename incoming/S$id: $!";
62 my $out = "[$nf] $id scanning ...\n";
63 open MESSAGE, "< incoming/R$id" or die "open incoming/R$id: $!";
64 # Kludge to work around Received: then From_ weirdness in receive;
65 # remove when receive is fixed? We may continue to need it for
66 # reprocessing old messages.
67 my @textarray = <MESSAGE>;
68 if ($textarray[0] !~ /^From /) {
69 ($textarray[0], $textarray[1]) = ($textarray[1], $textarray[0]);
72 my $mail = $spam->parse(\@textarray);
74 my $messageid = header_or_empty($mail, 'Message-Id');
75 $out .= " From: " . header_or_empty($mail, 'From') . "\n";
76 $out .= " Subject: ". header_or_empty($mail, 'Subject') . "\n";
77 $out .= " Date: " . header_or_empty($mail, 'Date') . "\n";
78 $out .= " Message-Id: $messageid\n";
79 my $keys = ca_keys($mail->get_body);
80 print "$keys\n$messageid\n"
81 or die "Could not send keys: $!";
82 my $ca_score = <STDIN>;
83 die "Could not read ca_score: $!" if not defined $ca_score;
88 die "Child could not read seen: $!" if not defined $seen;
94 $headers = join('',$mail->get_all_headers());
95 $body = join('', @{$mail->get_body()});
96 $out .= " spam $seen duplicate\n";
98 $status = $spam->check($mail);
99 ($headers, $body) = split /\n\n/, $status->rewrite_mail(), 2;
103 if ($status->is_spam()) {
105 my $score = sprintf "%.1f/%.1f %d",
106 $status->get_score(), $status->get_required_score(),
108 $out .= " spam $score\n";
110 } elsif ($status->get_score() > 0 && $ca_score >= $config{spam_max_cross}) {
112 my $score = sprintf "%.1f/%.1f %d",
113 $status->get_score(), $status->get_required_score(), $ca_score;
114 $out .= " spam $score\n";
117 my ($before, $received, $after) = $headers =~
118 /(^.*?)(^Received\: \(at .*?\n)(.*$)/ms;
119 open OUT, "> incoming/I$id" or die "open incoming/I$id: $!";
120 print OUT $received . $before . $after
121 or die "print incoming/I$id: $!";
123 print OUT "X-CrossAssassin-Score: $ca_score\n"
124 or die "print incoming/I$id: $!";
126 print OUT "\n" or die "print incoming/I$id: $!";
127 print OUT $body or die "print incoming/I$id: $!";
128 close OUT or die "close incoming/I$id: $!";
129 unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
130 $out .= sprintf " ok %.1f/%.1f %d\n",
131 $status->get_score(), $status->get_required_score(),
138 open OUT, '>>', ($todo == 1) ? $spam_mailbox : $cross_mailbox
139 or die "Could not open assassinated: $!";
140 print OUT $headers or die "print assassinated: $!";
142 print OUT "X-CrossAssassin-Score: $ca_score\n"
143 or die "print assassinated: $!";
145 print OUT "\n" or die "print assassinated: $!";
146 $body =~ s/^From />From /gm;
147 print OUT $body or die "print assassinated: $!";
148 close OUT or die "Close assassinated: $!";
149 unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
152 print "$nseen\n$out\n";
153 $status->finish() unless($seen);