1# <@LICENSE> 2# Licensed to the Apache Software Foundation (ASF) under one or more 3# contributor license agreements. See the NOTICE file distributed with 4# this work for additional information regarding copyright ownership. 5# The ASF licenses this file to you under the Apache License, Version 2.0 6# (the "License"); you may not use this file except in compliance with 7# the License. You may obtain a copy of the License at: 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# </@LICENSE> 17 18=head1 NAME 19 20Mail::SpamAssassin::Bayes - support for learning classifiers 21 22=head1 DESCRIPTION 23 24This is the general class used to train a learning classifier with new samples 25of spam and ham mail, and classify based on prior training. 26 27Prior to version 3.3.0, the default Bayes implementation was here; if you're 28looking for information on that, it has moved to 29C<Mail::SpamAssassin::Plugin::Bayes>. 30 31=cut 32 33package Mail::SpamAssassin::Bayes; 34 35use strict; 36use warnings; 37# use bytes; 38use re 'taint'; 39 40use Mail::SpamAssassin; 41use Mail::SpamAssassin::PerMsgStatus; 42use Mail::SpamAssassin::Logger; 43use Mail::SpamAssassin::Util qw(untaint_var); 44 45our @ISA = qw(); 46 47########################################################################### 48 49sub new { 50 my $class = shift; 51 $class = ref($class) || $class; 52 53 my ($main) = @_; 54 my $self = { 55 'main' => $main, 56 'conf' => $main->{conf}, 57 'use_ignores' => 1, 58 }; 59 bless ($self, $class); 60 61 $self->{main}->call_plugins("learner_new"); 62 $self; 63} 64 65########################################################################### 66 67sub finish { 68 my $self = shift; 69 # we don't need to do the plugin; Mail::SpamAssassin::finish() does 70 # that for us 71 %{$self} = (); 72} 73 74########################################################################### 75 76# force the Bayes dbs to be closed, if they haven't already been; called 77# at the end of scan operation, or when switching between user IDs, 78# or when C<Mail::SpamAssassin::finish_learner()> is called. 79# 80sub force_close { 81 my $self = shift; 82 my $quiet = shift; 83 $self->{main}->call_plugins("learner_close", { quiet => $quiet }); 84} 85 86########################################################################### 87 88sub ignore_message { 89 my ($self,$PMS) = @_; 90 91 return 0 unless $self->{use_ignores}; 92 93 my $ig_from = $self->{main}->call_plugins ("check_wb_list", 94 { permsgstatus => $PMS, type => 'from', list => 'bayes_ignore_from' }); 95 my $ig_to = $self->{main}->call_plugins ("check_wb_list", 96 { permsgstatus => $PMS, type => 'to', list => 'bayes_ignore_to' }); 97 98 my $ignore = $ig_from || $ig_to; 99 dbg("bayes: not using bayes, bayes_ignore_from or _to rule") if $ignore; 100 return $ignore; 101} 102 103########################################################################### 104 105sub learn { 106 my ($self, $isspam, $msg, $id) = @_; 107 return unless $self->{conf}->{use_learner}; 108 return unless defined $msg; 109 110 if( $self->{use_ignores} ) # Remove test when PerMsgStatus available. 111 { 112 # DMK, koppel@ece.lsu.edu: Hoping that the ultimate fix to bug 2263 will 113 # make it unnecessary to construct a PerMsgStatus here. 114 my $PMS = Mail::SpamAssassin::PerMsgStatus->new($self->{main}, $msg); 115 my $ignore = $self->ignore_message($PMS); 116 $PMS->finish(); 117 return 0 if $ignore; 118 } 119 120 return $self->{main}->call_plugins("learn_message", { isspam => $isspam, msg => $msg, id => $id }); 121} 122 123########################################################################### 124 125sub forget { 126 my ($self, $msg, $id) = @_; 127 return unless $self->{conf}->{use_learner}; 128 return unless defined $msg; 129 return $self->{main}->call_plugins("forget_message", { msg => $msg, id => $id }); 130} 131 132########################################################################### 133 134sub sync { 135 my ($self, $sync, $expire, $opts) = @_; 136 return 0 unless $self->{conf}->{use_learner}; 137 138 if ($sync) { 139 $self->{main}->call_plugins("learner_sync", $opts ); 140 } 141 if ($expire) { 142 $self->{main}->call_plugins("learner_expire_old_training", $opts ); 143 } 144 145 return 0; 146} 147 148########################################################################### 149 150sub is_scan_available { 151 my $self = shift; 152 return 0 unless $self->{conf}->{use_learner}; 153 return $self->{main}->call_plugins("learner_is_scan_available"); 154} 155 156########################################################################### 157 158sub dump_bayes_db { 159 my($self, $magic, $toks, $regex) = @_; 160 return 0 unless $self->{conf}->{use_learner}; 161 return $self->{main}->call_plugins("learner_dump_database", { 162 magic => $magic, toks => $toks, regex => $regex }); 163} 164 1651; 166