]> git.donarmstrong.com Git - debbugs.git/blob - scripts/spamscan.in
15a4c64273d37c1fc1ef6485b9ad525c4e85c040
[debbugs.git] / scripts / spamscan.in
1 #! /usr/bin/perl -T
2 # $Id: spamscan.in,v 1.2 2004/01/13 19:01:13 cjwatson Exp $
3 #
4 # Usage: spamscan
5 #
6 # Performs SpamAssassin checks on a message before allowing it through to
7 # the main incoming queue.
8 #
9 # Uses up: incoming/S<code><bugnum>.nn
10 # Temps:   incoming/R.nn
11 # Creates: incoming/I.nn
12 # Stop:    spamscan-stop
13
14 $config_path = '/etc/debbugs';
15 $lib_path = '/usr/lib/debbugs';
16
17 require "$config_path/config";
18 require "$lib_path/errorlib";
19 $ENV{PATH} = $lib_path . ':' . $ENV{PATH};
20
21 chdir $gSpoolDir or die "chdir spool: $!\n";
22 push @INC, $lib_path;
23
24 use Mail::SpamAssassin;
25 use Mail::SpamAssassin::NoMailAudit;
26
27 umask 002;
28
29 my $user_prefs = "$ENV{HOME}/.spamassassin/user_prefs";
30 my $user_prefs_time;
31 if (-e $user_prefs) {
32     $user_prefs_time = (stat $user_prefs)[9];
33 }
34
35 my $spam = Mail::SpamAssassin->new({
36     dont_copy_prefs => 1,
37     site_rules_filename => $gSpamRulesDir,
38     userprefs_filename => $user_prefs,
39     local_tests_only => ($gSpamLocalTestsOnly || 0),
40     debug => ($ENV{DEBBUGS_SPAM_DEBUG} || 0),
41 });
42 $spam->compile_now(1); # use all user preferences
43
44 $| = 1;
45
46 my @ids;
47 my %fudged;
48
49 sub header_or_empty ($$) {
50     my ($mail, $hdr) = @_;
51     my $value = $mail->get_header($hdr);
52     if (defined $value) {
53         chomp $value;
54         return $value;
55     }
56     return '';
57 }
58
59 &filelock('incoming-spamscan');
60 for (;;) {
61     if (-f 'spamscan-stop') {
62         print STDERR "spamscan-stop file created\n";
63         last;
64     }
65     if (-e $user_prefs) {
66         if ($user_prefs_time != (stat $user_prefs)[9]) {
67             # stop and wait to be re-invoked from cron
68             last;
69         }
70     }
71
72     if (!@ids) {
73         opendir DIR, 'incoming' or die "opendir incoming: $!";
74         while (defined($_ = readdir DIR)) {
75             push @ids, $1 if /^S(.*)/;
76         }
77         last unless @ids;
78         @ids = sort @ids;
79     }
80
81     my $nf = @ids;
82     my $id = shift @ids;
83     unless (rename "incoming/S$id", "incoming/R$id") {
84         if ($fudged{$id}) {
85             die "$id already fudged once! $!\n";
86         }
87         $fudged{$id} = 1;
88         next;
89     }
90
91     print "[$nf] $id scanning ...\n" or die "print log: $!";
92
93     open MESSAGE, "< incoming/R$id" or die "open incoming/R$id: $!";
94     my @textarray;
95     # Kludge to work around Received: then From_ weirdness in receive;
96     # remove when receive is fixed? We may continue to need it for
97     # reprocessing old messages.
98     $textarray[0] = <MESSAGE>;
99     if ($textarray[0] =~ /^Received:/) {
100         my $maybefrom = <MESSAGE>;
101         if ($maybefrom =~ /^From /) {
102             $textarray[1] = $textarray[0];
103             $textarray[0] = $maybefrom;
104         } else {
105             $textarray[1] = $maybefrom;
106         }
107     }
108     push @textarray, <MESSAGE>;
109     close MESSAGE;
110     my $mail = Mail::SpamAssassin::NoMailAudit->new(data => \@textarray);
111     $mail->{noexit} = 1;
112
113     print "  From: ", header_or_empty($mail, 'From'), "\n";
114     print "  Subject: ", header_or_empty($mail, 'Subject'), "\n";
115     print "  Message-Id: ", header_or_empty($mail, 'Message-Id'), "\n";
116     my $status = $spam->check($mail);
117     $status->rewrite_mail();
118
119     if ($status->is_spam()) {
120         $mail->accept($gSpamMailbox);
121         unlink "incoming/R$id" or warn "unlink incoming/R$id: $!";
122         printf "  spam %.1f/%.1f\n",
123                $status->get_hits(), $status->get_required_hits()
124             or die "printf log: $!";
125     } else {
126         open OUT, "> incoming/I$id" or die "open incoming/I$id: $!";
127         print OUT $mail->as_string() 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         printf "  ok %.1f/%.1f\n",
131                $status->get_hits(), $status->get_required_hits()
132             or die "printf log: $!";
133     }
134
135     $status->finish();
136 }
137 &unfilelock;
138
139 exit 0;