Server IP : 85.214.239.14 / Your IP : 3.144.255.247 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /proc/self/root/usr/share/perl5/Mail/SpamAssassin/Plugin/ |
Upload File : |
# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you 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 Mail::SpamAssassin::Plugin::Shortcircuit - short-circuit evaluation for certain rules =head1 SYNOPSIS loadplugin Mail::SpamAssassin::Plugin::Shortcircuit report Content analysis details: (_SCORE_ points, _REQD_ required, s/c _SCTYPE_) add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ shortcircuit=_SCTYPE_ autolearn=_AUTOLEARN_ version=_VERSION_" =head1 DESCRIPTION This plugin implements simple, test-based shortcircuiting. Shortcircuiting a test will force all other pending rules to be skipped, if that test is hit. In addition, a symbolic rule, C<SHORTCIRCUIT>, will fire. Recommended usage is to use C<priority> to set rules with strong S/O values (ie. 1.0) to be run first, and make instant spam or ham classification based on that. =cut package Mail::SpamAssassin::Plugin::Shortcircuit; use Mail::SpamAssassin::Plugin; use Mail::SpamAssassin::Logger; use strict; use warnings; # use bytes; use re 'taint'; our @ISA = qw(Mail::SpamAssassin::Plugin); sub new { my $class = shift; my $mailsaobject = shift; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsaobject); bless ($self, $class); $self->register_eval_rule("check_shortcircuit"); # type does not matter $self->set_config($mailsaobject->{conf}); return $self; } sub check_shortcircuit { return 0; } # never used sub set_config { my($self, $conf) = @_; my @cmds; =head1 CONFIGURATION SETTINGS The following configuration settings are used to control shortcircuiting: =over 4 =item shortcircuit SYMBOLIC_TEST_NAME {ham|spam|on|off} Shortcircuiting a test will force all other pending rules to be skipped, if that test is hit. Recommended usage is to use C<priority> to set rules with strong S/O values (ie. 1.0) to be run first, and make instant spam or ham classification based on that. To override a test that uses shortcircuiting, you can set the classification type to C<off>. Note that DNS and other network lookups are launched when SA reaches priority -100. If you want to shortcircuit scanning before any network queries are sent, you need to set lower than -100 priority to any such rule, like -200 as in the examples below. Shortcircuited test will be automatically set to priority -200, but only if the original priority is unchanged at default 0. =over 4 =item on Shortcircuits the rest of the tests, but does not make a strict classification of spam or ham. Rather, it uses the default score for the rule being shortcircuited. This would allow you, for example, to define a rule such as body TEST /test/ describe TEST test rule that scores barely over spam threshold score TEST 5.5 priority TEST -200 shortcircuit TEST on The result of a message hitting the above rule would be a final score of 5.5, as opposed to 100 (default) if it were classified as spam. =item off Disables shortcircuiting on said rule. =item spam Shortcircuit the rule using a set of defaults; override the default score of this rule with the score from C<shortcircuit_spam_score>, set the C<noautolearn> tflag, and set priority to C<-200>. In other words, equivalent to: shortcircuit TEST on priority TEST -200 score TEST 100 tflags TEST noautolearn =item ham Shortcircuit the rule using a set of defaults; override the default score of this rule with the score from C<shortcircuit_ham_score>, set the C<noautolearn> and C<nice> tflags, and set priority to C<-200>. In other words, equivalent to: shortcircuit TEST on priority TEST -200 score TEST -100 tflags TEST noautolearn nice =back =cut push (@cmds, { setting => 'shortcircuit', code => sub { my ($self, $key, $value, $line) = @_; unless (defined $value && $value !~ /^$/) { return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; } local($1,$2); unless ($value =~ /^(\w+)\s+(\w+)$/) { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } my ($rule, $type) = ($1, $2); if ($type eq "ham" || $type eq "spam") { dbg("shortcircuit: adding $rule using abbreviation $type"); # set the defaults: $self->{shortcircuit}->{$rule} = $type; # don't override existing priority unless it's default 0 $self->{priority}->{$rule} ||= -200; my $tf = $self->{tflags}->{$rule}; $self->{tflags}->{$rule} = ($tf ? $tf." " : "") . ($type eq 'ham' ? "nice " : "") . "noautolearn"; } elsif ($type eq "on") { $self->{shortcircuit}->{$rule} = "on"; } elsif ($type eq "off") { delete $self->{shortcircuit}->{$rule}; } else { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } } }); =item shortcircuit_spam_score n.nn (default: 100) When shortcircuit is used on a rule, and the shortcircuit classification type is set to C<spam>, this value should be applied in place of the default score for that rule. =cut push (@cmds, { setting => 'shortcircuit_spam_score', default => 100, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); =item shortcircuit_ham_score n.nn (default: -100) When shortcircuit is used on a rule, and the shortcircuit classification type is set to C<ham>, this value should be applied in place of the default score for that rule. =cut push (@cmds, { setting => 'shortcircuit_ham_score', default => -100, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); $conf->{parser}->register_commands(\@cmds); } =back =head1 TAGS The following tags are added to the set available for use in reports, headers etc.: _SC_ shortcircuit status (classification and rule name) _SCRULE_ rulename that caused the shortcircuit _SCTYPE_ shortcircuit classification ("spam", "ham", "default", "none") =cut sub hit_rule { my ($self, $params) = @_; my $scan = $params->{permsgstatus}; my $rule = $params->{rulename}; # don't s/c if we're linting return if ($self->{main}->{lint_rules}); # don't s/c if we're in compile_now() return if ($self->{am_compiling}); my $sctype = $scan->{conf}->{shortcircuit}->{$rule}; return unless $sctype; my $conf = $scan->{conf}; my $score = $params->{score}; $scan->{shortcircuit_rule} = $rule; my $scscore; if ($sctype eq 'on') { # guess by rule score dbg("shortcircuit: s/c due to $rule, using score of $score"); $scan->{shortcircuit_type} = ($score < 0 ? 'ham' : 'spam'); $scscore = ($score < 0) ? -0.0001 : 0.0001; } else { $scan->{shortcircuit_type} = $sctype; if ($sctype eq 'ham') { $score = $conf->{shortcircuit_ham_score}; } else { $score = $conf->{shortcircuit_spam_score}; } dbg("shortcircuit: s/c $sctype due to $rule, using score of $score"); $scscore = $score; } $scan->{shortcircuited} = 1; # bug 5256: if we short-circuit, don't do auto-learning $scan->{disable_auto_learning} = 1; $scan->got_hit('SHORTCIRCUIT', '', score => $scscore); } sub parsed_metadata { my ($self, $params) = @_; my $scan = $params->{permsgstatus}; $scan->set_tag ('SC', sub { my $rule = $scan->{shortcircuit_rule}; my $type = $scan->{shortcircuit_type}; return "$rule ($type)" if ($rule); return "no"; }); $scan->set_tag ('SCRULE', sub { my $rule = $scan->{shortcircuit_rule}; return ($rule || "none"); }); $scan->set_tag ('SCTYPE', sub { my $type = $scan->{shortcircuit_type}; return ($type || "no"); }); $scan->set_spamd_result_item (sub { "shortcircuit=".$scan->get_tag("SCTYPE"); }); } sub have_shortcircuited { my ($self, $params) = @_; return (exists $params->{permsgstatus}->{shortcircuit_type}) ? 1 : 0; } sub compile_now_start { my ($self, $params) = @_; $self->{am_compiling} = 1; } sub compile_now_finish { my ($self, $params) = @_; delete $self->{am_compiling}; } 1; =head1 SEE ALSO C<https://issues.apache.org/SpamAssassin/show_bug.cgi?id=3109> =cut