-
Notifications
You must be signed in to change notification settings - Fork 5
/
dspam.pm
207 lines (155 loc) · 5.28 KB
/
dspam.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# <@LICENSE>
# Copyright 2004 Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# </@LICENSE>
=head1 NAME
dspam - dspam plugin
=head1 SYNOPSIS
loadplugin Mail::SpamAssassin::Plugin::dspam
add_header all DSPAM-Result _DSPAMRESULT_
=head1 REVISION
$Revision: 1.4 $
=head1 AUTHOR
Eric Lubow <[email protected]>
$Id: dspam.pm,v 1.4 2006-12-09 02:33:08 eric Exp $
=head1 DESCRIPTION
To use this plugin, write the above two lines in the synopsis to
C</etc/spamassassin/dspamplugin.cf>.
DSPAM is a scalable and open-source content-based spam filter designed for
multi-user enterprise systems. On a properly configured system, many users
experience results between 99.5% - 99.95%, or one error for every 200 to
2000 messages. DSPAM supports many different MTAs and can also be deployed
as a stand-alone SMTP appliance. For developers, the DSPAM core engine
(libdspam) can be easily incorporated directly into applications for drop-in
filtering (GPL applies; commercial licenses are also available).
To find out more about dspam, see http://dspam.nuclearelephant.com/
=cut
package Mail::SpamAssassin::Plugin::dspam;
use Mail::SpamAssassin::Plugin;
use strict;
use warnings;
use bytes;
use vars qw(@ISA);
@ISA = qw(Mail::SpamAssassin::Plugin);
# constructor: register the eval rule
sub new {
my $class = shift;
my $mailsaobject = shift;
# some boilerplate...
$class = ref($class) || $class;
my $self = $class->SUPER::new($mailsaobject);
bless ($self, $class);
$self->set_config($mailsaobject->{conf});
return $self;
}
sub dbg { Mail::SpamAssassin::dbg (@_); }
sub set_config {
my ($self, $conf) = @_;
my @cmds = ();
=head1 CONFIG OPTIONS
The following options can be used with the dspam module.
=over 4
=item use_dspam ( 0 | 1 ) (default: 1)
Turn the module on.
=cut
push (@cmds, {
setting => 'use_dspam',
default => 1,
type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
});
=item ignore_dspam_wl ( 0 | 1 ) (default: 0)
dspam has a separate whitelisting functionality than spamassassin (as
they are separate programs). You have the option to assign a value to
dspam's whitelist result or ignore it. The value of DSPAM_AWL specified
in the dspam.cf file is ignored if this value is one.
=cut
push (@cmds, {
setting => 'ignore_dspam_wl',
default => 0,
type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL
});
=back
=cut
$conf->{parser}->register_commands(\@cmds);
}
sub parsed_metadata {
my ($self, $opts) = @_;
my ($pms) = $opts->{permsgstatus};
my %dspam = ( );
# Go home cause we're not wanted
return unless
($self->{main}->{conf}->{use_dspam} == 1);
dbg("dspam is on, so time to run");
# Get the dspam information and pull it into a hash
$dspam{Result} = $pms->get ("X-DSPAM-Result");
$dspam{Confidence} = $pms->get ("X-DSPAM-Confidence");
$dspam{Probability} = $pms->get ("X-DSPAM-Probability");
# We don't have everything we need to continue, so just die already
do {
dbg("dspam: Couldn't get all the data from the message headers");
return;
} unless
(defined($dspam{Result}) && defined($dspam{Confidence}) &&
defined($dspam{Probability}));
dbg("dspam Result: ". $dspam{Result});
if ($dspam{Result} =~ /^(Innocent|Spam)$/) {
$dspam{"SA-Score"} =
Calculate($pms->get("X-DSPAM-Confidence"),$pms->get("X-DSPAM-Probability"));
}
elsif ($dspam{Result} =~ /^Whitelisted$/) {
if ($self->{main}->{conf}->{ignore_dspam_wl} == 1) {
$dspam{"SA-Score"} = "DSPAM_NOSCORE";
} else { $dspam{"SA-Score"} = "DSPAM_AWL"; }
}
else { $dspam{"SA-Score"} = "DSPAM_ERROR"; }
dbg("dspam: \$dspam{\"SA-Score\"}: ". $dspam{"SA-Score"});
# Add it to the msg for posterity
$pms->set_tag("DSPAMRESULT", $dspam{"SA-Score"});
dbg("dspam: Add the header for posterity");
# Add it to the msg to be worked with
$pms->{msg}->put_metadata('DSPAM-Result',$dspam{"SA-Score"});
$pms->{msg}->put_metadata('X-Spam-DSPAM-Result',$dspam{"SA-Score"});
dbg("dspam: Add to the metadata for use");
return 0;
}
sub Calculate {
my ($conf, $prob) = @_;
my ($outcome) = 0.00;
my ($rv) = "DSPAM_";
my $t_prob = ((($prob - 0.5) * 2) * 100);
if ($t_prob > 0) { $rv .= "SPAM_"; }
elsif ($t_prob <= 0) { $rv .= "HAM_"; $t_prob *= -1; }
else { $rv .= "ERROR"; return $rv; } # This should never be reached
# Correctly figure out the $outcome
$outcome = (($t_prob + ($conf*100)) / 2);
dbg("dspam Outcome: $outcome");
if ($outcome > 0 && $outcome < 101) {
if ($outcome > 3 && $outcome < 7) {
$rv .= '05';
}
else {
my $sol = (int(($outcome / 10) + .49) * 10);
if ($outcome > 93) {
$sol -= $outcome > 97 ? 1 : 5;
}
$rv .= $sol;
}
}
else {
$rv = 'DSPAM_ERROR';
}
# Must return either (DSPAM_HAM_XX or DSPAM_SPAM_xx)
return $rv;
}
1;