]> git.donarmstrong.com Git - debbugs.git/blob - scripts/spamscan-sa
fix plural of {src,bin}packages? in updatesql
[debbugs.git] / scripts / spamscan-sa
1 #! /usr/bin/perl
2 # spamassassin handling split from spamscan
3 #
4
5 # unfortunatly we can't use strict;
6
7 use warnings;
8 use strict;
9 use Mail::CrossAssassin;
10 use Mail::SpamAssassin;
11
12 use Debbugs::Config qw(:config);
13 # New versions of debbugs will not allow use in /etc/debbugs/config
14 use POSIX qw(strftime);
15 my $spam_mailbox = strftime($config{spam_mailbox},gmtime);
16 my $cross_mailbox = strftime($config{spam_crossassassin_mailbox},gmtime);
17
18 umask 002;
19 $| = 1;
20 STDOUT->autoflush(1);
21
22 sub header_or_empty ($$) {
23     my ($mail, $hdr) = @_;
24     my $value = $mail->get_header($hdr);
25     if (defined $value) {
26         chomp $value;
27         # replace newlines with '\n'
28         $value =~ s/\n/\\n/g;
29         return $value;
30     }
31     return '';
32 }
33
34 my $spam = Mail::SpamAssassin->new({
35         dont_copy_prefs => 1,
36         site_rules_filename => $config{spam_rules_dir},
37         userprefs_filename => $config{spam_user_prefs},
38                 local_tests_only => ($config{spam_local_tests_only} || 0),
39                 debug => ($ENV{DEBBUGS_SPAM_DEBUG} || 0),
40 });
41 $spam->compile_now(1); # use all user preferences
42
43 while (my $id = <STDIN>) {
44     chomp $id;
45     my $nf = <STDIN>;
46     if (not defined $nf) {
47          die "Could not read nf: $!";
48     }
49     chomp $nf;
50     unless (rename "incoming/S$id", "incoming/R$id") {
51         die "Could not rename incoming/S$id: $!";
52     }
53     my $out = "[$nf] $id scanning ...\n";
54     open MESSAGE, "< incoming/R$id" or die "open incoming/R$id: $!";
55     # Kludge to work around Received: then From_ weirdness in receive;
56     # remove when receive is fixed? We may continue to need it for
57     # reprocessing old messages.
58     my @textarray = <MESSAGE>;
59     if ($textarray[0] !~ /^From /) {
60         ($textarray[0], $textarray[1]) = ($textarray[1], $textarray[0]);
61     }
62     close MESSAGE;
63     my $mail = $spam->parse(\@textarray);
64     
65     my $messageid = header_or_empty($mail, 'Message-Id');
66     $out .= "  From: " . header_or_empty($mail, 'From') . "\n";
67     $out .= "  Subject: ". header_or_empty($mail, 'Subject') . "\n";
68     $out .= "  Date: " . header_or_empty($mail, 'Date') . "\n";
69     $out .= "  Message-Id: $messageid\n";
70     my $keys = ca_keys($mail->get_body);
71     print  "$keys\n$messageid\n"
72         or die "Could not send keys: $!";
73     my $ca_score = <STDIN>;
74     die "Could not read ca_score: $!" if not defined $ca_score;
75     chomp $ca_score;
76     my $todo = 0;
77     my ($headers, $body);
78     my $seen = <STDIN>;
79     die "Child could not read seen: $!" if not defined $seen;
80     chomp $seen;
81     my $status;
82     my $nseen = $seen;
83     if ($seen) {
84         $todo = 1;
85         $headers = join('',$mail->get_all_headers());
86         $body = join('', @{$mail->get_body()});
87         $out .= "  spam $seen duplicate\n";
88     } else {
89         $status = $spam->check($mail);
90         ($headers, $body) = split /\n\n/, $status->rewrite_mail(), 2;
91         $headers .= "\n";
92         $body .= "\n";
93         
94         if ($status->is_spam()) {
95             $todo = 1;
96             my $score = sprintf "%.1f/%.1f %d",
97                     $status->get_score(), $status->get_required_score(),
98                     $ca_score;
99             $out .= "  spam $score\n";
100             $nseen = $score;
101         } elsif ($status->get_score() > 0 && $ca_score >= $config{spam_max_cross}) {
102             $todo = 2;
103             my $score = sprintf "%.1f/%.1f %d",
104             $status->get_score(), $status->get_required_score(), $ca_score;
105             $out .= "  spam $score\n";
106             $nseen = $score;
107         } else {
108             my ($before, $received, $after) = $headers =~
109                 /(^.*?)(^Received\: \(at .*?\n)(.*$)/ms;
110             open OUT, "> incoming/I$id" or die "open incoming/I$id: $!";
111             print OUT $received . $before . $after
112                 or die "print incoming/I$id: $!";
113             if ($ca_score > 1) {
114                 print OUT "X-CrossAssassin-Score: $ca_score\n"
115                     or die "print incoming/I$id: $!";
116             }
117             print OUT "\n" or die "print incoming/I$id: $!";
118             print OUT $body or die "print incoming/I$id: $!";
119             close OUT or die "close incoming/I$id: $!";
120             unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
121             $out .= sprintf "  ok %.1f/%.1f %d\n",
122             $status->get_score(), $status->get_required_score(),
123                     $ca_score;
124         }
125     }
126     print "$todo\n";
127     <STDIN>;
128     if ($todo) {
129         open OUT, '>>', ($todo == 1) ? $spam_mailbox : $cross_mailbox
130             or die "Could not open assassinated: $!";
131         print OUT $headers or die "print assassinated: $!";
132         if ($ca_score > 1) {
133             print OUT "X-CrossAssassin-Score: $ca_score\n"
134                 or die "print assassinated: $!";
135         }
136         print OUT "\n" or die "print assassinated: $!";
137         $body =~ s/^From />From /gm;
138         print OUT $body or die "print assassinated: $!";
139         close OUT or die "Close assassinated: $!";
140         unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
141     }
142     $out =~ tr/\n/\r/;
143     print "$nseen\n$out\n";
144     $status->finish() unless($seen);
145     $mail->finish();
146 }