1 |
#!/usr/bin/perl |
2 |
# Spam Update |
3 |
# |
4 |
# Douglas Thrift |
5 |
# |
6 |
# $Id$ |
7 |
|
8 |
use strict; |
9 |
use warnings; |
10 |
|
11 |
use IMAP::Client; |
12 |
use IPC::Open2; |
13 |
use Mail::SpamAssassin; |
14 |
|
15 |
my $debug = 0; |
16 |
|
17 |
for my $arg (@ARGV) |
18 |
{ |
19 |
if ($arg eq "-debug") |
20 |
{ |
21 |
$debug = 1; |
22 |
} |
23 |
else |
24 |
{ |
25 |
print "Usage: $0 [-debug]\n"; |
26 |
|
27 |
exit 1; |
28 |
} |
29 |
} |
30 |
|
31 |
my $negative = 'Spam.False Negative'; |
32 |
my $positive = 'Spam.False Positive'; |
33 |
my $spamc = '/usr/local/bin/spamc'; |
34 |
|
35 |
print "Information: |
36 |
If you receive spam in your Inbox mailbox, copy it to the $negative mailbox. |
37 |
|
38 |
If you receive mail that is not spam in your Spam mailbox, copy it to the $positive mailbox. |
39 |
"; |
40 |
|
41 |
my $imap = new IMAP::Client; |
42 |
|
43 |
$imap->onfail('ABORT'); |
44 |
$imap->debuglevel(1) if ($debug); |
45 |
$imap->capability_checking(1); |
46 |
$imap->connect(PeerAddr => 'mail.douglasthrift.net', ConnectMethod => 'STARTTLS'); |
47 |
|
48 |
{ |
49 |
my $user = getpwuid $<; |
50 |
|
51 |
open PASS, "$ENV{HOME}/.CreditCardReminder.pass" or die "$0: $!\n"; |
52 |
|
53 |
my $pass = <PASS>; |
54 |
|
55 |
chomp $pass; |
56 |
close PASS; |
57 |
|
58 |
$imap->authenticate($user, $pass); |
59 |
} |
60 |
|
61 |
for my $job (new Job($negative), new Job($positive)) |
62 |
{ |
63 |
$imap->select($job->mailbox); |
64 |
|
65 |
printf ' |
66 |
%s and %s from the %s mailbox: |
67 |
', ucfirst $job->learning, $job->collabing, $job->mailbox; |
68 |
|
69 |
my $messages = $imap->uidsearch('UNDELETED'); |
70 |
my $total = 0; |
71 |
my $learned = 0; |
72 |
my $collabed = 0; |
73 |
|
74 |
if (defined $messages) |
75 |
{ |
76 |
my %fetch = $imap->uidfetch($messages, {}); |
77 |
|
78 |
for my $message (values %fetch) |
79 |
{ |
80 |
++$total; |
81 |
|
82 |
my $learn = open2(\*LEARN_OUT, \*LEARN_IN, $spamc, '-L', $job->learn); |
83 |
my $collab = open2(\*COLLAB_OUT, \*COLLAB_IN, $spamc, '-C', $job->collab); |
84 |
|
85 |
print LEARN_IN $message->{BODY}->{BODY}; |
86 |
print COLLAB_IN $message->{BODY}->{BODY}; |
87 |
close LEARN_IN; |
88 |
close COLLAB_IN; |
89 |
|
90 |
my $learn_out = <LEARN_OUT>; |
91 |
my $collab_out = <COLLAB_OUT>; |
92 |
|
93 |
close LEARN_OUT; |
94 |
close COLLAB_OUT; |
95 |
chomp($learn_out, $collab_out); |
96 |
|
97 |
print "learn_out = $learn_out\ncollab_out = $collab_out\n" if ($debug); |
98 |
|
99 |
++$learned if ($learn_out eq "Message successfully un/learned"); |
100 |
++$collabed if ($collab_out eq "Message successfully reported/revoked"); |
101 |
|
102 |
$imap->uidstore($message->{UID}, '+FLAGS.SILENT', '\Deleted'); |
103 |
|
104 |
waitpid $learn, 0; |
105 |
waitpid $collab, 0; |
106 |
} |
107 |
} |
108 |
|
109 |
sub plural |
110 |
{ |
111 |
my $number = shift; |
112 |
|
113 |
return $number != 1 ? 's' : ''; |
114 |
} |
115 |
|
116 |
printf " $learned message%s %s and $collabed message%s %s ($total message%s total). |
117 |
", plural($learned), $job->learned, plural($collabed), $job->collabed, plural($total); |
118 |
} |
119 |
|
120 |
$imap->logout; |
121 |
|
122 |
{ |
123 |
package Job; |
124 |
|
125 |
sub new |
126 |
{ |
127 |
my $class = shift; |
128 |
my $self = {}; |
129 |
|
130 |
$self->{mailbox} = shift; |
131 |
$self->{negative} = $self->{mailbox} eq $negative; |
132 |
|
133 |
bless $self, $class; |
134 |
} |
135 |
|
136 |
sub learning |
137 |
{ |
138 |
my $self = shift; |
139 |
|
140 |
return $self->_learn . 'ing'; |
141 |
} |
142 |
|
143 |
sub collabing |
144 |
{ |
145 |
my $self = shift; |
146 |
|
147 |
return $self->_collab . 'ing'; |
148 |
} |
149 |
|
150 |
sub learned |
151 |
{ |
152 |
my $self = shift; |
153 |
|
154 |
return $self->_learn . 'ed'; |
155 |
} |
156 |
|
157 |
sub collabed |
158 |
{ |
159 |
my $self = shift; |
160 |
|
161 |
return $self->_collab . 'ed'; |
162 |
} |
163 |
|
164 |
sub learn |
165 |
{ |
166 |
my $self = shift; |
167 |
|
168 |
return $self->{negative} ? 'spam' : 'ham'; |
169 |
} |
170 |
|
171 |
sub collab |
172 |
{ |
173 |
my $self = shift; |
174 |
|
175 |
return $self->{negative} ? 'report' : 'revoke'; |
176 |
} |
177 |
|
178 |
sub mailbox |
179 |
{ |
180 |
my $self = shift; |
181 |
|
182 |
return $self->{mailbox}; |
183 |
} |
184 |
|
185 |
sub _learn |
186 |
{ |
187 |
my $self = shift; |
188 |
|
189 |
return ($self->{negative} ? '' : 'un') . 'learn'; |
190 |
} |
191 |
|
192 |
sub _collab |
193 |
{ |
194 |
my $self = shift; |
195 |
|
196 |
return 're' . ($self->{negative} ? 'port' : 'vok'); |
197 |
} |
198 |
} |