1 |
douglas |
811 |
#!/usr/bin/perl |
2 |
|
|
# False Positive |
3 |
|
|
# |
4 |
|
|
# Douglas Thrift |
5 |
|
|
# |
6 |
|
|
# $Id$ |
7 |
|
|
|
8 |
|
|
use strict; |
9 |
|
|
use warnings; |
10 |
|
|
|
11 |
douglas |
829 |
use Mail::Cclient; |
12 |
douglas |
811 |
use Mail::SpamAssassin; |
13 |
douglas |
829 |
use POSIX qw(:signal_h); |
14 |
douglas |
811 |
|
15 |
douglas |
829 |
my $error; |
16 |
|
|
my $debug = 0; |
17 |
|
|
my @messages; |
18 |
|
|
my $critical = 0; |
19 |
|
|
my $set = POSIX::SigSet->new(&POSIX::SIGHUP, &POSIX::SIGINT); |
20 |
douglas |
912 |
my $server = '{mail.douglasthrift.net/tls/novalidate-cert}'; |
21 |
|
|
my $falsepositive = "${server}Spam.False Positive"; |
22 |
|
|
my $inbox = "$server"; |
23 |
douglas |
811 |
|
24 |
douglas |
829 |
for my $arg (@ARGV) |
25 |
douglas |
811 |
{ |
26 |
douglas |
829 |
if ($arg eq "-debug") |
27 |
|
|
{ |
28 |
|
|
$debug = 1; |
29 |
|
|
} |
30 |
|
|
else |
31 |
|
|
{ |
32 |
|
|
print "Usage: $0 [-debug]\n"; |
33 |
|
|
|
34 |
|
|
exit 1; |
35 |
|
|
} |
36 |
douglas |
811 |
} |
37 |
|
|
|
38 |
douglas |
912 |
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 |
douglas |
811 |
|
40 |
douglas |
912 |
my $positive = Mail::Cclient->new($falsepositive, $debug ? 'debug' : ()) or die "$0: $error\n"; |
41 |
douglas |
829 |
|
42 |
|
|
$positive->search(SEARCH => 'UNFLAGGED'); |
43 |
|
|
|
44 |
douglas |
912 |
if ($#messages != -1) |
45 |
|
|
{ |
46 |
|
|
my $assassin = Mail::SpamAssassin->new($debug ? {debug => 'all'} : {}); |
47 |
douglas |
829 |
|
48 |
douglas |
912 |
$positive->fetch_flags(join(',', @messages)); |
49 |
douglas |
829 |
|
50 |
douglas |
912 |
for my $message (@messages) |
51 |
douglas |
829 |
{ |
52 |
douglas |
912 |
my $message_ = $assassin->remove_spamassassin_markup($assassin->parse($positive->fetch_message($message))); |
53 |
douglas |
829 |
|
54 |
douglas |
912 |
# XXX: stupid SpamAssassin! |
55 |
|
|
if ($message_ =~ /^((?:[!-9;-~]+:[^\r\n]+\n(?:[ \t][^\r\n]+\n)*)+\n)(.*)$/s) |
56 |
|
|
{ |
57 |
|
|
my ($header, $body) = ($1, $2); |
58 |
douglas |
829 |
|
59 |
douglas |
912 |
$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 |
douglas |
829 |
} |
67 |
|
|
} |
68 |
|
|
|
69 |
|
|
$positive->close(); |
70 |
|
|
|
71 |
douglas |
833 |
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 |
douglas |
829 |
sub mm_searched |
112 |
|
|
{ |
113 |
|
|
$messages[$#messages + 1] = $_[1]; |
114 |
|
|
} |
115 |
|
|
|
116 |
douglas |
833 |
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 |
douglas |
829 |
sub mm_log |
133 |
|
|
{ |
134 |
|
|
if ($debug) |
135 |
|
|
{ |
136 |
douglas |
833 |
print STDERR "$_[1]: $_[0]\n"; |
137 |
douglas |
829 |
} |
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 |
douglas |
912 |
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 |
douglas |
829 |
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 |
douglas |
833 |
print STDERR "diskerror: $_[1]" . $_[2] ? " serious\n" : "\n"; |
183 |
douglas |
829 |
|
184 |
|
|
return 1; |
185 |
|
|
} |
186 |
douglas |
831 |
|
187 |
|
|
sub mm_fatal |
188 |
|
|
{ |
189 |
douglas |
833 |
print STDERR "fatal: $_[0]\n"; |
190 |
douglas |
831 |
} |