1 |
#!/usr/bin/perl |
2 |
# False Positive |
3 |
# |
4 |
# Douglas Thrift |
5 |
# |
6 |
# $Id$ |
7 |
|
8 |
use strict; |
9 |
use warnings; |
10 |
|
11 |
use Mail::Cclient; |
12 |
use Mail::SpamAssassin; |
13 |
use POSIX qw(:signal_h); |
14 |
|
15 |
my $error; |
16 |
my $debug = 0; |
17 |
my @messages; |
18 |
my $critical = 0; |
19 |
my $set = POSIX::SigSet->new(&POSIX::SIGHUP, &POSIX::SIGINT); |
20 |
my $server = '{mail.douglasthrift.net/tls/novalidate-cert}'; |
21 |
my $falsepositive = "${server}Spam.False Positive"; |
22 |
my $inbox = "$server"; |
23 |
|
24 |
for my $arg (@ARGV) |
25 |
{ |
26 |
if ($arg eq "-debug") |
27 |
{ |
28 |
$debug = 1; |
29 |
} |
30 |
else |
31 |
{ |
32 |
print "Usage: $0 [-debug]\n"; |
33 |
|
34 |
exit 1; |
35 |
} |
36 |
} |
37 |
|
38 |
Mail::Cclient::set_callback(flags => \&mm_flags, status => \&mm_status, searched => \&mm_searched, exists => \&mm_exists, notify => \&mm_notify, log => \&mm_log, dlog => \&mm_dlog, login => \&mm_login, critical => \&mm_critical, nocritical => \&mm_nocritical, diskerror => \&mm_diskerror, fatal => \&mm_fatal); |
39 |
|
40 |
my $positive = Mail::Cclient->new($falsepositive, $debug ? 'debug' : ()) or die "$0: $error\n"; |
41 |
|
42 |
$positive->search(SEARCH => 'UNFLAGGED'); |
43 |
|
44 |
if ($#messages != -1) |
45 |
{ |
46 |
my $assassin = Mail::SpamAssassin->new($debug ? {debug => 'all'} : {}); |
47 |
|
48 |
$positive->fetch_flags(join(',', @messages)); |
49 |
|
50 |
for my $message (@messages) |
51 |
{ |
52 |
my $message_ = $assassin->remove_spamassassin_markup($assassin->parse($positive->fetch_message($message))); |
53 |
|
54 |
# XXX: stupid SpamAssassin! |
55 |
if ($message_ =~ /^((?:[!-9;-~]+:[^\r\n]+\n(?:[ \t][^\r\n]+\n)*)+\n)(.*)$/s) |
56 |
{ |
57 |
my ($header, $body) = ($1, $2); |
58 |
|
59 |
$header =~ s/\n/\r\n/gs; |
60 |
|
61 |
$message_ = $header . $body; |
62 |
} |
63 |
|
64 |
$positive->append($inbox, $message_, $positive->elt($message)->imapdate); |
65 |
$positive->setflag($message, '\Flagged'); |
66 |
} |
67 |
} |
68 |
|
69 |
$positive->close(); |
70 |
|
71 |
sub mm_flags |
72 |
{ |
73 |
if ($debug) |
74 |
{ |
75 |
print STDERR "flags: $_[1]\n"; |
76 |
} |
77 |
} |
78 |
|
79 |
sub mm_status |
80 |
{ |
81 |
if ($debug) |
82 |
{ |
83 |
print STDERR "status: $_[1]\n"; |
84 |
|
85 |
for (my $index; $index != $#_; $index += 2) |
86 |
{ |
87 |
if ($_[$index] eq 'messages') |
88 |
{ |
89 |
print STDERR " messages: $_[$index + 1]\n"; |
90 |
} |
91 |
elsif ($_[$index] eq 'recent') |
92 |
{ |
93 |
print STDERR " recent: $_[$index + 1]\n"; |
94 |
} |
95 |
elsif ($_[$index] eq 'unseen') |
96 |
{ |
97 |
print STDERR " unseen: $_[$index + 1]\n"; |
98 |
} |
99 |
elsif ($_[$index] eq 'uidnext') |
100 |
{ |
101 |
print STDERR " uid next: $_[$index + 1]\n"; |
102 |
} |
103 |
elsif ($_[$index] eq 'uidvalidity') |
104 |
{ |
105 |
print STDERR " uid validity: $_[$index + 1]\n"; |
106 |
} |
107 |
} |
108 |
} |
109 |
} |
110 |
|
111 |
sub mm_searched |
112 |
{ |
113 |
$messages[$#messages + 1] = $_[1]; |
114 |
} |
115 |
|
116 |
sub mm_exists |
117 |
{ |
118 |
if ($debug) |
119 |
{ |
120 |
print STDERR "exists: $_[1]\n"; |
121 |
} |
122 |
} |
123 |
|
124 |
sub mm_notify |
125 |
{ |
126 |
if ($debug) |
127 |
{ |
128 |
print STDERR "$_[2]: $_[1]\n"; |
129 |
} |
130 |
} |
131 |
|
132 |
sub mm_log |
133 |
{ |
134 |
if ($debug) |
135 |
{ |
136 |
print STDERR "$_[1]: $_[0]\n"; |
137 |
} |
138 |
|
139 |
if ($_[1] eq 'error') |
140 |
{ |
141 |
$error = $_[0]; |
142 |
} |
143 |
} |
144 |
|
145 |
sub mm_dlog |
146 |
{ |
147 |
print STDERR "$_[0]\n"; |
148 |
} |
149 |
|
150 |
sub mm_login |
151 |
{ |
152 |
my $user = getpwuid $<; |
153 |
|
154 |
open PASS, "$ENV{HOME}/.CreditCardReminder.pass" or die "$0: $!\n"; |
155 |
|
156 |
my $pass = <PASS>; |
157 |
|
158 |
chomp $pass; |
159 |
close PASS; |
160 |
|
161 |
return ($user, $pass); |
162 |
} |
163 |
|
164 |
sub mm_critical |
165 |
{ |
166 |
if (!$critical++) |
167 |
{ |
168 |
POSIX::sigprocmask(POSIX::SIG_BLOCK, $set) or die; |
169 |
} |
170 |
} |
171 |
|
172 |
sub mm_nocritical |
173 |
{ |
174 |
if (!--$critical) |
175 |
{ |
176 |
POSIX::sigprocmask(POSIX::SIG_UNBLOCK, $set) or die; |
177 |
} |
178 |
} |
179 |
|
180 |
sub mm_diskerror |
181 |
{ |
182 |
print STDERR "diskerror: $_[1]" . $_[2] ? " serious\n" : "\n"; |
183 |
|
184 |
return 1; |
185 |
} |
186 |
|
187 |
sub mm_fatal |
188 |
{ |
189 |
print STDERR "fatal: $_[0]\n"; |
190 |
} |