← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 03:09:29 2017
Reported on Mon Nov 6 13:20:45 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm
StatementsExecuted 116592 statements in 810ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
538211244ms244msMail::SpamAssassin::Conf::::is_rule_activeMail::SpamAssassin::Conf::is_rule_active
81111171ms189msMail::SpamAssassin::Conf::::__ANON__[:280]Mail::SpamAssassin::Conf::__ANON__[:280]
1901180.1ms80.1msMail::SpamAssassin::Conf::::set_ports_rangeMail::SpamAssassin::Conf::set_ports_range
7811158.6ms324msMail::SpamAssassin::Conf::::__ANON__[:2981]Mail::SpamAssassin::Conf::__ANON__[:2981]
770127131.7ms31.7msMail::SpamAssassin::Conf::::CORE:matchMail::SpamAssassin::Conf::CORE:match (opcode)
6551130.6ms233msMail::SpamAssassin::Conf::::__ANON__[:3020]Mail::SpamAssassin::Conf::__ANON__[:3020]
4591123.4ms28.2msMail::SpamAssassin::Conf::::__ANON__[:3750]Mail::SpamAssassin::Conf::__ANON__[:3750]
4651121.5ms322msMail::SpamAssassin::Conf::::__ANON__[:3174]Mail::SpamAssassin::Conf::__ANON__[:3174]
11120.4ms20.4msMail::SpamAssassin::Conf::::set_default_commandsMail::SpamAssassin::Conf::set_default_commands
11118.2ms112msMail::SpamAssassin::Conf::::BEGIN@85Mail::SpamAssassin::Conf::BEGIN@85
11115.1ms16.5msMail::SpamAssassin::Conf::::BEGIN@88Mail::SpamAssassin::Conf::BEGIN@88
1281113.5ms15.9msMail::SpamAssassin::Conf::::__ANON__[:3557]Mail::SpamAssassin::Conf::__ANON__[:3557]
30116.44ms87.4msMail::SpamAssassin::Conf::::__ANON__[:1685]Mail::SpamAssassin::Conf::__ANON__[:1685]
270115.85ms5.85msMail::SpamAssassin::Conf::::__ANON__[:2044]Mail::SpamAssassin::Conf::__ANON__[:2044]
2338415.10ms5.10msMail::SpamAssassin::Conf::::CORE:substMail::SpamAssassin::Conf::CORE:subst (opcode)
1114.32ms26.3msMail::SpamAssassin::Conf::::BEGIN@86Mail::SpamAssassin::Conf::BEGIN@86
71112.43ms24.1msMail::SpamAssassin::Conf::::__ANON__[:3052]Mail::SpamAssassin::Conf::__ANON__[:3052]
77112.22ms2.70msMail::SpamAssassin::Conf::::__ANON__[:3206]Mail::SpamAssassin::Conf::__ANON__[:3206]
27112.13ms510msMail::SpamAssassin::Conf::::__ANON__[:4145]Mail::SpamAssassin::Conf::__ANON__[:4145]
40112.08ms13.9msMail::SpamAssassin::Conf::::__ANON__[:3088]Mail::SpamAssassin::Conf::__ANON__[:3088]
192111.78ms1.78msMail::SpamAssassin::Conf::::register_eval_ruleMail::SpamAssassin::Conf::register_eval_rule
48111.52ms1.91msMail::SpamAssassin::Conf::::__ANON__[:3781]Mail::SpamAssassin::Conf::__ANON__[:3781]
1111.33ms1.63msMail::SpamAssassin::Conf::::BEGIN@90Mail::SpamAssassin::Conf::BEGIN@90
1111.19ms1.20msMail::SpamAssassin::Conf::::__ANON__[:3804]Mail::SpamAssassin::Conf::__ANON__[:3804]
15111.13ms5.28msMail::SpamAssassin::Conf::::__ANON__[:2701]Mail::SpamAssassin::Conf::__ANON__[:2701]
19111.01ms3.75msMail::SpamAssassin::Conf::::__ANON__[:433]Mail::SpamAssassin::Conf::__ANON__[:433]
511743µs865µsMail::SpamAssassin::Conf::::__ANON__[:935]Mail::SpamAssassin::Conf::__ANON__[:935]
2711701µs507msMail::SpamAssassin::Conf::::load_pluginMail::SpamAssassin::Conf::load_plugin
1311640µs2.33msMail::SpamAssassin::Conf::::__ANON__[:3122]Mail::SpamAssassin::Conf::__ANON__[:3122]
1511584µs584µsMail::SpamAssassin::Conf::::CORE:regcompMail::SpamAssassin::Conf::CORE:regcomp (opcode)
111350µs29.8msMail::SpamAssassin::Conf::::newMail::SpamAssassin::Conf::new
2711304µs304µsMail::SpamAssassin::Conf::::load_plugin_succeededMail::SpamAssassin::Conf::load_plugin_succeeded
2411301µs301µsMail::SpamAssassin::Conf::::feature_bug6558_freeMail::SpamAssassin::Conf::feature_bug6558_free
3611215µs215µsMail::SpamAssassin::Conf::::__ANON__[:3402]Mail::SpamAssassin::Conf::__ANON__[:3402]
211126µs132µsMail::SpamAssassin::Conf::::__ANON__[:1419]Mail::SpamAssassin::Conf::__ANON__[:1419]
1511103µs103µsMail::SpamAssassin::Conf::::CORE:qrMail::SpamAssassin::Conf::CORE:qr (opcode)
331103µs6.73msMail::SpamAssassin::Conf::::new_netsetMail::SpamAssassin::Conf::new_netset
11192µs132µsMail::SpamAssassin::Conf::::__ANON__[:3835]Mail::SpamAssassin::Conf::__ANON__[:3835]
71170µs70µsMail::SpamAssassin::Conf::::perl_min_version_5010000Mail::SpamAssassin::Conf::perl_min_version_5010000
22267µs86µsMail::SpamAssassin::Conf::::set_score_setMail::SpamAssassin::Conf::set_score_set
11151µs51µsMail::SpamAssassin::Conf::::__ANON__[:1007]Mail::SpamAssassin::Conf::__ANON__[:1007]
11144µs88µsMail::SpamAssassin::Conf::::__ANON__[:3858]Mail::SpamAssassin::Conf::__ANON__[:3858]
11139µs48µsMail::SpamAssassin::Conf::::BEGIN@80Mail::SpamAssassin::Conf::BEGIN@80
11135µs35µsMail::SpamAssassin::Conf::::CORE:ftdirMail::SpamAssassin::Conf::CORE:ftdir (opcode)
11134µs41µsMail::SpamAssassin::Conf::::__ANON__[:1054]Mail::SpamAssassin::Conf::__ANON__[:1054]
11131µs921µsMail::SpamAssassin::Conf::::BEGIN@87Mail::SpamAssassin::Conf::BEGIN@87
11131µs7.67sMail::SpamAssassin::Conf::::finish_parsingMail::SpamAssassin::Conf::finish_parsing
11129µs189µsMail::SpamAssassin::Conf::::BEGIN@89Mail::SpamAssassin::Conf::BEGIN@89
11128µs28µsMail::SpamAssassin::Conf::::found_any_rulesMail::SpamAssassin::Conf::found_any_rules
11124µs5.03sMail::SpamAssassin::Conf::::parse_rulesMail::SpamAssassin::Conf::parse_rules
11122µs111µsMail::SpamAssassin::Conf::::BEGIN@91Mail::SpamAssassin::Conf::BEGIN@91
11122µs22µsMail::SpamAssassin::Conf::::wipe_ports_rangeMail::SpamAssassin::Conf::wipe_ports_range
11121µs1.00msMail::SpamAssassin::Conf::::BEGIN@94Mail::SpamAssassin::Conf::BEGIN@94
11120µs27µsMail::SpamAssassin::Conf::::BEGIN@82Mail::SpamAssassin::Conf::BEGIN@82
11120µs20µsMail::SpamAssassin::Conf::::BEGIN@92Mail::SpamAssassin::Conf::BEGIN@92
21119µs19µsMail::SpamAssassin::Conf::::feature_registryboundariesMail::SpamAssassin::Conf::feature_registryboundaries
11119µs44µsMail::SpamAssassin::Conf::::BEGIN@81Mail::SpamAssassin::Conf::BEGIN@81
11118µs68µsMail::SpamAssassin::Conf::::BEGIN@83Mail::SpamAssassin::Conf::BEGIN@83
11117µs17µsMail::SpamAssassin::Conf::::__ANON__[:1437]Mail::SpamAssassin::Conf::__ANON__[:1437]
11110µs10µsMail::SpamAssassin::Conf::::feature_originating_ip_headersMail::SpamAssassin::Conf::feature_originating_ip_headers
1119µs9µsMail::SpamAssassin::Conf::::feature_yesno_takes_argsMail::SpamAssassin::Conf::feature_yesno_takes_args
1118µs8µsMail::SpamAssassin::Conf::::feature_dns_local_ports_permit_avoidMail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1165]Mail::SpamAssassin::Conf::__ANON__[:1165]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1277]Mail::SpamAssassin::Conf::__ANON__[:1277]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1331]Mail::SpamAssassin::Conf::__ANON__[:1331]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1388]Mail::SpamAssassin::Conf::__ANON__[:1388]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1519]Mail::SpamAssassin::Conf::__ANON__[:1519]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1573]Mail::SpamAssassin::Conf::__ANON__[:1573]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1592]Mail::SpamAssassin::Conf::__ANON__[:1592]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1649]Mail::SpamAssassin::Conf::__ANON__[:1649]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1717]Mail::SpamAssassin::Conf::__ANON__[:1717]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1810]Mail::SpamAssassin::Conf::__ANON__[:1810]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1862]Mail::SpamAssassin::Conf::__ANON__[:1862]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:1881]Mail::SpamAssassin::Conf::__ANON__[:1881]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:2017]Mail::SpamAssassin::Conf::__ANON__[:2017]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:2364]Mail::SpamAssassin::Conf::__ANON__[:2364]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:2406]Mail::SpamAssassin::Conf::__ANON__[:2406]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:2663]Mail::SpamAssassin::Conf::__ANON__[:2663]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:3379]Mail::SpamAssassin::Conf::__ANON__[:3379]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:3470]Mail::SpamAssassin::Conf::__ANON__[:3470]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:3882]Mail::SpamAssassin::Conf::__ANON__[:3882]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:4175]Mail::SpamAssassin::Conf::__ANON__[:4175]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:417]Mail::SpamAssassin::Conf::__ANON__[:417]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:4328]Mail::SpamAssassin::Conf::__ANON__[:4328]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:501]Mail::SpamAssassin::Conf::__ANON__[:501]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:715]Mail::SpamAssassin::Conf::__ANON__[:715]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:754]Mail::SpamAssassin::Conf::__ANON__[:754]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:775]Mail::SpamAssassin::Conf::__ANON__[:775]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:796]Mail::SpamAssassin::Conf::__ANON__[:796]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:858]Mail::SpamAssassin::Conf::__ANON__[:858]
0000s0sMail::SpamAssassin::Conf::::__ANON__[:974]Mail::SpamAssassin::Conf::__ANON__[:974]
0000s0sMail::SpamAssassin::Conf::::add_meta_dependsMail::SpamAssassin::Conf::add_meta_depends
0000s0sMail::SpamAssassin::Conf::::add_to_addrlistMail::SpamAssassin::Conf::add_to_addrlist
0000s0sMail::SpamAssassin::Conf::::add_to_addrlist_rcvdMail::SpamAssassin::Conf::add_to_addrlist_rcvd
0000s0sMail::SpamAssassin::Conf::::cloneMail::SpamAssassin::Conf::clone
0000s0sMail::SpamAssassin::Conf::::delete_ruleMail::SpamAssassin::Conf::delete_rule
0000s0sMail::SpamAssassin::Conf::::feature_bayes_auto_learn_on_errorMail::SpamAssassin::Conf::feature_bayes_auto_learn_on_error
0000s0sMail::SpamAssassin::Conf::::feature_dns_query_restrictionMail::SpamAssassin::Conf::feature_dns_query_restriction
0000s0sMail::SpamAssassin::Conf::::feature_ednsMail::SpamAssassin::Conf::feature_edns
0000s0sMail::SpamAssassin::Conf::::feature_uri_host_listedMail::SpamAssassin::Conf::feature_uri_host_listed
0000s0sMail::SpamAssassin::Conf::::finishMail::SpamAssassin::Conf::finish
0000s0sMail::SpamAssassin::Conf::::free_uncompiled_rule_sourceMail::SpamAssassin::Conf::free_uncompiled_rule_source
0000s0sMail::SpamAssassin::Conf::::get_description_for_ruleMail::SpamAssassin::Conf::get_description_for_rule
0000s0sMail::SpamAssassin::Conf::::get_rule_keysMail::SpamAssassin::Conf::get_rule_keys
0000s0sMail::SpamAssassin::Conf::::get_rule_typesMail::SpamAssassin::Conf::get_rule_types
0000s0sMail::SpamAssassin::Conf::::get_rule_valueMail::SpamAssassin::Conf::get_rule_value
0000s0sMail::SpamAssassin::Conf::::get_score_setMail::SpamAssassin::Conf::get_score_set
0000s0sMail::SpamAssassin::Conf::::maybe_body_onlyMail::SpamAssassin::Conf::maybe_body_only
0000s0sMail::SpamAssassin::Conf::::maybe_header_onlyMail::SpamAssassin::Conf::maybe_header_only
0000s0sMail::SpamAssassin::Conf::::mtimeMail::SpamAssassin::Conf::mtime
0000s0sMail::SpamAssassin::Conf::::parse_scores_onlyMail::SpamAssassin::Conf::parse_scores_only
0000s0sMail::SpamAssassin::Conf::::regression_testsMail::SpamAssassin::Conf::regression_tests
0000s0sMail::SpamAssassin::Conf::::remove_from_addrlistMail::SpamAssassin::Conf::remove_from_addrlist
0000s0sMail::SpamAssassin::Conf::::remove_from_addrlist_rcvdMail::SpamAssassin::Conf::remove_from_addrlist_rcvd
0000s0sMail::SpamAssassin::Conf::::sa_dieMail::SpamAssassin::Conf::sa_die
0000s0sMail::SpamAssassin::Conf::::trim_rulesMail::SpamAssassin::Conf::trim_rules
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
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::Conf - SpamAssassin configuration file
21
22=head1 SYNOPSIS
23
24 # a comment
25
26 rewrite_header Subject *****SPAM*****
27
28 full PARA_A_2_C_OF_1618 /Paragraph .a.{0,10}2.{0,10}C. of S. 1618/i
29 describe PARA_A_2_C_OF_1618 Claims compliance with senate bill 1618
30
31 header FROM_HAS_MIXED_NUMS From =~ /\d+[a-z]+\d+\S*@/i
32 describe FROM_HAS_MIXED_NUMS From: contains numbers mixed in with letters
33
34 score A_HREF_TO_REMOVE 2.0
35
36 lang es describe FROM_FORGED_HOTMAIL Forzado From: simula ser de hotmail.com
37
38 lang pt_BR report O programa detetor de Spam ZOE [...]
39
40=head1 DESCRIPTION
41
42SpamAssassin is configured using traditional UNIX-style configuration files,
43loaded from the C</usr/share/spamassassin> and C</etc/mail/spamassassin>
44directories.
45
46The following web page lists the most important configuration settings
47used to configure SpamAssassin; novices are encouraged to read it first:
48
49 http://wiki.apache.org/spamassassin/ImportantInitialConfigItems
50
51=head1 FILE FORMAT
52
53The C<#> character starts a comment, which continues until end of line.
54B<NOTE:> if the C<#> character is to be used as part of a rule or
55configuration option, it must be escaped with a backslash. i.e.: C<\#>
56
57Whitespace in the files is not significant, but please note that starting a
58line with whitespace is deprecated, as we reserve its use for multi-line rule
59definitions, at some point in the future.
60
61Currently, each rule or configuration setting must fit on one-line; multi-line
62settings are not supported yet.
63
64File and directory paths can use C<~> to refer to the user's home
65directory, but no other shell-style path extensions such as globing or
66C<~user/> are supported.
67
68Where appropriate below, default values are listed in parentheses.
69
70=head1 USER PREFERENCES
71
72The following options can be used in both site-wide (C<local.cf>) and
73user-specific (C<user_prefs>) configuration files to customize how
74SpamAssassin handles incoming email messages.
75
76=cut
77
78package Mail::SpamAssassin::Conf;
79
80253µs257µs
# spent 48µs (39+9) within Mail::SpamAssassin::Conf::BEGIN@80 which was called: # once (39µs+9µs) by Mail::SpamAssassin::BEGIN@71 at line 80
use strict;
# spent 48µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@80 # spent 9µs making 1 call to strict::import
81250µs269µs
# spent 44µs (19+25) within Mail::SpamAssassin::Conf::BEGIN@81 which was called: # once (19µs+25µs) by Mail::SpamAssassin::BEGIN@71 at line 81
use warnings;
# spent 44µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@81 # spent 25µs making 1 call to warnings::import
82253µs234µs
# spent 27µs (20+7) within Mail::SpamAssassin::Conf::BEGIN@82 which was called: # once (20µs+7µs) by Mail::SpamAssassin::BEGIN@71 at line 82
use bytes;
# spent 27µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@82 # spent 7µs making 1 call to bytes::import
83253µs2118µs
# spent 68µs (18+50) within Mail::SpamAssassin::Conf::BEGIN@83 which was called: # once (18µs+50µs) by Mail::SpamAssassin::BEGIN@71 at line 83
use re 'taint';
# spent 68µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@83 # spent 50µs making 1 call to re::import
84
852308µs2112ms
# spent 112ms (18.2+93.4) within Mail::SpamAssassin::Conf::BEGIN@85 which was called: # once (18.2ms+93.4ms) by Mail::SpamAssassin::BEGIN@71 at line 85
use Mail::SpamAssassin::Util;
# spent 112ms making 1 call to Mail::SpamAssassin::Conf::BEGIN@85 # spent 91µs making 1 call to Exporter::import
862332µs126.3ms
# spent 26.3ms (4.32+22.0) within Mail::SpamAssassin::Conf::BEGIN@86 which was called: # once (4.32ms+22.0ms) by Mail::SpamAssassin::BEGIN@71 at line 86
use Mail::SpamAssassin::NetSet;
# spent 26.3ms making 1 call to Mail::SpamAssassin::Conf::BEGIN@86
87272µs21.81ms
# spent 921µs (31+890) within Mail::SpamAssassin::Conf::BEGIN@87 which was called: # once (31µs+890µs) by Mail::SpamAssassin::BEGIN@71 at line 87
use Mail::SpamAssassin::Constants qw(:sa :ip);
# spent 921µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@87 # spent 890µs making 1 call to Exporter::import
882566µs116.5ms
# spent 16.5ms (15.1+1.35) within Mail::SpamAssassin::Conf::BEGIN@88 which was called: # once (15.1ms+1.35ms) by Mail::SpamAssassin::BEGIN@71 at line 88
use Mail::SpamAssassin::Conf::Parser;
# spent 16.5ms making 1 call to Mail::SpamAssassin::Conf::BEGIN@88
89263µs2348µs
# spent 189µs (29+159) within Mail::SpamAssassin::Conf::BEGIN@89 which was called: # once (29µs+159µs) by Mail::SpamAssassin::BEGIN@71 at line 89
use Mail::SpamAssassin::Logger;
# spent 189µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@89 # spent 159µs making 1 call to Exporter::import
902360µs11.63ms
# spent 1.63ms (1.33+306µs) within Mail::SpamAssassin::Conf::BEGIN@90 which was called: # once (1.33ms+306µs) by Mail::SpamAssassin::BEGIN@71 at line 90
use Mail::SpamAssassin::Util::TieOneStringHash;
# spent 1.63ms making 1 call to Mail::SpamAssassin::Conf::BEGIN@90
91257µs2200µs
# spent 111µs (22+89) within Mail::SpamAssassin::Conf::BEGIN@91 which was called: # once (22µs+89µs) by Mail::SpamAssassin::BEGIN@71 at line 91
use Mail::SpamAssassin::Util qw(untaint_var);
# spent 111µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@91 # spent 89µs making 1 call to Exporter::import
922118µs120µs
# spent 20µs within Mail::SpamAssassin::Conf::BEGIN@92 which was called: # once (20µs+0s) by Mail::SpamAssassin::BEGIN@71 at line 92
use File::Spec;
# spent 20µs making 1 call to Mail::SpamAssassin::Conf::BEGIN@92
93
9412µs
# spent 1.00ms (21µs+983µs) within Mail::SpamAssassin::Conf::BEGIN@94 which was called: # once (21µs+983µs) by Mail::SpamAssassin::BEGIN@71 at line 109
use vars qw{
95 @ISA
96 $CONF_TYPE_STRING $CONF_TYPE_BOOL
97 $CONF_TYPE_NUMERIC $CONF_TYPE_HASH_KEY_VALUE
98 $CONF_TYPE_ADDRLIST $CONF_TYPE_TEMPLATE
99 $CONF_TYPE_STRINGLIST $CONF_TYPE_IPADDRLIST
100 $CONF_TYPE_DURATION $CONF_TYPE_NOARGS
101 $MISSING_REQUIRED_VALUE $INVALID_VALUE $INVALID_HEADER_FIELD_NAME
102 @MIGRATED_SETTINGS
103 $COLLECT_REGRESSION_TESTS
104
105$TYPE_HEAD_TESTS $TYPE_HEAD_EVALS
106$TYPE_BODY_TESTS $TYPE_BODY_EVALS $TYPE_FULL_TESTS $TYPE_FULL_EVALS
107$TYPE_RAWBODY_TESTS $TYPE_RAWBODY_EVALS $TYPE_URI_TESTS $TYPE_URI_EVALS
108$TYPE_META_TESTS $TYPE_RBL_EVALS $TYPE_EMPTY_TESTS
109128.2ms21.99ms};
# spent 1.00ms making 1 call to Mail::SpamAssassin::Conf::BEGIN@94 # spent 983µs making 1 call to vars::import
110
111125µs@ISA = qw();
112
113# odd => eval test. Not constants so they can be shared with Parser
114# TODO: move to Constants.pm?
11512µs$TYPE_HEAD_TESTS = 0x0008;
11612µs$TYPE_HEAD_EVALS = 0x0009;
11712µs$TYPE_BODY_TESTS = 0x000a;
11812µs$TYPE_BODY_EVALS = 0x000b;
11912µs$TYPE_FULL_TESTS = 0x000c;
12011µs$TYPE_FULL_EVALS = 0x000d;
12112µs$TYPE_RAWBODY_TESTS = 0x000e;
12212µs$TYPE_RAWBODY_EVALS = 0x000f;
12312µs$TYPE_URI_TESTS = 0x0010;
12412µs$TYPE_URI_EVALS = 0x0011;
12511µs$TYPE_META_TESTS = 0x0012;
12612µs$TYPE_RBL_EVALS = 0x0013;
12711µs$TYPE_EMPTY_TESTS = 0x0014;
128
12917µsmy @rule_types = ("body_tests", "uri_tests", "uri_evals",
130 "head_tests", "head_evals", "body_evals", "full_tests",
131 "full_evals", "rawbody_tests", "rawbody_evals",
132 "rbl_evals", "meta_tests");
133
134#Removed $VERSION per BUG 6422
135#$VERSION = 'bogus'; # avoid CPAN.pm picking up version strings later
136
137# these are variables instead of constants so that other classes can
138# access them; if they're constants, they'd have to go in Constants.pm
139# TODO: move to Constants.pm?
14012µs$CONF_TYPE_STRING = 1;
14112µs$CONF_TYPE_BOOL = 2;
14212µs$CONF_TYPE_NUMERIC = 3;
14311µs$CONF_TYPE_HASH_KEY_VALUE = 4;
14412µs$CONF_TYPE_ADDRLIST = 5;
14512µs$CONF_TYPE_TEMPLATE = 6;
14612µs$CONF_TYPE_NOARGS = 7;
14712µs$CONF_TYPE_STRINGLIST = 8;
14812µs$CONF_TYPE_IPADDRLIST = 9;
14912µs$CONF_TYPE_DURATION = 10;
15012µs$MISSING_REQUIRED_VALUE = '-99999999999999'; # string expected by parser
15112µs$INVALID_VALUE = '-99999999999998';
15213µs$INVALID_HEADER_FIELD_NAME = '-99999999999997';
153
154# set to "1" by the test suite code, to record regression tests
155# $Mail::SpamAssassin::Conf::COLLECT_REGRESSION_TESTS = 1;
156
157# search for "sub new {" to find the start of the code
158###########################################################################
159
160
# spent 20.4ms within Mail::SpamAssassin::Conf::set_default_commands which was called: # once (20.4ms+0s) by Mail::SpamAssassin::Conf::new at line 4516
sub set_default_commands {
16112µs my($self) = @_;
162
163 # see "perldoc Mail::SpamAssassin::Conf::Parser" for details on this fmt.
164 # push each config item like this, to avoid a POD bug; it can't just accept
165 # ( { ... }, { ... }, { ...} ) otherwise POD parsing dies.
16612µs my @cmds;
167
168=head2 SCORING OPTIONS
169
170=over 4
171
172=item required_score n.nn (default: 5)
173
174Set the score required before a mail is considered spam. C<n.nn> can
175be an integer or a real number. 5.0 is the default setting, and is
176quite aggressive; it would be suitable for a single-user setup, but if
177you're an ISP installing SpamAssassin, you should probably set the
178default to be more conservative, like 8.0 or 10.0. It is not
179recommended to automatically delete or discard messages marked as
180spam, as your users B<will> complain, but if you choose to do so, only
181delete messages with an exceptionally high score such as 15.0 or
182higher. This option was previously known as C<required_hits> and that
183name is still accepted, but is deprecated.
184
185=cut
186
187111µs push (@cmds, {
188 setting => 'required_score',
189 aliases => ['required_hits'], # backward compatible
190 default => 5,
191 type => $CONF_TYPE_NUMERIC,
192 });
193
194=item score SYMBOLIC_TEST_NAME n.nn [ n.nn n.nn n.nn ]
195
196Assign scores (the number of points for a hit) to a given test.
197Scores can be positive or negative real numbers or integers.
198C<SYMBOLIC_TEST_NAME> is the symbolic name used by SpamAssassin for
199that test; for example, 'FROM_ENDS_IN_NUMS'.
200
201If only one valid score is listed, then that score is always used
202for a test.
203
204If four valid scores are listed, then the score that is used depends
205on how SpamAssassin is being used. The first score is used when
206both Bayes and network tests are disabled (score set 0). The second
207score is used when Bayes is disabled, but network tests are enabled
208(score set 1). The third score is used when Bayes is enabled and
209network tests are disabled (score set 2). The fourth score is used
210when Bayes is enabled and network tests are enabled (score set 3).
211
212Setting a rule's score to 0 will disable that rule from running.
213
214If any of the score values are surrounded by parenthesis '()', then
215all of the scores in the line are considered to be relative to the
216already set score. ie: '(3)' means increase the score for this
217rule by 3 points in all score sets. '(3) (0) (3) (0)' means increase
218the score for this rule by 3 in score sets 0 and 2 only.
219
220If no score is given for a test by the end of the configuration,
221a default score is assigned: a score of 1.0 is used for all tests,
222except those whose names begin with 'T_' (this is used to indicate a
223rule in testing) which receive 0.01.
224
225Note that test names which begin with '__' are indirect rules used
226to compose meta-match rules and can also act as prerequisites to
227other rules. They are not scored or listed in the 'tests hit'
228reports, but assigning a score of 0 to an indirect rule will disable
229it from running.
230
231=cut
232
233 push (@cmds, {
234 setting => 'score',
235 is_frequent => 1,
236
# spent 189ms (171+17.8) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:280] which was called 811 times, avg 233µs/call: # 811 times (171ms+17.8ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 233µs/call
code => sub {
2378115.91ms my ($self, $key, $value, $line) = @_;
23881112.7ms my($rule, @scores) = split(/\s+/, $value);
23981110.3ms8112.10ms unless (defined $value && $value !~ /^$/ &&
# spent 2.10ms making 811 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
240 (scalar @scores == 1 || scalar @scores == 4)) {
241 info("config: score: requires a symbolic rule name and 1 or 4 scores");
242 return $MISSING_REQUIRED_VALUE;
243 }
244
245 # Figure out if we're doing relative scores, remove the parens if we are
2468111.39ms my $relative = 0;
2478113.17ms foreach (@scores) {
24823238.92ms local ($1);
249232338.4ms23235.07ms if (s/^\((-?\d+(?:\.\d+)?)\)$/$1/) {
# spent 5.07ms making 2323 calls to Mail::SpamAssassin::Conf::CORE:subst, avg 2µs/call
250 $relative = 1;
251 }
252232345.2ms232310.6ms unless (/^-?\d+(?:\.\d+)?$/) {
# spent 10.6ms making 2323 calls to Mail::SpamAssassin::Conf::CORE:match, avg 5µs/call
253 info("config: score: the non-numeric score ($_) is not valid, " .
254 "a numeric score is required");
255 return $INVALID_VALUE;
256 }
257 }
258
2598111.31ms if ($relative && !exists $self->{scoreset}->[0]->{$rule}) {
260 info("config: score: relative score without previous setting in " .
261 "configuration");
262 return $INVALID_VALUE;
263 }
264
265 # If we're only passed 1 score, copy it to the other scoresets
26681119.9ms if (@scores) {
2678112.00ms if (@scores != 4) {
2683072.42ms @scores = ( $scores[0], $scores[0], $scores[0], $scores[0] );
269 }
270
271 # Set the actual scoreset values appropriately
2728113.15ms for my $index (0..3) {
273 my $score = $relative ?
27432447.71ms $self->{scoreset}->[$index]->{$rule} + $scores[$index] :
275 $scores[$index];
276
277324438.7ms $self->{scoreset}->[$index]->{$rule} = $score + 0.0;
278 }
279 }
280 }
281119µs });
282
283=back
284
285=head2 WHITELIST AND BLACKLIST OPTIONS
286
287=over 4
288
289=item whitelist_from user@example.com
290
291Used to whitelist sender addresses which send mail that is often tagged
292(incorrectly) as spam.
293
294Use of this setting is not recommended, since it blindly trusts the message,
295which is routinely and easily forged by spammers and phish senders. The
296recommended solution is to instead use C<whitelist_auth> or other authenticated
297whitelisting methods, or C<whitelist_from_rcvd>.
298
299Whitelist and blacklist addresses are now file-glob-style patterns, so
300C<friend@somewhere.com>, C<*@isp.com>, or C<*.domain.net> will all work.
301Specifically, C<*> and C<?> are allowed, but all other metacharacters
302are not. Regular expressions are not used for security reasons.
303Matching is case-insensitive.
304
305Multiple addresses per line, separated by spaces, is OK. Multiple
306C<whitelist_from> lines are also OK.
307
308The headers checked for whitelist addresses are as follows: if C<Resent-From>
309is set, use that; otherwise check all addresses taken from the following
310set of headers:
311
312 Envelope-Sender
313 Resent-Sender
314 X-Envelope-From
315 From
316
317In addition, the "envelope sender" data, taken from the SMTP envelope data
318where this is available, is looked up. See C<envelope_sender_header>.
319
320e.g.
321
322 whitelist_from joe@example.com fred@example.com
323 whitelist_from *@example.com
324
325=cut
326
32715µs push (@cmds, {
328 setting => 'whitelist_from',
329 type => $CONF_TYPE_ADDRLIST,
330 });
331
332=item unwhitelist_from user@example.com
333
334Used to override a default whitelist_from entry, so for example a distribution
335whitelist_from can be overridden in a local.cf file, or an individual user can
336override a whitelist_from entry in their own C<user_prefs> file.
337The specified email address has to match exactly (although case-insensitively)
338the address previously used in a whitelist_from line, which implies that a
339wildcard only matches literally the same wildcard (not 'any' address).
340
341e.g.
342
343 unwhitelist_from joe@example.com fred@example.com
344 unwhitelist_from *@example.com
345
346=cut
347
34817µs push (@cmds, {
349 command => 'unwhitelist_from',
350 setting => 'whitelist_from',
351 type => $CONF_TYPE_ADDRLIST,
352 code => \&Mail::SpamAssassin::Conf::Parser::remove_addrlist_value
353 });
354
355=item whitelist_from_rcvd addr@lists.sourceforge.net sourceforge.net
356
357Works similarly to whitelist_from, except that in addition to matching
358a sender address, a relay's rDNS name or its IP address must match too
359for the whitelisting rule to fire. The first parameter is a sender's e-mail
360address to whitelist, and the second is a string to match the relay's rDNS,
361or its IP address. Matching is case-insensitive.
362
363This second parameter is matched against the TCP-info information field as
364provided in a FROM clause of a trace information (i.e. the Received header
365field, see RFC 5321). Only the Received header fields inserted by trusted
366hosts are considered. This parameter can either be a full hostname, or the
367domain component of that hostname, or an IP address in square brackets.
368The reverse DNS lookup is done by a MTA, not by SpamAssassin.
369
370In case of an IPv4 address in brackets, it may be truncated on classful
371boundaries to cover whole subnets, e.g. C<[10.1.2.3]>, C<[10.1.2]>,
372C<[10.1]>, C<[10]>. CIDR notation is currently not supported, nor is
373IPv6. The matching on IP address is mainly provided to cover rare cases
374where whitelisting of a sending MTA is desired which does not have a
375correct reverse DNS configured.
376
377In other words, if the host that connected to your MX had an IP address
378192.0.2.123 that mapped to 'sendinghost.example.org', you should specify
379C<sendinghost.example.org>, or C<example.org>, or C<[192.0.2.123]> or
380C<[192.0.2]> here.
381
382Note that this requires that C<internal_networks> be correct. For simple
383cases, it will be, but for a complex network you may get better results
384by setting that parameter.
385
386It also requires that your mail exchangers be configured to perform DNS
387reverse lookups on the connecting host's IP address, and to record the
388result in the generated Received header field according to RFC 5321.
389
390e.g.
391
392 whitelist_from_rcvd joe@example.com example.com
393 whitelist_from_rcvd *@axkit.org sergeant.org
394 whitelist_from_rcvd *@axkit.org [192.0.2.123]
395
396=item def_whitelist_from_rcvd addr@lists.sourceforge.net sourceforge.net
397
398Same as C<whitelist_from_rcvd>, but used for the default whitelist entries
399in the SpamAssassin distribution. The whitelist score is lower, because
400these are often targets for spammer spoofing.
401
402=cut
403
404 push (@cmds, {
405 setting => 'whitelist_from_rcvd',
406 type => $CONF_TYPE_ADDRLIST,
407 code => sub {
408 my ($self, $key, $value, $line) = @_;
409 unless (defined $value && $value !~ /^$/) {
410 return $MISSING_REQUIRED_VALUE;
411 }
412 unless ($value =~ /^\S+\s+\S+$/) {
413 return $INVALID_VALUE;
414 }
415 $self->{parser}->add_to_addrlist_rcvd ('whitelist_from_rcvd',
416 split(/\s+/, $value));
417 }
418112µs });
419
420 push (@cmds, {
421 setting => 'def_whitelist_from_rcvd',
422 type => $CONF_TYPE_ADDRLIST,
423
# spent 3.75ms (1.01+2.75) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] which was called 19 times, avg 198µs/call: # 19 times (1.01ms+2.75ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 198µs/call
code => sub {
42419230µs my ($self, $key, $value, $line) = @_;
42519198µs1948µs unless (defined $value && $value !~ /^$/) {
# spent 48µs making 19 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
426 return $MISSING_REQUIRED_VALUE;
427 }
42819196µs1967µs unless ($value =~ /^\S+\s+\S+$/) {
# spent 67µs making 19 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
429 return $INVALID_VALUE;
430 }
43119511µs192.63ms $self->{parser}->add_to_addrlist_rcvd ('def_whitelist_from_rcvd',
# spent 2.63ms making 19 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 138µs/call
432 split(/\s+/, $value));
433 }
434110µs });
435
436=item whitelist_allows_relays user@example.com
437
438Specify addresses which are in C<whitelist_from_rcvd> that sometimes
439send through a mail relay other than the listed ones. By default mail
440with a From address that is in C<whitelist_from_rcvd> that does not match
441the relay will trigger a forgery rule. Including the address in
442C<whitelist_allows_relay> prevents that.
443
444Whitelist and blacklist addresses are now file-glob-style patterns, so
445C<friend@somewhere.com>, C<*@isp.com>, or C<*.domain.net> will all work.
446Specifically, C<*> and C<?> are allowed, but all other metacharacters
447are not. Regular expressions are not used for security reasons.
448Matching is case-insensitive.
449
450Multiple addresses per line, separated by spaces, is OK. Multiple
451C<whitelist_allows_relays> lines are also OK.
452
453The specified email address does not have to match exactly the address
454previously used in a whitelist_from_rcvd line as it is compared to the
455address in the header.
456
457e.g.
458
459 whitelist_allows_relays joe@example.com fred@example.com
460 whitelist_allows_relays *@example.com
461
462=cut
463
46415µs push (@cmds, {
465 setting => 'whitelist_allows_relays',
466 type => $CONF_TYPE_ADDRLIST,
467 });
468
469=item unwhitelist_from_rcvd user@example.com
470
471Used to override a default whitelist_from_rcvd entry, so for example a
472distribution whitelist_from_rcvd can be overridden in a local.cf file,
473or an individual user can override a whitelist_from_rcvd entry in
474their own C<user_prefs> file.
475
476The specified email address has to match exactly the address previously
477used in a whitelist_from_rcvd line.
478
479e.g.
480
481 unwhitelist_from_rcvd joe@example.com fred@example.com
482 unwhitelist_from_rcvd *@axkit.org
483
484=cut
485
486 push (@cmds, {
487 setting => 'unwhitelist_from_rcvd',
488 type => $CONF_TYPE_ADDRLIST,
489 code => sub {
490 my ($self, $key, $value, $line) = @_;
491 unless (defined $value && $value !~ /^$/) {
492 return $MISSING_REQUIRED_VALUE;
493 }
494 unless ($value =~ /^(?:\S+(?:\s+\S+)*)$/) {
495 return $INVALID_VALUE;
496 }
497 $self->{parser}->remove_from_addrlist_rcvd('whitelist_from_rcvd',
498 split (/\s+/, $value));
499 $self->{parser}->remove_from_addrlist_rcvd('def_whitelist_from_rcvd',
500 split (/\s+/, $value));
501 }
502112µs });
503
504=item blacklist_from user@example.com
505
506Used to specify addresses which send mail that is often tagged (incorrectly) as
507non-spam, but which the user doesn't want. Same format as C<whitelist_from>.
508
509=cut
510
51115µs push (@cmds, {
512 setting => 'blacklist_from',
513 type => $CONF_TYPE_ADDRLIST,
514 });
515
516=item unblacklist_from user@example.com
517
518Used to override a default blacklist_from entry, so for example a
519distribution blacklist_from can be overridden in a local.cf file, or
520an individual user can override a blacklist_from entry in their own
521C<user_prefs> file. The specified email address has to match exactly
522the address previously used in a blacklist_from line.
523
524
525e.g.
526
527 unblacklist_from joe@example.com fred@example.com
528 unblacklist_from *@spammer.com
529
530=cut
531
532
53317µs push (@cmds, {
534 command => 'unblacklist_from',
535 setting => 'blacklist_from',
536 type => $CONF_TYPE_ADDRLIST,
537 code => \&Mail::SpamAssassin::Conf::Parser::remove_addrlist_value
538 });
539
540
541=item whitelist_to user@example.com
542
543If the given address appears as a recipient in the message headers
544(Resent-To, To, Cc, obvious envelope recipient, etc.) the mail will
545be whitelisted. Useful if you're deploying SpamAssassin system-wide,
546and don't want some users to have their mail filtered. Same format
547as C<whitelist_from>.
548
549There are three levels of To-whitelisting, C<whitelist_to>, C<more_spam_to>
550and C<all_spam_to>. Users in the first level may still get some spammish
551mails blocked, but users in C<all_spam_to> should never get mail blocked.
552
553The headers checked for whitelist addresses are as follows: if C<Resent-To> or
554C<Resent-Cc> are set, use those; otherwise check all addresses taken from the
555following set of headers:
556
557 To
558 Cc
559 Apparently-To
560 Delivered-To
561 Envelope-Recipients
562 Apparently-Resent-To
563 X-Envelope-To
564 Envelope-To
565 X-Delivered-To
566 X-Original-To
567 X-Rcpt-To
568 X-Real-To
569
570=item more_spam_to user@example.com
571
572See above.
573
574=item all_spam_to user@example.com
575
576See above.
577
578=cut
579
58015µs push (@cmds, {
581 setting => 'whitelist_to',
582 type => $CONF_TYPE_ADDRLIST,
583 });
58414µs push (@cmds, {
585 setting => 'more_spam_to',
586 type => $CONF_TYPE_ADDRLIST,
587 });
58814µs push (@cmds, {
589 setting => 'all_spam_to',
590 type => $CONF_TYPE_ADDRLIST,
591 });
592
593=item blacklist_to user@example.com
594
595If the given address appears as a recipient in the message headers
596(Resent-To, To, Cc, obvious envelope recipient, etc.) the mail will
597be blacklisted. Same format as C<blacklist_from>.
598
599=cut
600
60114µs push (@cmds, {
602 setting => 'blacklist_to',
603 type => $CONF_TYPE_ADDRLIST,
604 });
605
606=item whitelist_auth user@example.com
607
608Used to specify addresses which send mail that is often tagged (incorrectly) as
609spam. This is different from C<whitelist_from> and C<whitelist_from_rcvd> in
610that it first verifies that the message was sent by an authorized sender for
611the address, before whitelisting.
612
613Authorization is performed using one of the installed sender-authorization
614schemes: SPF (using C<Mail::SpamAssassin::Plugin::SPF>), or DKIM (using
615C<Mail::SpamAssassin::Plugin::DKIM>). Note that those plugins must be active,
616and working, for this to operate.
617
618Using C<whitelist_auth> is roughly equivalent to specifying duplicate
619C<whitelist_from_spf>, C<whitelist_from_dk>, and C<whitelist_from_dkim> lines
620for each of the addresses specified.
621
622e.g.
623
624 whitelist_auth joe@example.com fred@example.com
625 whitelist_auth *@example.com
626
627=item def_whitelist_auth user@example.com
628
629Same as C<whitelist_auth>, but used for the default whitelist entries
630in the SpamAssassin distribution. The whitelist score is lower, because
631these are often targets for spammer spoofing.
632
633=cut
634
63514µs push (@cmds, {
636 setting => 'whitelist_auth',
637 type => $CONF_TYPE_ADDRLIST,
638 });
639
64014µs push (@cmds, {
641 setting => 'def_whitelist_auth',
642 type => $CONF_TYPE_ADDRLIST,
643 });
644
645=item unwhitelist_auth user@example.com
646
647Used to override a C<whitelist_auth> entry. The specified email address has to
648match exactly the address previously used in a C<whitelist_auth> line.
649
650e.g.
651
652 unwhitelist_auth joe@example.com fred@example.com
653 unwhitelist_auth *@example.com
654
655=cut
656
65716µs push (@cmds, {
658 command => 'unwhitelist_auth',
659 setting => 'whitelist_auth',
660 type => $CONF_TYPE_ADDRLIST,
661 code => \&Mail::SpamAssassin::Conf::Parser::remove_addrlist_value
662 });
663
664
665=item enlist_uri_host (listname) host ...
666
667Adds one or more host names or domain names to a named list of URI domains.
668The named list can then be consulted through a check_uri_host_listed()
669eval rule implemented by the WLBLEval plugin, which takes the list name as
670an argument. Parenthesis around a list name are literal - a required syntax.
671
672Host names may optionally be prefixed by an exclamantion mark '!', which
673produces false as a result if this entry matches. This makes it easier
674to exclude some subdomains when their superdomain is listed, for example:
675
676 enlist_uri_host (MYLIST) !sub1.example.com !sub2.example.com example.com
677
678No wildcards are supported, but subdomains do match implicitly. Lists
679are independent. Search for each named list starts by looking up the
680full hostname first, then leading fields are progressively stripped off
681(e.g.: sub.example.com, example.com, com) until a match is found or we run
682out of fields. The first matching entry (the most specific) determines if a
683lookup yielded a true (no '!' prefix) or a false (with a '!' prefix) result.
684
685If an URL found in a message contains an IP address in place of a host name,
686the given list must specify the exact same IP address (instead of a host name)
687in order to match.
688
689Use the delist_uri_host directive to neutralize previous enlist_uri_host
690settings.
691
692Enlisting to lists named 'BLACK' and 'WHITE' have their shorthand directives
693blacklist_uri_host and whitelist_uri_host and corresponding default rules,
694but the names 'BLACK' and 'WHITE' are otherwise not special or reserved.
695
696=cut
697
698 push (@cmds, {
699 command => 'enlist_uri_host',
700 setting => 'uri_host_lists',
701 type => $CONF_TYPE_ADDRLIST,
702 code => sub {
703 my($conf, $key, $value, $line) = @_;
704 local($1,$2);
705 if ($value !~ /^ \( (.*?) \) \s+ (.*) \z/sx) {
706 return $MISSING_REQUIRED_VALUE;
707 }
708 my $listname = $1; # corresponds to arg in check_uri_host_in_wblist()
709 # note: must not factor out dereferencing, as otherwise
710 # subhashes would spring up in a copy and be lost
711 foreach my $host ( split(' ', lc $2) ) {
712 my $v = $host =~ s/^!// ? 0 : 1;
713 $conf->{uri_host_lists}{$listname}{$host} = $v;
714 }
715 }
716112µs });
717
718=item delist_uri_host [ (listname) ] host ...
719
720Removes one or more specified host names from a named list of URI domains.
721Removing an unlisted name is ignored (is not an error). Listname is optional,
722if specified then just the named list is affected, otherwise hosts are
723removed from all URI host lists created so far. Parenthesis around a list
724name are a required syntax.
725
726Note that directives in configuration files are processed in sequence,
727the delist_uri_host only applies to previously listed entries and has
728no effect on enlisted entries in yet-to-be-processed directives.
729
730For convenience (similarity to the enlist_uri_host directive) hostnames
731may be prefixed by a an exclamation mark, which is stripped off from each
732name and has no meaning here.
733
734=cut
735
736 push (@cmds, {
737 command => 'delist_uri_host',
738 setting => 'uri_host_lists',
739 type => $CONF_TYPE_ADDRLIST,
740 code => sub {
741 my($conf, $key, $value, $line) = @_;
742 local($1,$2);
743 if ($value !~ /^ (?: \( (.*?) \) \s+ )? (.*) \z/sx) {
744 return $MISSING_REQUIRED_VALUE;
745 }
746 my @listnames = defined $1 ? $1 : keys %{$conf->{uri_host_lists}};
747 my @args = split(' ', lc $2);
748 foreach my $listname (@listnames) {
749 foreach my $host (@args) {
750 my $v = $host =~ s/^!// ? 0 : 1;
751 delete $conf->{uri_host_lists}{$listname}{$host};
752 }
753 }
754 }
755113µs });
756
757=item blacklist_uri_host host-or-domain ...
758
759Is a shorthand for a directive: enlist_uri_host (BLACK) host ...
760
761Please see directives enlist_uri_host and delist_uri_host for details.
762
763=cut
764
765 push (@cmds, {
766 command => 'blacklist_uri_host',
767 setting => 'uri_host_lists',
768 type => $CONF_TYPE_ADDRLIST,
769 code => sub {
770 my($conf, $key, $value, $line) = @_;
771 foreach my $host ( split(' ', lc $value) ) {
772 my $v = $host =~ s/^!// ? 0 : 1;
773 $conf->{uri_host_lists}{'BLACK'}{$host} = $v;
774 }
775 }
776111µs });
777
778=item whitelist_uri_host host-or-domain ...
779
780Is a shorthand for a directive: enlist_uri_host (BLACK) host ...
781
782Please see directives enlist_uri_host and delist_uri_host for details.
783
784=cut
785
786 push (@cmds, {
787 command => 'whitelist_uri_host',
788 setting => 'uri_host_lists',
789 type => $CONF_TYPE_ADDRLIST,
790 code => sub {
791 my($conf, $key, $value, $line) = @_;
792 foreach my $host ( split(' ', lc $value) ) {
793 my $v = $host =~ s/^!// ? 0 : 1;
794 $conf->{uri_host_lists}{'WHITE'}{$host} = $v;
795 }
796 }
797110µs });
798
799=back
800
801=head2 BASIC MESSAGE TAGGING OPTIONS
802
803=over 4
804
805=item rewrite_header { subject | from | to } STRING
806
807By default, suspected spam messages will not have the C<Subject>,
808C<From> or C<To> lines tagged to indicate spam. By setting this option,
809the header will be tagged with C<STRING> to indicate that a message is
810spam. For the From or To headers, this will take the form of an RFC 2822
811comment following the address in parantheses. For the Subject header,
812this will be prepended to the original subject. Note that you should
813only use the _REQD_ and _SCORE_ tags when rewriting the Subject header
814if C<report_safe> is 0. Otherwise, you may not be able to remove
815the SpamAssassin markup via the normal methods. More information
816about tags is explained below in the B<TEMPLATE TAGS> section.
817
818Parentheses are not permitted in STRING if rewriting the From or To headers.
819(They will be converted to square brackets.)
820
821If C<rewrite_header subject> is used, but the message being rewritten
822does not already contain a C<Subject> header, one will be created.
823
824A null value for C<STRING> will remove any existing rewrite for the specified
825header.
826
827=cut
828
829 push (@cmds, {
830 setting => 'rewrite_header',
831 type => $CONF_TYPE_HASH_KEY_VALUE,
832 code => sub {
833 my ($self, $key, $value, $line) = @_;
834 my($hdr, $string) = split(/\s+/, $value, 2);
835 $hdr = ucfirst(lc($hdr));
836
837 if ($hdr =~ /^$/) {
838 return $MISSING_REQUIRED_VALUE;
839 }
840 # We only deal with From, Subject, and To ...
841 elsif ($hdr =~ /^(?:From|Subject|To)$/) {
842 unless (defined $string && $string =~ /\S/) {
843 delete $self->{rewrite_header}->{$hdr};
844 return;
845 }
846
847 if ($hdr ne 'Subject') {
848 $string =~ tr/()/[]/;
849 }
850 $self->{rewrite_header}->{$hdr} = $string;
851 return;
852 }
853 else {
854 # if we get here, note the issue, then we'll fail through for an error.
855 info("config: rewrite_header: ignoring $hdr, not From, Subject, or To");
856 return $INVALID_VALUE;
857 }
858 }
859110µs });
860
861=item add_header { spam | ham | all } header_name string
862
863Customized headers can be added to the specified type of messages (spam,
864ham, or "all" to add to either). All headers begin with C<X-Spam->
865(so a C<header_name> Foo will generate a header called X-Spam-Foo).
866header_name is restricted to the character set [A-Za-z0-9_-].
867
868The order of C<add_header> configuration options is preserved, inserted
869headers will follow this order of declarations. When combining C<add_header>
870with C<clear_headers> and C<remove_header>, keep in mind that C<add_header>
871appends a new header to the current list, after first removing any existing
872header fields of the same name. Note also that C<add_header>, C<clear_headers>
873and C<remove_header> may appear in multiple .cf files, which are interpreted
874in alphabetic order.
875
876C<string> can contain tags as explained below in the B<TEMPLATE TAGS> section.
877You can also use C<\n> and C<\t> in the header to add newlines and tabulators
878as desired. A backslash has to be written as \\, any other escaped chars will
879be silently removed.
880
881All headers will be folded if fold_headers is set to C<1>. Note: Manually
882adding newlines via C<\n> disables any further automatic wrapping (ie:
883long header lines are possible). The lines will still be properly folded
884(marked as continuing) though.
885
886You can customize existing headers with B<add_header> (only the specified
887subset of messages will be changed).
888
889See also C<clear_headers> and C<remove_header> for removing headers.
890
891Here are some examples (these are the defaults, note that Checker-Version can
892not be changed or removed):
893
894 add_header spam Flag _YESNOCAPS_
895 add_header all Status _YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ autolearn=_AUTOLEARN_ version=_VERSION_
896 add_header all Level _STARS(*)_
897 add_header all Checker-Version SpamAssassin _VERSION_ (_SUBVERSION_) on _HOSTNAME_
898
899=cut
900
901 push (@cmds, {
902 setting => 'add_header',
903
# spent 865µs (743+122) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] which was called 5 times, avg 173µs/call: # 5 times (743µs+122µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 173µs/call
code => sub {
904525µs my ($self, $key, $value, $line) = @_;
905527µs local ($1,$2,$3);
9065112µs572µs if ($value !~ /^(ham|spam|all)\s+([A-Za-z0-9_-]+)\s+(.*?)\s*$/) {
# spent 72µs making 5 calls to Mail::SpamAssassin::Conf::CORE:match, avg 14µs/call
907 return $INVALID_VALUE;
908 }
909
910528µs my ($type, $name, $hline) = ($1, $2, $3);
911551µs515µs if ($hline =~ /^"(.*)"$/) {
# spent 15µs making 5 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
91214µs $hline = $1;
913 }
914533µs my @line = split(
915 /\\\\/, # split at double backslashes,
916 $hline."\n" # newline needed to make trailing backslashes work
917 );
918521µs foreach (@line) {
919549µs513µs s/\\t/\t/g; # expand tabs
# spent 13µs making 5 calls to Mail::SpamAssassin::Conf::CORE:subst, avg 3µs/call
920540µs511µs s/\\n/\n/g; # expand newlines
# spent 11µs making 5 calls to Mail::SpamAssassin::Conf::CORE:subst, avg 2µs/call
921551µs512µs s/\\.//g; # purge all other escapes
# spent 12µs making 5 calls to Mail::SpamAssassin::Conf::CORE:subst, avg 2µs/call
922 };
923525µs $hline = join("\\", @line);
924516µs chop($hline); # remove dummy newline again
925521µs if (($type eq "ham") || ($type eq "all")) {
926 $self->{headers_ham} =
9271596µs [ grep { lc($_->[0]) ne lc($name) } @{$self->{headers_ham}} ];
928832µs push(@{$self->{headers_ham}}, [$name, $hline]);
929 }
930574µs if (($type eq "spam") || ($type eq "all")) {
931 $self->{headers_spam} =
93221115µs [ grep { lc($_->[0]) ne lc($name) } @{$self->{headers_spam}} ];
9331045µs push(@{$self->{headers_spam}}, [$name, $hline]);
934 }
935 }
936111µs });
937
938=item remove_header { spam | ham | all } header_name
939
940Headers can be removed from the specified type of messages (spam, ham,
941or "all" to remove from either). All headers begin with C<X-Spam->
942(so C<header_name> will be appended to C<X-Spam->).
943
944See also C<clear_headers> for removing all the headers at once.
945
946Note that B<X-Spam-Checker-Version> is not removable because the version
947information is needed by mail administrators and developers to debug
948problems. Without at least one header, it might not even be possible to
949determine that SpamAssassin is running.
950
951=cut
952
953 push (@cmds, {
954 setting => 'remove_header',
955 code => sub {
956 my ($self, $key, $value, $line) = @_;
957 local ($1,$2);
958 if ($value !~ /^(ham|spam|all)\s+([A-Za-z0-9_-]+)\s*$/) {
959 return $INVALID_VALUE;
960 }
961
962 my ($type, $name) = ($1, $2);
963 return if ( $name eq "Checker-Version" );
964
965 $name = lc($name);
966 if (($type eq "ham") || ($type eq "all")) {
967 $self->{headers_ham} =
968 [ grep { lc($_->[0]) ne $name } @{$self->{headers_ham}} ];
969 }
970 if (($type eq "spam") || ($type eq "all")) {
971 $self->{headers_spam} =
972 [ grep { lc($_->[0]) ne $name } @{$self->{headers_spam}} ];
973 }
974 }
975110µs });
976
977=item clear_headers
978
979Clear the list of headers to be added to messages. You may use this
980before any B<add_header> options to prevent the default headers from being
981added to the message.
982
983C<add_header>, C<clear_headers> and C<remove_header> may appear in multiple
984.cf files, which are interpreted in alphabetic order, so C<clear_headers>
985in a later file will remove all added headers from previously interpreted
986configuration files, which may or may not be desired.
987
988Note that B<X-Spam-Checker-Version> is not removable because the version
989information is needed by mail administrators and developers to debug
990problems. Without at least one header, it might not even be possible to
991determine that SpamAssassin is running.
992
993=cut
994
995 push (@cmds, {
996 setting => 'clear_headers',
997 type => $CONF_TYPE_NOARGS,
998
# spent 51µs within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1007] which was called: # once (51µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
99915µs my ($self, $key, $value, $line) = @_;
100014µs unless (!defined $value || $value eq '') {
1001 return $INVALID_VALUE;
1002 }
100317µs my @h = grep { lc($_->[0]) eq "checker-version" }
1004217µs @{$self->{headers_ham}};
100516µs $self->{headers_ham} = !@h ? [] : [ $h[0] ];
1006115µs $self->{headers_spam} = !@h ? [] : [ $h[0] ];
1007 }
1008110µs });
1009
1010=item report_safe ( 0 | 1 | 2 ) (default: 1)
1011
1012if this option is set to 1, if an incoming message is tagged as spam,
1013instead of modifying the original message, SpamAssassin will create a
1014new report message and attach the original message as a message/rfc822
1015MIME part (ensuring the original message is completely preserved, not
1016easily opened, and easier to recover).
1017
1018If this option is set to 2, then original messages will be attached with
1019a content type of text/plain instead of message/rfc822. This setting
1020may be required for safety reasons on certain broken mail clients that
1021automatically load attachments without any action by the user. This
1022setting may also make it somewhat more difficult to extract or view the
1023original message.
1024
1025If this option is set to 0, incoming spam is only modified by adding
1026some C<X-Spam-> headers and no changes will be made to the body. In
1027addition, a header named B<X-Spam-Report> will be added to spam. You
1028can use the B<remove_header> option to remove that header after setting
1029B<report_safe> to 0.
1030
1031See B<report_safe_copy_headers> if you want to copy headers from
1032the original mail into tagged messages.
1033
1034=cut
1035
1036 push (@cmds, {
1037 setting => 'report_safe',
1038 default => 1,
1039 type => $CONF_TYPE_NUMERIC,
1040
# spent 41µs (34+7) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1054] which was called: # once (34µs+7µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
104116µs my ($self, $key, $value, $line) = @_;
1042120µs18µs if ($value eq '') {
# spent 8µs making 1 call to Mail::SpamAssassin::Conf::CORE:match
1043 return $MISSING_REQUIRED_VALUE;
1044 }
1045 elsif ($value !~ /^[012]$/) {
1046 return $INVALID_VALUE;
1047 }
1048
104916µs $self->{report_safe} = $value+0;
1050112µs if (! $self->{report_safe} &&
1051 ! (grep { lc($_->[0]) eq "report" } @{$self->{headers_spam}}) ) {
1052 push(@{$self->{headers_spam}}, ["Report", "_REPORT_"]);
1053 }
1054 }
1055123µs });
1056
1057=back
1058
1059=head2 LANGUAGE OPTIONS
1060
1061=over 4
1062
1063=item ok_locales xx [ yy zz ... ] (default: all)
1064
1065This option is used to specify which locales are considered OK for
1066incoming mail. Mail using the B<character sets> that are allowed by
1067this option will not be marked as possibly being spam in a foreign
1068language.
1069
1070If you receive lots of spam in foreign languages, and never get any non-spam in
1071these languages, this may help. Note that all ISO-8859-* character sets, and
1072Windows code page character sets, are always permitted by default.
1073
1074Set this to C<all> to allow all character sets. This is the default.
1075
1076The rules C<CHARSET_FARAWAY>, C<CHARSET_FARAWAY_BODY>, and
1077C<CHARSET_FARAWAY_HEADERS> are triggered based on how this is set.
1078
1079Examples:
1080
1081 ok_locales all (allow all locales)
1082 ok_locales en (only allow English)
1083 ok_locales en ja zh (allow English, Japanese, and Chinese)
1084
1085Note: if there are multiple ok_locales lines, only the last one is used.
1086
1087Select the locales to allow from the list below:
1088
1089=over 4
1090
1091=item en - Western character sets in general
1092
1093=item ja - Japanese character sets
1094
1095=item ko - Korean character sets
1096
1097=item ru - Cyrillic character sets
1098
1099=item th - Thai character sets
1100
1101=item zh - Chinese (both simplified and traditional) character sets
1102
1103=back
1104
1105=cut
1106
110715µs push (@cmds, {
1108 setting => 'ok_locales',
1109 default => 'all',
1110 type => $CONF_TYPE_STRING,
1111 });
1112
1113=item normalize_charset ( 0 | 1) (default: 0)
1114
1115Whether to decode non- UTF-8 and non-ASCII textual parts and recode them
1116to UTF-8 before the text is given over to rules processing. The character
1117set used for attempted decoding is primarily based on a declared character
1118set in a Content-Type header, but if the decoding attempt fails a module
1119Encode::Detect::Detector is consulted (if available) to provide a guess
1120based on the actual text, and decoding is re-attempted. Even if the option
1121is enabled no unnecessary decoding and re-encoding work is done when
1122possible (like with an all-ASCII text with a US-ASCII or extended ASCII
1123character set declaration, e.g. UTF-8 or ISO-8859-nn or Windows-nnnn).
1124
1125Unicode support in old versions of perl or in a core module Encode is likely
1126to be buggy in places, so if the normalize_charset function is enabled
1127it is advised to stick to more recent versions of perl (preferably 5.12
1128or later). The module Encode::Detect::Detector is optional, when necessary
1129it will be used if it is available.
1130
1131=cut
1132
1133 push (@cmds, {
1134 setting => 'normalize_charset',
1135 default => 0,
1136 type => $CONF_TYPE_BOOL,
1137 code => sub {
1138 my ($self, $key, $value, $line) = @_;
1139 unless (defined $value && $value !~ /^$/) {
1140 return $MISSING_REQUIRED_VALUE;
1141 }
1142 if (lc $value eq 'yes' || $value eq '1') { $value = 1 }
1143 elsif (lc $value eq 'no' || $value eq '0') { $value = 0 }
1144 else { return $INVALID_VALUE }
1145
1146 $self->{normalize_charset} = $value;
1147
1148 unless ($] > 5.008004) {
1149 $self->{parser}->lint_warn("config: normalize_charset requires Perl 5.8.5 or later");
1150 $self->{normalize_charset} = 0;
1151 return $INVALID_VALUE;
1152 }
1153 require HTML::Parser;
1154 #changed to eval to use VERSION so that this version was not incorrectly parsed for CPAN
1155 unless ( eval { HTML::Parser->VERSION(3.46) } ) {
1156 $self->{parser}->lint_warn("config: normalize_charset requires HTML::Parser 3.46 or later");
1157 $self->{normalize_charset} = 0;
1158 return $INVALID_VALUE;
1159 }
1160 unless (eval 'require Encode') {
1161 $self->{parser}->lint_warn("config: normalize_charset requires Encode");
1162 $self->{normalize_charset} = 0;
1163 return $INVALID_VALUE;
1164 }
1165 }
1166113µs });
1167
1168
1169=back
1170
1171=head2 NETWORK TEST OPTIONS
1172
1173=over 4
1174
1175=item trusted_networks IPaddress[/masklen] ... (default: none)
1176
1177What networks or hosts are 'trusted' in your setup. B<Trusted> in this case
1178means that relay hosts on these networks are considered to not be potentially
1179operated by spammers, open relays, or open proxies. A trusted host could
1180conceivably relay spam, but will not originate it, and will not forge header
1181data. DNS blacklist checks will never query for hosts on these networks.
1182
1183See C<http://wiki.apache.org/spamassassin/TrustPath> for more information.
1184
1185MXes for your domain(s) and internal relays should B<also> be specified using
1186the C<internal_networks> setting. When there are 'trusted' hosts that
1187are not MXes or internal relays for your domain(s) they should B<only> be
1188specified in C<trusted_networks>.
1189
1190The C<IPaddress> can be an IPv4 address (in a dot-quad form), or an IPv6
1191address optionally enclosed in square brackets. Scoped link-local IPv6
1192addresses are syntactically recognized but the interface scope is currently
1193ignored (e.g. [fe80::1234%eth0] ) and should be avoided.
1194
1195If a C</masklen> is specified, it is considered a CIDR-style 'netmask' length,
1196specified in bits. If it is not specified, but less than 4 octets of an IPv4
1197address are specified with a trailing dot, an implied netmask length covers
1198all addresses in remaining octets (i.e. implied masklen is /8 or /16 or /24).
1199If masklen is not specified, and there is not trailing dot, then just a single
1200IP address specified is used, as if the masklen were C</32> with an IPv4
1201address, or C</128> in case of an IPv6 address.
1202
1203If a network or host address is prefaced by a C<!> the matching network or
1204host will be excluded from the list even if a less specific (shorter netmask
1205length) subnet is later specified in the list. This allows a subset of
1206a wider network to be exempt. In case of specifying overlapping subnets,
1207specify more specific subnets first (tighter matching, i.e. with a longer
1208netmask length), followed by less specific (shorter netmask length) subnets
1209to get predictable results regarless of the search algorithm used - when
1210Net::Patricia module is installed the search finds the tightest matching
1211entry in the list, while a sequential search as used in absence of the
1212module Net::Patricia will find the first matching entry in the list.
1213
1214Note: 127.0.0.0/8 and ::1 are always included in trusted_networks, regardless
1215of your config.
1216
1217Examples:
1218
1219 trusted_networks 192.168.0.0/16 # all in 192.168.*.*
1220 trusted_networks 192.168. # all in 192.168.*.*
1221 trusted_networks 212.17.35.15 # just that host
1222 trusted_networks !10.0.1.5 10.0.1/24 # all in 10.0.1.* but not 10.0.1.5
1223 trusted_networks 2001:db8:1::1 !2001:db8:1::/64 2001:db8::/32
1224 # 2001:db8::/32 and 2001:db8:1::1/128, except the rest of 2001:db8:1::/64
1225
1226This operates additively, so a C<trusted_networks> line after another one
1227will append new entries to the list of trusted networks. To clear out the
1228existing entries, use C<clear_trusted_networks>.
1229
1230If C<trusted_networks> is not set and C<internal_networks> is, the value
1231of C<internal_networks> will be used for this parameter.
1232
1233If neither C<trusted_networks> or C<internal_networks> is set, a basic
1234inference algorithm is applied. This works as follows:
1235
1236=over 4
1237
1238=item *
1239
1240If the 'from' host has an IP address in a private (RFC 1918) network range,
1241then it's trusted
1242
1243=item *
1244
1245If there are authentication tokens in the received header, and
1246the previous host was trusted, then this host is also trusted
1247
1248=item *
1249
1250Otherwise this host, and all further hosts, are consider untrusted.
1251
1252=back
1253
1254=cut
1255
125614µs push (@cmds, {
1257 setting => 'trusted_networks',
1258 type => $CONF_TYPE_IPADDRLIST,
1259 });
1260
1261=item clear_trusted_networks
1262
1263Empty the list of trusted networks.
1264
1265=cut
1266
1267 push (@cmds, {
1268 setting => 'clear_trusted_networks',
1269 type => $CONF_TYPE_NOARGS,
1270 code => sub {
1271 my ($self, $key, $value, $line) = @_;
1272 unless (!defined $value || $value eq '') {
1273 return $INVALID_VALUE;
1274 }
1275 $self->{trusted_networks} = $self->new_netset('trusted_networks',1);
1276 $self->{trusted_networks_configured} = 0;
1277 }
1278110µs });
1279
1280=item internal_networks IPaddress[/masklen] ... (default: none)
1281
1282What networks or hosts are 'internal' in your setup. B<Internal> means
1283that relay hosts on these networks are considered to be MXes for your
1284domain(s), or internal relays. This uses the same syntax as
1285C<trusted_networks>, above - see there for details.
1286
1287This value is used when checking 'dial-up' or dynamic IP address
1288blocklists, in order to detect direct-to-MX spamming.
1289
1290Trusted relays that accept mail directly from dial-up connections
1291(i.e. are also performing a role of mail submission agents - MSA)
1292should not be listed in C<internal_networks>. List them only in
1293C<trusted_networks>.
1294
1295If C<trusted_networks> is set and C<internal_networks> is not, the value
1296of C<trusted_networks> will be used for this parameter.
1297
1298If neither C<trusted_networks> nor C<internal_networks> is set, no addresses
1299will be considered local; in other words, any relays past the machine where
1300SpamAssassin is running will be considered external.
1301
1302Every entry in C<internal_networks> must appear in C<trusted_networks>; in
1303other words, C<internal_networks> is always a subset of the trusted set.
1304
1305Note: 127/8 and ::1 are always included in internal_networks, regardless of
1306your config.
1307
1308=cut
1309
131014µs push (@cmds, {
1311 setting => 'internal_networks',
1312 type => $CONF_TYPE_IPADDRLIST,
1313 });
1314
1315=item clear_internal_networks
1316
1317Empty the list of internal networks.
1318
1319=cut
1320
1321 push (@cmds, {
1322 setting => 'clear_internal_networks',
1323 type => $CONF_TYPE_NOARGS,
1324 code => sub {
1325 my ($self, $key, $value, $line) = @_;
1326 unless (!defined $value || $value eq '') {
1327 return $INVALID_VALUE;
1328 }
1329 $self->{internal_networks} = $self->new_netset('internal_networks',1);
1330 $self->{internal_networks_configured} = 0;
1331 }
1332110µs });
1333
1334=item msa_networks IPaddress[/masklen] ... (default: none)
1335
1336The networks or hosts which are acting as MSAs in your setup (but not also
1337as MX relays). This uses the same syntax as C<trusted_networks>, above - see
1338there for details.
1339
1340B<MSA> means that the relay hosts on these networks accept mail from your
1341own users and authenticates them appropriately. These relays will never
1342accept mail from hosts that aren't authenticated in some way. Examples of
1343authentication include, IP lists, SMTP AUTH, POP-before-SMTP, etc.
1344
1345All relays found in the message headers after the MSA relay will take
1346on the same trusted and internal classifications as the MSA relay itself,
1347as defined by your I<trusted_networks> and I<internal_networks> configuration.
1348
1349For example, if the MSA relay is trusted and internal so will all of the
1350relays that precede it.
1351
1352When using msa_networks to identify an MSA it is recommended that you treat
1353that MSA as both trusted and internal. When an MSA is not included in
1354msa_networks you should treat the MSA as trusted but not internal, however
1355if the MSA is also acting as an MX or intermediate relay you must always
1356treat it as both trusted and internal and ensure that the MSA includes
1357visible auth tokens in its Received header to identify submission clients.
1358
1359B<Warning:> Never include an MSA that also acts as an MX (or is also an
1360intermediate relay for an MX) or otherwise accepts mail from
1361non-authenticated users in msa_networks. Doing so will result in unknown
1362external relays being trusted.
1363
1364=cut
1365
136615µs push (@cmds, {
1367 setting => 'msa_networks',
1368 type => $CONF_TYPE_IPADDRLIST,
1369 });
1370
1371=item clear_msa_networks
1372
1373Empty the list of msa networks.
1374
1375=cut
1376
1377 push (@cmds, {
1378 setting => 'clear_msa_networks',
1379 type => $CONF_TYPE_NOARGS,
1380 code => sub {
1381 my ($self, $key, $value, $line) = @_;
1382 unless (!defined $value || $value eq '') {
1383 return $INVALID_VALUE;
1384 }
1385 $self->{msa_networks} =
1386 $self->new_netset('msa_networks',0); # no loopback IP
1387 $self->{msa_networks_configured} = 0;
1388 }
1389110µs });
1390
1391=item originating_ip_headers header ... (default: X-Yahoo-Post-IP X-Originating-IP X-Apparently-From X-SenderIP)
1392
1393A list of header field names from which an originating IP address can
1394be obtained. For example, webmail servers may record a client IP address
1395in X-Originating-IP.
1396
1397These IP addresses are virtually appended into the Received: chain, so they
1398are used in RBL checks where appropriate.
1399
1400Currently the IP addresses are not added into X-Spam-Relays-* header fields,
1401but they may be in the future.
1402
1403=cut
1404
1405 push (@cmds, {
1406 setting => 'originating_ip_headers',
1407 default => [],
1408 type => $CONF_TYPE_STRINGLIST,
1409
# spent 132µs (126+6) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1419] which was called 2 times, avg 66µs/call: # 2 times (126µs+6µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 66µs/call
code => sub {
1410210µs my ($self, $key, $value, $line) = @_;
1411221µs26µs unless (defined $value && $value !~ /^$/) {
# spent 6µs making 2 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
1412 return $MISSING_REQUIRED_VALUE;
1413 }
1414234µs foreach my $hfname (split(/\s+/, $value)) {
1415 # avoid duplicates, consider header field names case-insensitive
141659µs push(@{$self->{originating_ip_headers}}, $hfname)
14171067µs if !grep(lc($_) eq lc($hfname), @{$self->{originating_ip_headers}});
1418 }
1419 }
1420111µs });
1421
1422=item clear_originating_ip_headers
1423
1424Empty the list of 'originating IP address' header field names.
1425
1426=cut
1427
1428 push (@cmds, {
1429 setting => 'clear_originating_ip_headers',
1430 type => $CONF_TYPE_NOARGS,
1431
# spent 17µs within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1437] which was called: # once (17µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
143215µs my ($self, $key, $value, $line) = @_;
143313µs unless (!defined $value || $value eq '') {
1434 return $INVALID_VALUE;
1435 }
1436112µs $self->{originating_ip_headers} = [];
1437 }
143819µs });
1439
1440=item always_trust_envelope_sender ( 0 | 1 ) (default: 0)
1441
1442Trust the envelope sender even if the message has been passed through one or
1443more trusted relays. See also C<envelope_sender_header>.
1444
1445=cut
1446
144715µs push (@cmds, {
1448 setting => 'always_trust_envelope_sender',
1449 default => 0,
1450 type => $CONF_TYPE_BOOL,
1451 });
1452
1453=item skip_rbl_checks ( 0 | 1 ) (default: 0)
1454
1455Turning on the skip_rbl_checks setting will disable the DNSEval plugin,
1456which implements Real-time Block List (or: Blackhole List) (RBL) lookups.
1457
1458By default, SpamAssassin will run RBL checks. Individual blocklists may
1459be disabled selectively by setting a score of a corresponding rule to 0.
1460
1461See also a related configuration parameter skip_uribl_checks,
1462which controls the URIDNSBL plugin (documented in the URIDNSBL man page).
1463
1464=cut
1465
146615µs push (@cmds, {
1467 setting => 'skip_rbl_checks',
1468 default => 0,
1469 type => $CONF_TYPE_BOOL,
1470 });
1471
1472=item dns_available { yes | no | test[: domain1 domain2...] } (default: yes)
1473
1474Tells SpamAssassin whether DNS resolving is available or not. A value I<yes>
1475indicates DNS resolving is available, a value I<no> indicates DNS resolving
1476is not available - both of these values apply unconditionally and skip initial
1477DNS tests, which can be slow or unreliable.
1478
1479When the option value is a I<test> (with or without arguments), SpamAssassin
1480will query some domain names on the internet during initialization, attempting
1481to determine if DNS resolving is working or not. A space-separated list
1482of domain names may be specified explicitly, or left to a built-in default
1483of a dozen or so domain names. From an explicit or a default list a subset
1484of three domain names is picked randomly for checking. The test queries for
1485NS records of these domain: if at least one query returns a success then
1486SpamAssassin considers DNS resolving as available, otherwise not.
1487
1488The problem is that the test can introduce some startup delay if a network
1489connection is down, and in some cases it can wrongly guess that DNS is
1490unavailable because a test connection failed, what causes disabling several
1491DNS-dependent tests.
1492
1493Please note, the DNS test queries for NS records, so specify domain names,
1494not host names.
1495
1496Since version 3.4.0 of SpamAssassin a default setting for option
1497I<dns_available> is I<yes>. A default in older versions was I<test>.
1498
1499=cut
1500
1501 push (@cmds, {
1502 setting => 'dns_available',
1503 default => 'yes',
1504 type => $CONF_TYPE_STRING,
1505 code => sub {
1506 my ($self, $key, $value, $line) = @_;
1507 if ($value =~ /^test(?::\s*\S.*)?$/) {
1508 $self->{dns_available} = $value;
1509 }
1510 elsif ($value =~ /^(?:yes|1)$/) {
1511 $self->{dns_available} = 'yes';
1512 }
1513 elsif ($value =~ /^(?:no|0)$/) {
1514 $self->{dns_available} = 'no';
1515 }
1516 else {
1517 return $INVALID_VALUE;
1518 }
1519 }
1520111µs });
1521
1522=item dns_server ip-addr-port (default: entries provided by Net::DNS)
1523
1524Specifies an IP address of a DNS server, and optionally its port number.
1525The I<dns_server> directive may be specified multiple times, each entry
1526adding to a list of available resolving name servers. The I<ip-addr-port>
1527argument can either be an IPv4 or IPv6 address, optionally enclosed in
1528brackets, and optionally followed by a colon and a port number. In absence
1529of a port number a standard port number 53 is assumed. When an IPv6 address
1530is specified along with a port number, the address B<must> be enclosed in
1531brackets to avoid parsing ambiguity regarding a colon separator. A scoped
1532link-local IP address is allowed (assuming underlying modules allow it).
1533
1534Examples :
1535 dns_server 127.0.0.1
1536 dns_server 127.0.0.1:53
1537 dns_server [127.0.0.1]:53
1538 dns_server [::1]:53
1539 dns_server fe80::1%lo0
1540 dns_server [fe80::1%lo0]:53
1541
1542In absence of I<dns_server> directives, the list of name servers is provided
1543by Net::DNS module, which typically obtains the list from /etc/resolv.conf,
1544but this may be platform dependent. Please consult the Net::DNS::Resolver
1545documentation for details.
1546
1547=cut
1548
1549 push (@cmds, {
1550 setting => 'dns_server',
1551 type => $CONF_TYPE_STRING,
1552 code => sub {
1553 my ($self, $key, $value, $line) = @_;
1554 my($address,$port); local($1,$2,$3);
1555 if ($value =~ /^(?: \[ ([^\]]*) \] | ([^:]*) ) : (\d+) \z/sx) {
1556 $address = defined $1 ? $1 : $2; $port = $3;
1557 } elsif ($value =~ /^(?: \[ ([^\]]*) \] |
1558 ([0-9A-F.:]+ (?: %[A-Z0-9._~-]* )? ) ) \z/six) {
1559 $address = defined $1 ? $1 : $2; $port = '53';
1560 } else {
1561 return $INVALID_VALUE;
1562 }
1563 my $scope = ''; # scoped IP address?
1564 $scope = $1 if $address =~ s/ ( % [A-Z0-9._~-]* ) \z//xsi;
1565 my $IP_ADDRESS = IP_ADDRESS; # IP_ADDRESS regexp does not handle scope
1566 if ($address =~ /$IP_ADDRESS/ && $port >= 1 && $port <= 65535) {
1567 $self->{dns_servers} = [] if !$self->{dns_servers};
1568 # checked, untainted, stored in a normalized form
1569 push(@{$self->{dns_servers}}, untaint_var("[$address$scope]:$port"));
1570 } else {
1571 return $INVALID_VALUE;
1572 }
1573 }
1574120µs });
1575
1576=item clear_dns_servers
1577
1578Empty the list of explicitly configured DNS servers through a I<dns_server>
1579directive, falling back to Net::DNS -supplied defaults.
1580
1581=cut
1582
1583 push (@cmds, {
1584 setting => 'clear_dns_servers',
1585 type => $CONF_TYPE_NOARGS,
1586 code => sub {
1587 my ($self, $key, $value, $line) = @_;
1588 unless (!defined $value || $value eq '') {
1589 return $INVALID_VALUE;
1590 }
1591 undef $self->{dns_servers};
1592 }
1593110µs });
1594
1595=item dns_local_ports_permit ranges...
1596
1597Add the specified ports or ports ranges to the set of allowed port numbers
1598that can be used as local port numbers when sending DNS queries to a resolver.
1599
1600The argument is a whitespace-separated or a comma-separated list of
1601single port numbers n, or port number pairs (i.e. m-n) delimited by a '-',
1602representing a range. Allowed port numbers are between 1 and 65535.
1603
1604Directives I<dns_local_ports_permit> and I<dns_local_ports_avoid> are processed
1605in order in which they appear in configuration files. Each directive adds
1606(or subtracts) its subsets of ports to a current set of available ports.
1607Whatever is left in the set by the end of configuration processing
1608is made available to a DNS resolving client code.
1609
1610If the resulting set of port numbers is empty (see also the directive
1611I<dns_local_ports_none>), then SpamAssassin does not apply its ports
1612randomization logic, but instead leaves the operating system to choose
1613a suitable free local port number.
1614
1615The initial set consists of all port numbers in the range 1024-65535.
1616Note that system config files already modify the set and remove all the
1617IANA registered port numbers and some other ranges, so there is rarely
1618a need to adjust the ranges by site-specific directives.
1619
1620See also directives I<dns_local_ports_permit> and I<dns_local_ports_none>.
1621
1622=cut
1623
1624 push (@cmds, {
1625 setting => 'dns_local_ports_permit',
1626 type => $CONF_TYPE_STRING,
1627 is_admin => 1,
1628 code => sub {
1629 my($self, $key, $value, $line) = @_;
1630 my(@port_ranges); local($1,$2);
1631 foreach my $range (split(/[ \t,]+/, $value)) {
1632 if ($range =~ /^(\d{1,5})\z/) {
1633 # don't allow adding a port number 0
1634 if ($1 < 1 || $1 > 65535) { return $INVALID_VALUE }
1635 push(@port_ranges, [$1,$1]);
1636 } elsif ($range =~ /^(\d{1,5})-(\d{1,5})\z/) {
1637 if ($1 < 1 || $1 > 65535) { return $INVALID_VALUE }
1638 if ($2 < 1 || $2 > 65535) { return $INVALID_VALUE }
1639 push(@port_ranges, [$1,$2]);
1640 } else {
1641 return $INVALID_VALUE;
1642 }
1643 }
1644 foreach my $p (@port_ranges) {
1645 undef $self->{dns_available_portscount}; # invalidate derived data
1646 set_ports_range(\$self->{dns_available_ports_bitset},
1647 $p->[0], $p->[1], 1);
1648 }
1649 }
1650121µs });
1651
1652=item dns_local_ports_avoid ranges...
1653
1654Remove specified ports or ports ranges from the set of allowed port numbers
1655that can be used as local port numbers when sending DNS queries to a resolver.
1656
1657Please see directive I<dns_local_ports_permit> for details.
1658
1659=cut
1660
1661 push (@cmds, {
1662 setting => 'dns_local_ports_avoid',
1663 type => $CONF_TYPE_STRING,
1664 is_admin => 1,
1665
# spent 87.4ms (6.44+81.0) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1685] which was called 30 times, avg 2.91ms/call: # 30 times (6.44ms+81.0ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 2.91ms/call
code => sub {
166630137µs my($self, $key, $value, $line) = @_;
166760140µs my(@port_ranges); local($1,$2);
166830378µs foreach my $range (split(/[ \t,]+/, $value)) {
16691902.82ms247847µs if ($range =~ /^(\d{1,5})\z/) {
# spent 847µs making 247 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
1670133291µs if ($1 > 65535) { return $INVALID_VALUE }
1671 # don't mind clearing also the port number 0
1672133511µs push(@port_ranges, [$1,$1]);
1673 } elsif ($range =~ /^(\d{1,5})-(\d{1,5})\z/) {
167457170µs if ($1 > 65535 || $2 > 65535) { return $INVALID_VALUE }
167557221µs push(@port_ranges, [$1,$2]);
1676 } else {
1677 return $INVALID_VALUE;
1678 }
1679 }
168030424µs foreach my $p (@port_ranges) {
1681190394µs undef $self->{dns_available_portscount}; # invalidate derived data
1682 set_ports_range(\$self->{dns_available_ports_bitset},
16831901.50ms19080.1ms $p->[0], $p->[1], 0);
# spent 80.1ms making 190 calls to Mail::SpamAssassin::Conf::set_ports_range, avg 422µs/call
1684 }
1685 }
1686111µs });
1687
1688=item dns_local_ports_none
1689
1690Is a fast shorthand for:
1691
1692 dns_local_ports_avoid 1-65535
1693
1694leaving the set of available DNS query local port numbers empty. In all
1695respects (apart from speed) it is equivalent to the shown directive, and can
1696be freely mixed with I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
1697
1698If the resulting set of port numbers is empty, then SpamAssassin does not
1699apply its ports randomization logic, but instead leaves the operating system
1700to choose a suitable free local port number.
1701
1702See also directives I<dns_local_ports_permit> and I<dns_local_ports_avoid>.
1703
1704=cut
1705
1706 push (@cmds, {
1707 setting => 'dns_local_ports_none',
1708 type => $CONF_TYPE_NOARGS,
1709 is_admin => 1,
1710 code => sub {
1711 my ($self, $key, $value, $line) = @_;
1712 unless (!defined $value || $value eq '') {
1713 return $INVALID_VALUE;
1714 }
1715 undef $self->{dns_available_portscount}; # invalidate derived data
1716 wipe_ports_range(\$self->{dns_available_ports_bitset}, 0);
1717 }
1718110µs });
1719
1720=item dns_test_interval n (default: 600 seconds)
1721
1722If dns_available is set to I<test>, the dns_test_interval time in number
1723of seconds will tell SpamAssassin how often to retest for working DNS.
1724A numeric value is optionally suffixed by a time unit (s, m, h, d, w,
1725indicating seconds (default), minutes, hours, days, weeks).
1726
1727=cut
1728
172915µs push (@cmds, {
1730 setting => 'dns_test_interval',
1731 default => 600,
1732 type => $CONF_TYPE_DURATION,
1733 });
1734
1735=item dns_options opts (default: norotate, nodns0x20, edns=4096)
1736
1737Provides a (whitespace or comma -separated) list of options applying
1738to DNS resolving. Available options are: I<rotate>, I<dns0x20> and
1739I<edns> (or I<edns0>). Option name may be negated by prepending a I<no>
1740(e.g. I<norotate>, I<NoEDNS>) to counteract a previously enabled option.
1741Option names are not case-sensitive. The I<dns_options> directive may
1742appear in configuration files multiple times, the last setting prevails.
1743
1744Option I<edns> (or I<edsn0>) may take a value which specifies a requestor's
1745acceptable UDP payload size according to EDNS0 specifications (RFC 6891,
1746ex RFC 2671) e.g. I<edns=4096>. When EDNS0 is off (I<noedns> or I<edns=512>)
1747a traditional implied UDP payload size is 512 bytes, which is also a minimum
1748allowed value for this option. When the option is specified but a value
1749is not provided, a conservative default of 1220 bytes is implied. It is
1750recommended to keep I<edns> enabled when using a local recursive DNS server
1751which supports EDNS0 (like most modern DNS servers do), a suitable setting
1752in this case is I<edns=4096>, which is also a default. Allowing UDP payload
1753size larger than 512 bytes can avoid truncation of resource records in large
1754DNS responses (like in TXT records of some SPF and DKIM responses, or when
1755an unreasonable number of A records is published by some domain). The option
1756should be disabled when a recursive DNS server is only reachable through
1757non- RFC 6891 compliant middleboxes (such as some old-fashioned firewall)
1758which bans DNS UDP payload sizes larger than 512 bytes. A suitable value
1759when a non-local recursive DNS server is used and a middlebox B<does> allow
1760EDNS0 but blocks fragmented IP packets is perhaps 1220 bytes, allowing a
1761DNS UDP packet to fit within a single IP packet in most cases (a slightly
1762less conservative range would be 1280-1410 bytes).
1763
1764Option I<rotate> causes SpamAssassin to choose a DNS server at random
1765from all servers listed in C</etc/resolv.conf> every I<dns_test_interval>
1766seconds, effectively spreading the load over all currently available DNS
1767servers when there are many spamd workers.
1768
1769Option I<dns0x20> enables randomization of letters in a DNS query label
1770according to draft-vixie-dnsext-dns0x20, decreasing a chance of collisions
1771of responses (by chance or by a malicious intent) by increasing spread
1772as provided by a 16-bit query ID and up to 16 bits of a port number,
1773with additional bits as encoded by flipping case (upper/lower) of letters
1774in a query. The number of additional random bits corresponds to the number
1775of letters in a query label. Should work reliably with all mainstream
1776DNS servers - do not turn on if you see frequent info messages
1777"dns: no callback for id:" in the log, or if RBL or URIDNS lookups
1778do not work for no apparent reason.
1779
1780=cut
1781
1782 push (@cmds, {
1783 setting => 'dns_options',
1784 type => $CONF_TYPE_HASH_KEY_VALUE,
1785 code => sub {
1786 my ($self, $key, $value, $line) = @_;
1787 foreach my $option (split (/[\s,]+/, lc $value)) {
1788 local($1,$2);
1789 if ($option =~ /^no(rotate|dns0x20)\z/) {
1790 $self->{dns_options}->{$1} = 0;
1791 } elsif ($option =~ /^no(edns)0?\z/) {
1792 $self->{dns_options}->{$1} = 0;
1793 } elsif ($option =~ /^(rotate|dns0x20)\z/) {
1794 $self->{dns_options}->{$1} = 1;
1795 } elsif ($option =~ /^(edns)0? (?: = (\d+) )? \z/x) {
1796 # RFC 6891 (ex RFC 2671) - EDNS0, value is a requestor's UDP payload
1797 # size, defaults to some UDP packet size likely to fit into a single
1798 # IP packet which is more likely to pass firewalls which choke on IP
1799 # fragments. RFC 2460: min MTU is 1280 for IPv6, minus 40 bytes for
1800 # basic header, yielding 1240. RFC 3226 prescribes a min of 1220 for
1801 # RFC 2535 compliant servers. RFC 6891: choosing between 1280 and
1802 # 1410 bytes for IP (v4 or v6) over Ethernet would be reasonable.
1803 #
1804 $self->{dns_options}->{$1} = $2 || 1220;
1805 return $INVALID_VALUE if $self->{dns_options}->{$1} < 512;
1806 } else {
1807 return $INVALID_VALUE;
1808 }
1809 }
1810 }
1811110µs });
1812
1813=item dns_query_restriction (allow|deny) domain1 domain2 ...
1814
1815Option allows disabling of rules which would result in a DNS query to one of
1816the listed domains. The first argument must be a literal C<allow> or C<deny>,
1817remaining arguments are domains names.
1818
1819Most DNS queries (with some exceptions) are subject to dns_query_restriction.
1820A domain to be queried is successively stripped-off of its leading labels
1821(thus yielding a series of its parent domains), and on each iteration a
1822check is made against an associative array generated by dns_query_restriction
1823options. Search stops at the first match (i.e. the tightest match), and the
1824matching entry with its C<allow> or C<deny> value then controls whether a
1825DNS query is allowed to be launched.
1826
1827If no match is found an implicit default is to allow a query. The purpose of
1828an explicit C<allow> entry is to be able to override a previously configured
1829C<deny> on the same domain or to override an entry (possibly yet to be
1830configured in subsequent config directives) on one of its parent domains.
1831Thus an 'allow zen.spamhaus.org' with a 'deny spamhaus.org' would permit
1832DNS queries on a specific DNS BL zone but deny queries to other zones under
1833the same parent domain.
1834
1835Domains are matched case-insensitively, no wildcards are recognized,
1836there should be no leading or trailing dot.
1837
1838Specifying a block on querying a domain name has a similar effect as setting
1839a score of corresponding DNSBL and URIBL rules to zero, and can be a handy
1840alternative to hunting for such rules when a site policy does not allow
1841certain DNS block lists to be queried.
1842
1843Example:
1844 dns_query_restriction deny dnswl.org surbl.org
1845 dns_query_restriction allow zen.spamhaus.org
1846 dns_query_restriction deny spamhaus.org mailspike.net spamcop.net
1847
1848=cut
1849
1850 push (@cmds, {
1851 setting => 'dns_query_restriction',
1852 type => $CONF_TYPE_STRING,
1853 code => sub {
1854 my ($self, $key, $value, $line) = @_;
1855 defined $value && $value =~ s/^(allow|deny)\s+//i
1856 or return $INVALID_VALUE;
1857 my $blocked = lc($1) eq 'deny' ? 1 : 0;
1858 foreach my $domain (split(' ', $value)) {
1859 $domain =~ s/^\.//; $domain =~ s/\.\z//; # strip dots
1860 $self->{dns_query_blocked}{lc $domain} = $blocked;
1861 }
1862 }
1863115µs });
1864
1865=item clear_dns_query_restriction
1866
1867The option removes any entries entered by previous 'dns_query_restriction'
1868options, leaving the list empty, i.e. allowing DNS queries for any domain
1869(including any DNS BL zone).
1870
1871=cut
1872
1873 push (@cmds, {
1874 setting => 'clear_dns_query_restriction',
1875 aliases => ['clear_dns_query_restrictions'],
1876 type => $CONF_TYPE_NOARGS,
1877 code => sub {
1878 my ($self, $key, $value, $line) = @_;
1879 return $INVALID_VALUE if defined $value && $value ne '';
1880 delete $self->{dns_query_blocked};
1881 }
1882111µs });
1883
1884=back
1885
1886=head2 LEARNING OPTIONS
1887
1888=over 4
1889
1890=item use_learner ( 0 | 1 ) (default: 1)
1891
1892Whether to use any machine-learning classifiers with SpamAssassin, such as the
1893default 'BAYES_*' rules. Setting this to 0 will disable use of any and all
1894human-trained classifiers.
1895
1896=cut
1897
189816µs push (@cmds, {
1899 setting => 'use_learner',
1900 default => 1,
1901 type => $CONF_TYPE_BOOL,
1902 });
1903
1904=item use_bayes ( 0 | 1 ) (default: 1)
1905
1906Whether to use the naive-Bayesian-style classifier built into
1907SpamAssassin. This is a master on/off switch for all Bayes-related
1908operations.
1909
1910=cut
1911
191215µs push (@cmds, {
1913 setting => 'use_bayes',
1914 default => 1,
1915 type => $CONF_TYPE_BOOL,
1916 });
1917
1918=item use_bayes_rules ( 0 | 1 ) (default: 1)
1919
1920Whether to use rules using the naive-Bayesian-style classifier built
1921into SpamAssassin. This allows you to disable the rules while leaving
1922auto and manual learning enabled.
1923
1924=cut
1925
1926110µs push (@cmds, {
1927 setting => 'use_bayes_rules',
1928 default => 1,
1929 type => $CONF_TYPE_BOOL,
1930 });
1931
1932=item bayes_auto_learn ( 0 | 1 ) (default: 1)
1933
1934Whether SpamAssassin should automatically feed high-scoring mails (or
1935low-scoring mails, for non-spam) into its learning systems. The only
1936learning system supported currently is a naive-Bayesian-style classifier.
1937
1938See the documentation for the
1939C<Mail::SpamAssassin::Plugin::AutoLearnThreshold> plugin module
1940for details on how Bayes auto-learning is implemented by default.
1941
1942=cut
1943
194415µs push (@cmds, {
1945 setting => 'bayes_auto_learn',
1946 default => 1,
1947 type => $CONF_TYPE_BOOL,
1948 });
1949
1950=item bayes_token_sources (default: header visible invisible uri)
1951
1952Controls which sources in a mail message can contribute tokens (e.g. words,
1953phrases, etc.) to a Bayes classifier. The argument is a space-separated list
1954of keywords: I<header>, I<visible>, I<invisible>, I<uri>, I<mimepart>), each
1955of which may be prefixed by a I<no> to indicate its exclusion. Additionally
1956two reserved keywords are allowed: I<all> and I<none> (or: I<noall>). The list
1957of keywords is processed sequentially: a keyword I<all> adds all available
1958keywords to a set being built, a I<none> or I<noall> clears the set, other
1959non-negated keywords are added to the set, and negated keywords are removed
1960from the set. Keywords are case-insensitive.
1961
1962The default set is: I<header> I<visible> I<invisible> I<uri>, which is
1963equivalent for example to: I<All> I<NoMIMEpart>. The reason why I<mimepart>
1964is not currently in a default set is that it is a newer source (introduced
1965with SpamAssassin version 3.4.1) and not much experience has yet been gathered
1966regarding its usefulness.
1967
1968See also option C<bayes_ignore_header> for a fine-grained control on individual
1969header fields under the umbrella of a more general keyword I<header> here.
1970
1971Keywords imply the following data sources:
1972
1973=over 4
1974
1975=item I<header> - tokens collected from a message header section
1976
1977=item I<visible> - words from visible text (plain or HTML) in a message body
1978
1979=item I<invisible> - hidden/invisible text in HTML parts of a message body
1980
1981=item I<uri> - URIs collected from a message body
1982
1983=item I<mimepart> - digests (hashes) of all MIME parts (textual or non-textual) of a message, computed after Base64 and quoted-printable decoding, suffixed by their Content-Type
1984
1985=item I<all> - adds all the above keywords to the set being assembled
1986
1987=item I<none> or I<noall> - removes all keywords from the set
1988
1989=back
1990
1991The C<bayes_token_sources> directive may appear multiple times, its keywords
1992are interpreted sequentially, adding or removing items from the final set
1993as they appear in their order in C<bayes_token_sources> directive(s).
1994
1995=cut
1996
1997 push (@cmds, {
1998 setting => 'bayes_token_sources',
1999 default => { map(($_,1), qw(header visible invisible uri)) }, # mimepart
2000 type => $CONF_TYPE_HASH_KEY_VALUE,
2001 code => sub {
2002 my ($self, $key, $value, $line) = @_;
2003 return $MISSING_REQUIRED_VALUE if $value eq '';
2004 my $h = ($self->{bayes_token_sources} ||= {});
2005 my %all_kw = map(($_,1), qw(header visible invisible uri mimepart));
2006 foreach (split(' ', lc $value)) {
2007 if (/^(none|noall)\z/) {
2008 %$h = ();
2009 } elsif ($_ eq 'all') {
2010 %$h = %all_kw;
2011 } elsif (/^(no)?(.+)\z/s && exists $all_kw{$2}) {
2012 $h->{$2} = defined $1 ? 0 : 1;
2013 } else {
2014 return $INVALID_VALUE;
2015 }
2016 }
2017 }
2018124µs });
2019
2020=item bayes_ignore_header header_name
2021
2022If you receive mail filtered by upstream mail systems, like
2023a spam-filtering ISP or mailing list, and that service adds
2024new headers (as most of them do), these headers may provide
2025inappropriate cues to the Bayesian classifier, allowing it
2026to take a "short cut". To avoid this, list the headers using this
2027setting. Example:
2028
2029 bayes_ignore_header X-Upstream-Spamfilter
2030 bayes_ignore_header X-Upstream-SomethingElse
2031
2032=cut
2033
2034 push (@cmds, {
2035 setting => 'bayes_ignore_header',
2036 default => [],
2037 type => $CONF_TYPE_STRINGLIST,
2038
# spent 5.85ms within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2044] which was called 270 times, avg 22µs/call: # 270 times (5.85ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 22µs/call
code => sub {
20392701.36ms my ($self, $key, $value, $line) = @_;
2040270479µs if ($value eq '') {
2041 return $MISSING_REQUIRED_VALUE;
2042 }
20435405.36ms push (@{$self->{bayes_ignore_headers}}, split(/\s+/, $value));
2044 }
2045110µs });
2046
2047=item bayes_ignore_from user@example.com
2048
2049Bayesian classification and autolearning will not be performed on mail
2050from the listed addresses. Program C<sa-learn> will also ignore the
2051listed addresses if it is invoked using the C<--use-ignores> option.
2052One or more addresses can be listed, see C<whitelist_from>.
2053
2054Spam messages from certain senders may contain many words that
2055frequently occur in ham. For example, one might read messages from a
2056preferred bookstore but also get unwanted spam messages from other
2057bookstores. If the unwanted messages are learned as spam then any
2058messages discussing books, including the preferred bookstore and
2059antiquarian messages would be in danger of being marked as spam. The
2060addresses of the annoying bookstores would be listed. (Assuming they
2061were halfway legitimate and didn't send you mail through myriad
2062affiliates.)
2063
2064Those who have pieces of spam in legitimate messages or otherwise
2065receive ham messages containing potentially spammy words might fear
2066that some spam messages might be in danger of being marked as ham.
2067The addresses of the spam mailing lists, correspondents, etc. would
2068be listed.
2069
2070=cut
2071
207214µs push (@cmds, {
2073 setting => 'bayes_ignore_from',
2074 type => $CONF_TYPE_ADDRLIST,
2075 });
2076
2077=item bayes_ignore_to user@example.com
2078
2079Bayesian classification and autolearning will not be performed on mail
2080to the listed addresses. See C<bayes_ignore_from> for details.
2081
2082=cut
2083
208414µs push (@cmds, {
2085 setting => 'bayes_ignore_to',
2086 type => $CONF_TYPE_ADDRLIST,
2087 });
2088
2089=item bayes_min_ham_num (Default: 200)
2090
2091=item bayes_min_spam_num (Default: 200)
2092
2093To be accurate, the Bayes system does not activate until a certain number of
2094ham (non-spam) and spam have been learned. The default is 200 of each ham and
2095spam, but you can tune these up or down with these two settings.
2096
2097=cut
2098
209914µs push (@cmds, {
2100 setting => 'bayes_min_ham_num',
2101 default => 200,
2102 type => $CONF_TYPE_NUMERIC,
2103 });
210414µs push (@cmds, {
2105 setting => 'bayes_min_spam_num',
2106 default => 200,
2107 type => $CONF_TYPE_NUMERIC,
2108 });
2109
2110=item bayes_learn_during_report (Default: 1)
2111
2112The Bayes system will, by default, learn any reported messages
2113(C<spamassassin -r>) as spam. If you do not want this to happen, set
2114this option to 0.
2115
2116=cut
2117
211816µs push (@cmds, {
2119 setting => 'bayes_learn_during_report',
2120 default => 1,
2121 type => $CONF_TYPE_BOOL,
2122 });
2123
2124=item bayes_sql_override_username
2125
2126Used by BayesStore::SQL storage implementation.
2127
2128If this options is set the BayesStore::SQL module will override the set
2129username with the value given. This could be useful for implementing global or
2130group bayes databases.
2131
2132=cut
2133
213415µs push (@cmds, {
2135 setting => 'bayes_sql_override_username',
2136 default => '',
2137 type => $CONF_TYPE_STRING,
2138 });
2139
2140=item bayes_use_hapaxes (default: 1)
2141
2142Should the Bayesian classifier use hapaxes (words/tokens that occur only
2143once) when classifying? This produces significantly better hit-rates.
2144
2145=cut
2146
214715µs push (@cmds, {
2148 setting => 'bayes_use_hapaxes',
2149 default => 1,
2150 type => $CONF_TYPE_BOOL,
2151 });
2152
2153=item bayes_journal_max_size (default: 102400)
2154
2155SpamAssassin will opportunistically sync the journal and the database.
2156It will do so once a day, but will sync more often if the journal file
2157size goes above this setting, in bytes. If set to 0, opportunistic
2158syncing will not occur.
2159
2160=cut
2161
216214µs push (@cmds, {
2163 setting => 'bayes_journal_max_size',
2164 default => 102400,
2165 type => $CONF_TYPE_NUMERIC,
2166 });
2167
2168=item bayes_expiry_max_db_size (default: 150000)
2169
2170What should be the maximum size of the Bayes tokens database? When expiry
2171occurs, the Bayes system will keep either 75% of the maximum value, or
2172100,000 tokens, whichever has a larger value. 150,000 tokens is roughly
2173equivalent to a 8Mb database file.
2174
2175=cut
2176
217714µs push (@cmds, {
2178 setting => 'bayes_expiry_max_db_size',
2179 default => 150000,
2180 type => $CONF_TYPE_NUMERIC,
2181 });
2182
2183=item bayes_auto_expire (default: 1)
2184
2185If enabled, the Bayes system will try to automatically expire old tokens
2186from the database. Auto-expiry occurs when the number of tokens in the
2187database surpasses the bayes_expiry_max_db_size value. If a bayes datastore
2188backend does not implement individual key/value expirations, the setting
2189is silently ignored.
2190
2191=cut
2192
219314µs push (@cmds, {
2194 setting => 'bayes_auto_expire',
2195 default => 1,
2196 type => $CONF_TYPE_BOOL,
2197 });
2198
2199=item bayes_token_ttl (default: 3w, i.e. 3 weeks)
2200
2201Time-to-live / expiration time in seconds for tokens kept in a Bayes database.
2202A numeric value is optionally suffixed by a time unit (s, m, h, d, w,
2203indicating seconds (default), minutes, hours, days, weeks).
2204
2205If bayes_auto_expire is true and a Bayes datastore backend supports it
2206(currently only Redis), this setting controls deletion of expired tokens
2207from a bayes database. The value is observed on a best-effort basis, exact
2208timing promises are not necessarily kept. If a bayes datastore backend
2209does not implement individual key/value expirations, the setting is silently
2210ignored.
2211
2212=cut
2213
221414µs push (@cmds, {
2215 setting => 'bayes_token_ttl',
2216 default => 3*7*24*60*60, # seconds (3 weeks)
2217 type => $CONF_TYPE_DURATION,
2218 });
2219
2220=item bayes_seen_ttl (default: 8d, i.e. 8 days)
2221
2222Time-to-live / expiration time in seconds for 'seen' entries
2223(i.e. mail message digests with their status) kept in a Bayes database.
2224A numeric value is optionally suffixed by a time unit (s, m, h, d, w,
2225indicating seconds (default), minutes, hours, days, weeks).
2226
2227If bayes_auto_expire is true and a Bayes datastore backend supports it
2228(currently only Redis), this setting controls deletion of expired 'seen'
2229entries from a bayes database. The value is observed on a best-effort basis,
2230exact timing promises are not necessarily kept. If a bayes datastore backend
2231does not implement individual key/value expirations, the setting is silently
2232ignored.
2233
2234=cut
2235
223614µs push (@cmds, {
2237 setting => 'bayes_seen_ttl',
2238 default => 8*24*60*60, # seconds (8 days)
2239 type => $CONF_TYPE_DURATION,
2240 });
2241
2242=item bayes_learn_to_journal (default: 0)
2243
2244If this option is set, whenever SpamAssassin does Bayes learning, it
2245will put the information into the journal instead of directly into the
2246database. This lowers contention for locking the database to execute
2247an update, but will also cause more access to the journal and cause a
2248delay before the updates are actually committed to the Bayes database.
2249
2250=cut
2251
2252111µs push (@cmds, {
2253 setting => 'bayes_learn_to_journal',
2254 default => 0,
2255 type => $CONF_TYPE_BOOL,
2256 });
2257
2258=back
2259
2260=head2 MISCELLANEOUS OPTIONS
2261
2262=over 4
2263
2264=item time_limit n (default: 300)
2265
2266Specifies a limit on elapsed time in seconds that SpamAssassin is allowed
2267to spend before providing a result. The value may be fractional and must
2268not be negative, zero is interpreted as unlimited. The default is 300
2269seconds for consistency with the spamd default setting of --timeout-child .
2270
2271This is a best-effort advisory setting, processing will not be abruptly
2272aborted at an arbitrary point in processing when the time limit is exceeded,
2273but only on reaching one of locations in the program flow equipped with a
2274time test. Currently equipped with the test are the main checking loop,
2275asynchronous DNS lookups, plugins which are calling external programs.
2276Rule evaluation is guarded by starting a timer (alarm) on each set of
2277compiled rules.
2278
2279When a message is passed to Mail::SpamAssassin::parse, a deadline time
2280is established as a sum of current time and the C<time_limit> setting.
2281
2282This deadline may also be specified by a caller through an option
2283'master_deadline' in $suppl_attrib on a call to parse(), possibly providing
2284a more accurate deadline taking into account past and expected future
2285processing of a message in a mail filtering setup. If both the config
2286option as well as a 'master_deadline' option in a call are provided,
2287the shorter time limit of the two is used (since version 3.3.2).
2288Note that spamd (and possibly third-party callers of SpamAssassin) will
2289supply the 'master_deadline' option in a call based on its --timeout-child
2290option (or equivalent), unlike the command line C<spamassassin>, which has
2291no such command line option.
2292
2293When a time limit is exceeded, most of the remaining tests will be skipped,
2294as well as auto-learning. Whatever tests fired so far will determine the
2295final score. The behaviour is similar to short-circuiting with attribute 'on',
2296as implemented by a Shortcircuit plugin. A synthetic hit on a rule named
2297TIME_LIMIT_EXCEEDED with a near-zero default score is generated, so that
2298the report will reflect the event. A score for TIME_LIMIT_EXCEEDED may
2299be provided explicitly in a configuration file, for example to achieve
2300whitelisting or blacklisting effect for messages with long processing times.
2301
2302The C<time_limit> option is a useful protection against excessive processing
2303time on certain degenerate or unusually long or complex mail messages, as well
2304as against some DoS attacks. It is also needed in time-critical pre-queue
2305filtering setups (e.g. milter, proxy, integration with MTA), where message
2306processing must finish before a SMTP client times out. RFC 5321 prescribes
2307in section 4.5.3.2.6 the 'DATA Termination' time limit of 10 minutes,
2308although it is not unusual to see some SMTP clients abort sooner on waiting
2309for a response. A sensible C<time_limit> for a pre-queue filtering setup is
2310maybe 50 seconds, assuming that clients are willing to wait at least a minute.
2311
2312=cut
2313
231414µs push (@cmds, {
2315 setting => 'time_limit',
2316 default => 300,
2317 type => $CONF_TYPE_DURATION,
2318 });
2319
2320=item lock_method type
2321
2322Select the file-locking method used to protect database files on-disk. By
2323default, SpamAssassin uses an NFS-safe locking method on UNIX; however, if you
2324are sure that the database files you'll be using for Bayes and AWL storage will
2325never be accessed over NFS, a non-NFS-safe locking system can be selected.
2326
2327This will be quite a bit faster, but may risk file corruption if the files are
2328ever accessed by multiple clients at once, and one or more of them is accessing
2329them through an NFS filesystem.
2330
2331Note that different platforms require different locking systems.
2332
2333The supported locking systems for C<type> are as follows:
2334
2335=over 4
2336
2337=item I<nfssafe> - an NFS-safe locking system
2338
2339=item I<flock> - simple UNIX C<flock()> locking
2340
2341=item I<win32> - Win32 locking using C<sysopen (..., O_CREAT|O_EXCL)>.
2342
2343=back
2344
2345nfssafe and flock are only available on UNIX, and win32 is only available
2346on Windows. By default, SpamAssassin will choose either nfssafe or
2347win32 depending on the platform in use.
2348
2349=cut
2350
2351 push (@cmds, {
2352 setting => 'lock_method',
2353 default => '',
2354 type => $CONF_TYPE_STRING,
2355 code => sub {
2356 my ($self, $key, $value, $line) = @_;
2357 if ($value !~ /^(nfssafe|flock|win32)$/) {
2358 return $INVALID_VALUE;
2359 }
2360
2361 $self->{lock_method} = $value;
2362 # recreate the locker
2363 $self->{main}->create_locker();
2364 }
2365110µs });
2366
2367=item fold_headers ( 0 | 1 ) (default: 1)
2368
2369By default, headers added by SpamAssassin will be whitespace folded.
2370In other words, they will be broken up into multiple lines instead of
2371one very long one and each continuation line will have a tabulator
2372prepended to mark it as a continuation of the preceding one.
2373
2374The automatic wrapping can be disabled here. Note that this can generate very
2375long lines. RFC 2822 required that header lines do not exceed 998 characters
2376(not counting the final CRLF).
2377
2378=cut
2379
238014µs push (@cmds, {
2381 setting => 'fold_headers',
2382 default => 1,
2383 type => $CONF_TYPE_BOOL,
2384 });
2385
2386=item report_safe_copy_headers header_name ...
2387
2388If using C<report_safe>, a few of the headers from the original message
2389are copied into the wrapper header (From, To, Cc, Subject, Date, etc.)
2390If you want to have other headers copied as well, you can add them
2391using this option. You can specify multiple headers on the same line,
2392separated by spaces, or you can just use multiple lines.
2393
2394=cut
2395
2396 push (@cmds, {
2397 setting => 'report_safe_copy_headers',
2398 default => [],
2399 type => $CONF_TYPE_STRINGLIST,
2400 code => sub {
2401 my ($self, $key, $value, $line) = @_;
2402 if ($value eq '') {
2403 return $MISSING_REQUIRED_VALUE;
2404 }
2405 push(@{$self->{report_safe_copy_headers}}, split(/\s+/, $value));
2406 }
2407116µs });
2408
2409=item envelope_sender_header Name-Of-Header
2410
2411SpamAssassin will attempt to discover the address used in the 'MAIL FROM:'
2412phase of the SMTP transaction that delivered this message, if this data has
2413been made available by the SMTP server. This is used in the C<EnvelopeFrom>
2414pseudo-header, and for various rules such as SPF checking.
2415
2416By default, various MTAs will use different headers, such as the following:
2417
2418 X-Envelope-From
2419 Envelope-Sender
2420 X-Sender
2421 Return-Path
2422
2423SpamAssassin will attempt to use these, if some heuristics (such as the header
2424placement in the message, or the absence of fetchmail signatures) appear to
2425indicate that they are safe to use. However, it may choose the wrong headers
2426in some mailserver configurations. (More discussion of this can be found
2427in bug 2142 and bug 4747 in the SpamAssassin BugZilla.)
2428
2429To avoid this heuristic failure, the C<envelope_sender_header> setting may be
2430helpful. Name the header that your MTA or MDA adds to messages containing the
2431address used at the MAIL FROM step of the SMTP transaction.
2432
2433If the header in question contains C<E<lt>> or C<E<gt>> characters at the start
2434and end of the email address in the right-hand side, as in the SMTP
2435transaction, these will be stripped.
2436
2437If the header is not found in a message, or if it's value does not contain an
2438C<@> sign, SpamAssassin will issue a warning in the logs and fall back to its
2439default heuristics.
2440
2441(Note for MTA developers: we would prefer if the use of a single header be
2442avoided in future, since that precludes 'downstream' spam scanning.
2443C<http://wiki.apache.org/spamassassin/EnvelopeSenderInReceived> details a
2444better proposal, storing the envelope sender at each hop in the C<Received>
2445header.)
2446
2447example:
2448
2449 envelope_sender_header X-SA-Exim-Mail-From
2450
2451=cut
2452
245315µs push (@cmds, {
2454 setting => 'envelope_sender_header',
2455 default => undef,
2456 type => $CONF_TYPE_STRING,
2457 });
2458
2459=item describe SYMBOLIC_TEST_NAME description ...
2460
2461Used to describe a test. This text is shown to users in the detailed report.
2462
2463Note that test names which begin with '__' are reserved for meta-match
2464sub-rules, and are not scored or listed in the 'tests hit' reports.
2465
2466Also note that by convention, rule descriptions should be limited in
2467length to no more than 50 characters.
2468
2469=cut
2470
2471111µs push (@cmds, {
2472 command => 'describe',
2473 setting => 'descriptions',
2474 is_frequent => 1,
2475 type => $CONF_TYPE_HASH_KEY_VALUE,
2476 });
2477
2478=item report_charset CHARSET (default: unset)
2479
2480Set the MIME Content-Type charset used for the text/plain report which
2481is attached to spam mail messages.
2482
2483=cut
2484
248515µs push (@cmds, {
2486 setting => 'report_charset',
2487 default => '',
2488 type => $CONF_TYPE_STRING,
2489 });
2490
2491=item report ...some text for a report...
2492
2493Set the report template which is attached to spam mail messages. See the
2494C<10_default_prefs.cf> configuration file in C</usr/share/spamassassin> for an
2495example.
2496
2497If you change this, try to keep it under 78 columns. Each C<report>
2498line appends to the existing template, so use C<clear_report_template>
2499to restart.
2500
2501Tags can be included as explained above.
2502
2503=cut
2504
250516µs push (@cmds, {
2506 command => 'report',
2507 setting => 'report_template',
2508 default => '',
2509 type => $CONF_TYPE_TEMPLATE,
2510 });
2511
2512=item clear_report_template
2513
2514Clear the report template.
2515
2516=cut
2517
251817µs push (@cmds, {
2519 command => 'clear_report_template',
2520 setting => 'report_template',
2521 type => $CONF_TYPE_NOARGS,
2522 code => \&Mail::SpamAssassin::Conf::Parser::set_template_clear
2523 });
2524
2525=item report_contact ...text of contact address...
2526
2527Set what _CONTACTADDRESS_ is replaced with in the above report text.
2528By default, this is 'the administrator of that system', since the hostname
2529of the system the scanner is running on is also included.
2530
2531=cut
2532
253315µs push (@cmds, {
2534 setting => 'report_contact',
2535 default => 'the administrator of that system',
2536 type => $CONF_TYPE_STRING,
2537 });
2538
2539=item report_hostname ...hostname to use...
2540
2541Set what _HOSTNAME_ is replaced with in the above report text.
2542By default, this is determined dynamically as whatever the host running
2543SpamAssassin calls itself.
2544
2545=cut
2546
254715µs push (@cmds, {
2548 setting => 'report_hostname',
2549 default => '',
2550 type => $CONF_TYPE_STRING,
2551 });
2552
2553=item unsafe_report ...some text for a report...
2554
2555Set the report template which is attached to spam mail messages which contain a
2556non-text/plain part. See the C<10_default_prefs.cf> configuration file in
2557C</usr/share/spamassassin> for an example.
2558
2559Each C<unsafe-report> line appends to the existing template, so use
2560C<clear_unsafe_report_template> to restart.
2561
2562Tags can be used in this template (see above for details).
2563
2564=cut
2565
256616µs push (@cmds, {
2567 command => 'unsafe_report',
2568 setting => 'unsafe_report_template',
2569 default => '',
2570 type => $CONF_TYPE_TEMPLATE,
2571 });
2572
2573=item clear_unsafe_report_template
2574
2575Clear the unsafe_report template.
2576
2577=cut
2578
257916µs push (@cmds, {
2580 command => 'clear_unsafe_report_template',
2581 setting => 'unsafe_report_template',
2582 type => $CONF_TYPE_NOARGS,
2583 code => \&Mail::SpamAssassin::Conf::Parser::set_template_clear
2584 });
2585
2586=item mbox_format_from_regex
2587
2588Set a specific regular expression to be used for mbox file From separators.
2589
2590For example, this setting will allow sa-learn to process emails stored in
2591a kmail 2 mbox:
2592
2593mbox_format_from_regex /^From \S+ ?[[:upper:]][[:lower:]]{2}(?:, \d\d [[:upper:]][[:lower:]]{2} \d{4} [0-2]\d:\d\d:\d\d [+-]\d{4}| [[:upper:]][[:lower:]]{2} [ 1-3]\d [ 0-2]\d:\d\d:\d\d \d{4})/
2594
2595
2596=cut
2597
259814µs push (@cmds, {
2599 setting => 'mbox_format_from_regex',
2600 type => $CONF_TYPE_STRING
2601 });
2602
2603
2604=item parse_dkim_uris ( 0 | 1 ) (default: 0)
2605
2606If this option is set to 1 and the message contains DKIM headers, the headers will be parsed for URIs to process alongside URIs found in the body with some rules and moduels (ex. URIDNSBL)
2607
2608=cut
2609
261015µs push (@cmds, {
2611 setting => 'parse_dkim_uris',
2612 default => 0,
2613 type => $CONF_TYPE_BOOL,
2614 });
2615
2616=back
2617
2618=head1 RULE DEFINITIONS AND PRIVILEGED SETTINGS
2619
2620These settings differ from the ones above, in that they are considered
2621'privileged'. Only users running C<spamassassin> from their procmailrc's or
2622forward files, or sysadmins editing a file in C</etc/mail/spamassassin>, can
2623use them. C<spamd> users cannot use them in their C<user_prefs> files, for
2624security and efficiency reasons, unless C<allow_user_rules> is enabled (and
2625then, they may only add rules from below).
2626
2627=over 4
2628
2629=item allow_user_rules ( 0 | 1 ) (default: 0)
2630
2631This setting allows users to create rules (and only rules) in their
2632C<user_prefs> files for use with C<spamd>. It defaults to off, because
2633this could be a severe security hole. It may be possible for users to
2634gain root level access if C<spamd> is run as root. It is NOT a good
2635idea, unless you have some other way of ensuring that users' tests are
2636safe. Don't use this unless you are certain you know what you are
2637doing. Furthermore, this option causes spamassassin to recompile all
2638the tests each time it processes a message for a user with a rule in
2639his/her C<user_prefs> file, which could have a significant effect on
2640server load. It is not recommended.
2641
2642Note that it is not currently possible to use C<allow_user_rules> to modify an
2643existing system rule from a C<user_prefs> file with C<spamd>.
2644
2645=cut
2646
2647 push (@cmds, {
2648 setting => 'allow_user_rules',
2649 is_priv => 1,
2650 default => 0,
2651 type => $CONF_TYPE_BOOL,
2652 code => sub {
2653 my ($self, $key, $value, $line) = @_;
2654 if ($value eq '') {
2655 return $MISSING_REQUIRED_VALUE;
2656 }
2657 elsif ($value !~ /^[01]$/) {
2658 return $INVALID_VALUE;
2659 }
2660
2661 $self->{allow_user_rules} = $value+0;
2662 dbg("config: " . ($self->{allow_user_rules} ? "allowing":"not allowing") . " user rules!");
2663 }
2664112µs });
2665
2666=item redirector_pattern /pattern/modifiers
2667
2668A regex pattern that matches both the redirector site portion, and
2669the target site portion of a URI.
2670
2671Note: The target URI portion must be surrounded in parentheses and
2672 no other part of the pattern may create a backreference.
2673
2674Example: http://chkpt.zdnet.com/chkpt/whatever/spammer.domain/yo/dude
2675
2676 redirector_pattern /^https?:\/\/(?:opt\.)?chkpt\.zdnet\.com\/chkpt\/\w+\/(.*)$/i
2677
2678=cut
2679
2680 push (@cmds, {
2681 setting => 'redirector_pattern',
2682 is_priv => 1,
2683
# spent 5.28ms (1.13+4.14) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] which was called 15 times, avg 352µs/call: # 15 times (1.13ms+4.14ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 352µs/call
code => sub {
26841582µs my ($self, $key, $value, $line) = @_;
268515122µs153.36ms if ($value eq '') {
# spent 3.36ms making 15 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 224µs/call
2686 return $MISSING_REQUIRED_VALUE;
2687 }
2688 elsif (!$self->{parser}->is_delimited_regexp_valid("redirector_pattern", $value)) {
2689 return $INVALID_VALUE;
2690 }
2691
2692 # convert to qr// while including modifiers
26931565µs local ($1,$2,$3);
269415223µs1595µs $value =~ /^m?(\W)(.*)(?:\1|>|}|\)|\])(.*?)$/;
# spent 95µs making 15 calls to Mail::SpamAssassin::Conf::CORE:match, avg 6µs/call
26951559µs my $pattern = $2;
26961579µs $pattern = "(?".$3.")".$pattern if $3;
269715952µs30687µs $pattern = qr/$pattern/;
# spent 584µs making 15 calls to Mail::SpamAssassin::Conf::CORE:regcomp, avg 39µs/call # spent 103µs making 15 calls to Mail::SpamAssassin::Conf::CORE:qr, avg 7µs/call
2698
269930317µs push @{$self->{main}->{conf}->{redirector_patterns}}, $pattern;
2700 # dbg("config: adding redirector regex: " . $value);
2701 }
2702116µs });
2703
2704=item header SYMBOLIC_TEST_NAME header op /pattern/modifiers [if-unset: STRING]
2705
2706Define a test. C<SYMBOLIC_TEST_NAME> is a symbolic test name, such as
2707'FROM_ENDS_IN_NUMS'. C<header> is the name of a mail header field,
2708such as 'Subject', 'To', 'From', etc. Header field names are matched
2709case-insensitively (conforming to RFC 5322 section 1.2.2), except for
2710all-capitals metaheader fields such as ALL, MESSAGEID, ALL-TRUSTED.
2711
2712Appending a modifier C<:raw> to a header field name will inhibit decoding of
2713quoted-printable or base-64 encoded strings, and will preserve all whitespace
2714inside the header string. The C<:raw> may also be applied to pseudo-headers
2715e.g. C<ALL:raw> will return a pristine (unmodified) header section.
2716
2717Appending a modifier C<:addr> to a header field name will cause everything
2718except the first email address to be removed from the header field. It is
2719mainly applicable to header fields 'From', 'Sender', 'To', 'Cc' along with
2720their 'Resent-*' counterparts, and the 'Return-Path'.
2721
2722Appending a modifier C<:name> to a header field name will cause everything
2723except the first display name to be removed from the header field. It is
2724mainly applicable to header fields containing a single mail address: 'From',
2725'Sender', along with their 'Resent-From' and 'Resent-Sender' counterparts.
2726
2727It is syntactically permitted to append more than one modifier to a header
2728field name, although currently most combinations achieve no additional effect,
2729for example C<From:addr:raw> or C<From:raw:addr> is currently the same as
2730C<From:addr> .
2731
2732For example, appending C<:addr> to a header name will result in example@foo
2733in all of the following cases:
2734
2735=over 4
2736
2737=item example@foo
2738
2739=item example@foo (Foo Blah)
2740
2741=item example@foo, example@bar
2742
2743=item display: example@foo (Foo Blah), example@bar ;
2744
2745=item Foo Blah <example@foo>
2746
2747=item "Foo Blah" <example@foo>
2748
2749=item "'Foo Blah'" <example@foo>
2750
2751=back
2752
2753For example, appending C<:name> to a header name will result in "Foo Blah"
2754(without quotes) in all of the following cases:
2755
2756=over 4
2757
2758=item example@foo (Foo Blah)
2759
2760=item example@foo (Foo Blah), example@bar
2761
2762=item display: example@foo (Foo Blah), example@bar ;
2763
2764=item Foo Blah <example@foo>
2765
2766=item "Foo Blah" <example@foo>
2767
2768=item "'Foo Blah'" <example@foo>
2769
2770=back
2771
2772There are several special pseudo-headers that can be specified:
2773
2774=over 4
2775
2776=item C<ALL> can be used to mean the text of all the message's headers.
2777Note that all whitespace inside the headers, at line folds, is currently
2778compressed into a single space (' ') character. To obtain a pristine
2779(unmodified) header section, use C<ALL:raw> - the :raw modifier is documented
2780above.
2781
2782=item C<ToCc> can be used to mean the contents of both the 'To' and 'Cc'
2783headers.
2784
2785=item C<EnvelopeFrom> is the address used in the 'MAIL FROM:' phase of the SMTP
2786transaction that delivered this message, if this data has been made available
2787by the SMTP server. See C<envelope_sender_header> for more information
2788on how to set this.
2789
2790=item C<MESSAGEID> is a symbol meaning all Message-Id's found in the message;
2791some mailing list software moves the real 'Message-Id' to 'Resent-Message-Id'
2792or to 'X-Message-Id', then uses its own one in the 'Message-Id' header.
2793The value returned for this symbol is the text from all 3 headers, separated
2794by newlines.
2795
2796=item C<X-Spam-Relays-Untrusted>, C<X-Spam-Relays-Trusted>,
2797C<X-Spam-Relays-Internal> and C<X-Spam-Relays-External> represent a portable,
2798pre-parsed representation of the message's network path, as recorded in the
2799Received headers, divided into 'trusted' vs 'untrusted' and 'internal' vs
2800'external' sets. See C<http://wiki.apache.org/spamassassin/TrustedRelays> for
2801more details.
2802
2803=back
2804
2805C<op> is either C<=~> (contains regular expression) or C<!~> (does not contain
2806regular expression), and C<pattern> is a valid Perl regular expression, with
2807C<modifiers> as regexp modifiers in the usual style. Note that multi-line
2808rules are not supported, even if you use C<x> as a modifier. Also note that
2809the C<#> character must be escaped (C<\#>) or else it will be considered to be
2810the start of a comment and not part of the regexp.
2811
2812If the C<[if-unset: STRING]> tag is present, then C<STRING> will
2813be used if the header is not found in the mail message.
2814
2815Test names must not start with a number, and must contain only
2816alphanumerics and underscores. It is suggested that lower-case characters
2817not be used, and names have a length of no more than 22 characters,
2818as an informal convention. Dashes are not allowed.
2819
2820Note that test names which begin with '__' are reserved for meta-match
2821sub-rules, and are not scored or listed in the 'tests hit' reports.
2822Test names which begin with 'T_' are reserved for tests which are
2823undergoing QA, and these are given a very low score.
2824
2825If you add or modify a test, please be sure to run a sanity check afterwards
2826by running C<spamassassin --lint>. This will avoid confusing error
2827messages, or other tests being skipped as a side-effect.
2828
2829=item header SYMBOLIC_TEST_NAME exists:header_field_name
2830
2831Define a header field existence test. C<header_field_name> is the name
2832of a header field to test for existence. Not to be confused with a
2833test for a nonempty header field body, which can be implemented by a
2834C<header SYMBOLIC_TEST_NAME header =~ /\S/> rule as described above.
2835
2836=item header SYMBOLIC_TEST_NAME eval:name_of_eval_method([arguments])
2837
2838Define a header eval test. C<name_of_eval_method> is the name of
2839a method on the C<Mail::SpamAssassin::EvalTests> object. C<arguments>
2840are optional arguments to the function call.
2841
2842=item header SYMBOLIC_TEST_NAME eval:check_rbl('set', 'zone' [, 'sub-test'])
2843
2844Check a DNSBL (a DNS blacklist or whitelist). This will retrieve Received:
2845headers from the message, extract the IP addresses, select which ones are
2846'untrusted' based on the C<trusted_networks> logic, and query that DNSBL
2847zone. There's a few things to note:
2848
2849=over 4
2850
2851=item duplicated or private IPs
2852
2853Duplicated IPs are only queried once and reserved IPs are not queried.
2854Private IPs are those listed in
2855<http://www.iana.org/assignments/ipv4-address-space>,
2856<http://duxcw.com/faq/network/privip.htm>,
2857<http://duxcw.com/faq/network/autoip.htm>, or
2858<http://tools.ietf.org/html/rfc5735> as private.
2859
2860=item the 'set' argument
2861
2862This is used as a 'zone ID'. If you want to look up a multiple-meaning zone
2863like SORBS, you can then query the results from that zone using it;
2864but all check_rbl_sub() calls must use that zone ID.
2865
2866Also, if more than one IP address gets a DNSBL hit for a particular rule, it
2867does not affect the score because rules only trigger once per message.
2868
2869=item the 'zone' argument
2870
2871This is the root zone of the DNSBL.
2872
2873The domain name is considered to be a fully qualified domain name
2874(i.e. not subject to DNS resolver's search or default domain options).
2875No trailing period is needed, and will be removed if specified.
2876
2877=item the 'sub-test' argument
2878
2879This optional argument behaves the same as the sub-test argument in
2880C<check_rbl_sub()> below.
2881
2882=item selecting all IPs except for the originating one
2883
2884This is accomplished by placing '-notfirsthop' at the end of the set name.
2885This is useful for querying against DNS lists which list dialup IP
2886addresses; the first hop may be a dialup, but as long as there is at least
2887one more hop, via their outgoing SMTP server, that's legitimate, and so
2888should not gain points. If there is only one hop, that will be queried
2889anyway, as it should be relaying via its outgoing SMTP server instead of
2890sending directly to your MX (mail exchange).
2891
2892=item selecting IPs by whether they are trusted
2893
2894When checking a 'nice' DNSBL (a DNS whitelist), you cannot trust the IP
2895addresses in Received headers that were not added by trusted relays. To
2896test the first IP address that can be trusted, place '-firsttrusted' at the
2897end of the set name. That should test the IP address of the relay that
2898connected to the most remote trusted relay.
2899
2900Note that this requires that SpamAssassin know which relays are trusted. For
2901simple cases, SpamAssassin can make a good estimate. For complex cases, you
2902may get better results by setting C<trusted_networks> manually.
2903
2904In addition, you can test all untrusted IP addresses by placing '-untrusted'
2905at the end of the set name. Important note -- this does NOT include the
2906IP address from the most recent 'untrusted line', as used in '-firsttrusted'
2907above. That's because we're talking about the trustworthiness of the
2908IP address data, not the source header line, here; and in the case of
2909the most recent header (the 'firsttrusted'), that data can be trusted.
2910See the Wiki page at C<http://wiki.apache.org/spamassassin/TrustedRelays>
2911for more information on this.
2912
2913=item Selecting just the last external IP
2914
2915By using '-lastexternal' at the end of the set name, you can select only
2916the external host that connected to your internal network, or at least
2917the last external host with a public IP.
2918
2919=back
2920
2921=item header SYMBOLIC_TEST_NAME eval:check_rbl_txt('set', 'zone')
2922
2923Same as check_rbl(), except querying using IN TXT instead of IN A records.
2924If the zone supports it, it will result in a line of text describing
2925why the IP is listed, typically a hyperlink to a database entry.
2926
2927=item header SYMBOLIC_TEST_NAME eval:check_rbl_sub('set', 'sub-test')
2928
2929Create a sub-test for 'set'. If you want to look up a multi-meaning zone
2930like relays.osirusoft.com, you can then query the results from that zone
2931using the zone ID from the original query. The sub-test may either be an
2932IPv4 dotted address for RBLs that return multiple A records or a
2933non-negative decimal number to specify a bitmask for RBLs that return a
2934single A record containing a bitmask of results, a SenderBase test
2935beginning with "sb:", or (if none of the preceding options seem to fit) a
2936regular expression.
2937
2938Note: the set name must be exactly the same for as the main query rule,
2939including selections like '-notfirsthop' appearing at the end of the set
2940name.
2941
2942=cut
2943
2944 push (@cmds, {
2945 setting => 'header',
2946 is_frequent => 1,
2947 is_priv => 1,
2948
# spent 324ms (58.6+266) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] which was called 781 times, avg 415µs/call: # 781 times (58.6ms+266ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 415µs/call
code => sub {
29497815.29ms my ($self, $key, $value, $line) = @_;
29507813.24ms local ($1,$2);
295178144.1ms13874.82ms if ($value =~ /^(\S+)\s+(?:rbl)?eval:(.*)$/) {
# spent 4.82ms making 1387 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
2952175834µs my ($rulename, $fn) = ($1, $2);
2953
29541752.58ms175637µs if ($fn =~ /^check_(?:rbl|dns)/) {
# spent 637µs making 175 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
295573578µs736.04ms $self->{parser}->add_test ($rulename, $fn, $TYPE_RBL_EVALS);
# spent 6.04ms making 73 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 83µs/call
2956 }
2957 else {
2958102792µs1027.59ms $self->{parser}->add_test ($rulename, $fn, $TYPE_HEAD_EVALS);
# spent 7.59ms making 102 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 74µs/call
2959 }
2960 }
2961 elsif ($value =~ /^(\S+)\s+exists:(.*)$/) {
296258271µs my ($rulename, $header_name) = ($1, $2);
2963 # RFC 5322 section 3.6.8, ftext printable US-ASCII ch not including ":"
2964581.27ms116513µs if ($header_name !~ /\S/) {
# spent 513µs making 116 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
2965 return $MISSING_REQUIRED_VALUE;
2966 # } elsif ($header_name !~ /^([!-9;-\176]+)$/) {
2967 } elsif ($header_name !~ /^([^: \t]+)$/) { # be generous
2968 return $INVALID_HEADER_FIELD_NAME;
2969 }
297058728µs585.29ms $self->{parser}->add_test ($rulename, "defined($header_name)",
# spent 5.29ms making 58 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 91µs/call
2971 $TYPE_HEAD_TESTS);
2972581.46ms11612.1ms $self->{descriptions}->{$rulename} = "Found a $header_name header";
# spent 6.73ms making 58 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 116µs/call # spent 5.42ms making 58 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 93µs/call
2973 }
2974 else {
29755484.03ms my @values = split(/\s+/, $value, 2);
29765481.19ms if (@values != 2) {
2977 return $MISSING_REQUIRED_VALUE;
2978 }
29795484.89ms548229ms $self->{parser}->add_test (@values, $TYPE_HEAD_TESTS);
# spent 229ms making 548 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 417µs/call
2980 }
2981 }
2982120µs });
2983
2984=item body SYMBOLIC_TEST_NAME /pattern/modifiers
2985
2986Define a body pattern test. C<pattern> is a Perl regular expression. Note:
2987as per the header tests, C<#> must be escaped (C<\#>) or else it is considered
2988the beginning of a comment.
2989
2990The 'body' in this case is the textual parts of the message body;
2991any non-text MIME parts are stripped, and the message decoded from
2992Quoted-Printable or Base-64-encoded format if necessary. The message
2993Subject header is considered part of the body and becomes the first
2994paragraph when running the rules. All HTML tags and line breaks will
2995be removed before matching.
2996
2997=item body SYMBOLIC_TEST_NAME eval:name_of_eval_method([args])
2998
2999Define a body eval test. See above.
3000
3001=cut
3002
3003 push (@cmds, {
3004 setting => 'body',
3005 is_frequent => 1,
3006 is_priv => 1,
3007
# spent 233ms (30.6+202) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] which was called 655 times, avg 356µs/call: # 655 times (30.6ms+202ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 356µs/call
code => sub {
30086553.64ms my ($self, $key, $value, $line) = @_;
30096552.47ms local ($1,$2);
301065516.2ms6552.78ms if ($value =~ /^(\S+)\s+eval:(.*)$/) {
# spent 2.78ms making 655 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
30111421.07ms14219.5ms $self->{parser}->add_test ($1, $2, $TYPE_BODY_EVALS);
# spent 19.5ms making 142 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 137µs/call
3012 }
3013 else {
30145133.37ms my @values = split(/\s+/, $value, 2);
30155131.04ms if (@values != 2) {
3016 return $MISSING_REQUIRED_VALUE;
3017 }
30185134.40ms513180ms $self->{parser}->add_test (@values, $TYPE_BODY_TESTS);
# spent 180ms making 513 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 351µs/call
3019 }
3020 }
3021111µs });
3022
3023=item uri SYMBOLIC_TEST_NAME /pattern/modifiers
3024
3025Define a uri pattern test. C<pattern> is a Perl regular expression. Note: as
3026per the header tests, C<#> must be escaped (C<\#>) or else it is considered
3027the beginning of a comment.
3028
3029The 'uri' in this case is a list of all the URIs in the body of the email,
3030and the test will be run on each and every one of those URIs, adjusting the
3031score if a match is found. Use this test instead of one of the body tests
3032when you need to match a URI, as it is more accurately bound to the start/end
3033points of the URI, and will also be faster.
3034
3035=cut
3036
3037# we don't do URI evals yet - maybe later
3038# if (/^uri\s+(\S+)\s+eval:(.*)$/) {
3039# $self->{parser}->add_test ($1, $2, $TYPE_URI_EVALS);
3040# next;
3041# }
3042 push (@cmds, {
3043 setting => 'uri',
3044 is_priv => 1,
3045
# spent 24.1ms (2.43+21.7) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3052] which was called 71 times, avg 340µs/call: # 71 times (2.43ms+21.7ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 340µs/call
code => sub {
304671396µs my ($self, $key, $value, $line) = @_;
304771451µs my @values = split(/\s+/, $value, 2);
304871156µs if (@values != 2) {
3049 return $MISSING_REQUIRED_VALUE;
3050 }
3051711.15ms7121.7ms $self->{parser}->add_test (@values, $TYPE_URI_TESTS);
# spent 21.7ms making 71 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 306µs/call
3052 }
3053111µs });
3054
3055=item rawbody SYMBOLIC_TEST_NAME /pattern/modifiers
3056
3057Define a raw-body pattern test. C<pattern> is a Perl regular expression.
3058Note: as per the header tests, C<#> must be escaped (C<\#>) or else it is
3059considered the beginning of a comment.
3060
3061The 'raw body' of a message is the raw data inside all textual parts. The
3062text will be decoded from base64 or quoted-printable encoding, but HTML
3063tags and line breaks will still be present. Multiline expressions will
3064need to be used to match strings that are broken by line breaks.
3065
3066=item rawbody SYMBOLIC_TEST_NAME eval:name_of_eval_method([args])
3067
3068Define a raw-body eval test. See above.
3069
3070=cut
3071
3072 push (@cmds, {
3073 setting => 'rawbody',
3074 is_frequent => 1,
3075 is_priv => 1,
3076
# spent 13.9ms (2.08+11.8) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] which was called 40 times, avg 347µs/call: # 40 times (2.08ms+11.8ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 347µs/call
code => sub {
307740237µs my ($self, $key, $value, $line) = @_;
307840155µs local ($1,$2);
307940905µs40149µs if ($value =~ /^(\S+)\s+eval:(.*)$/) {
# spent 149µs making 40 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
3080752µs7401µs $self->{parser}->add_test ($1, $2, $TYPE_RAWBODY_EVALS);
# spent 401µs making 7 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 57µs/call
3081 } else {
308233245µs my @values = split(/\s+/, $value, 2);
30833376µs if (@values != 2) {
3084 return $MISSING_REQUIRED_VALUE;
3085 }
308633297µs3311.3ms $self->{parser}->add_test (@values, $TYPE_RAWBODY_TESTS);
# spent 11.3ms making 33 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 341µs/call
3087 }
3088 }
3089113µs });
3090
3091=item full SYMBOLIC_TEST_NAME /pattern/modifiers
3092
3093Define a full message pattern test. C<pattern> is a Perl regular expression.
3094Note: as per the header tests, C<#> must be escaped (C<\#>) or else it is
3095considered the beginning of a comment.
3096
3097The full message is the pristine message headers plus the pristine message
3098body, including all MIME data such as images, other attachments, MIME
3099boundaries, etc.
3100
3101=item full SYMBOLIC_TEST_NAME eval:name_of_eval_method([args])
3102
3103Define a full message eval test. See above.
3104
3105=cut
3106
3107 push (@cmds, {
3108 setting => 'full',
3109 is_priv => 1,
3110
# spent 2.33ms (640µs+1.69) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] which was called 13 times, avg 179µs/call: # 13 times (640µs+1.69ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 179µs/call
code => sub {
31111393µs my ($self, $key, $value, $line) = @_;
31121355µs local ($1,$2);
311313413µs1374µs if ($value =~ /^(\S+)\s+eval:(.*)$/) {
# spent 74µs making 13 calls to Mail::SpamAssassin::Conf::CORE:match, avg 6µs/call
31141198µs111.05ms $self->{parser}->add_test ($1, $2, $TYPE_FULL_EVALS);
# spent 1.05ms making 11 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 95µs/call
3115 } else {
3116215µs my @values = split(/\s+/, $value, 2);
311725µs if (@values != 2) {
3118 return $MISSING_REQUIRED_VALUE;
3119 }
3120218µs2564µs $self->{parser}->add_test (@values, $TYPE_FULL_TESTS);
# spent 564µs making 2 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 282µs/call
3121 }
3122 }
3123110µs });
3124
3125=item meta SYMBOLIC_TEST_NAME boolean expression
3126
3127Define a boolean expression test in terms of other tests that have
3128been hit or not hit. For example:
3129
3130meta META1 TEST1 && !(TEST2 || TEST3)
3131
3132Note that English language operators ("and", "or") will be treated as
3133rule names, and that there is no C<XOR> operator.
3134
3135=item meta SYMBOLIC_TEST_NAME boolean arithmetic expression
3136
3137Can also define an arithmetic expression in terms of other tests,
3138with an unhit test having the value "0" and a hit test having a
3139nonzero value. The value of a hit meta test is that of its arithmetic
3140expression. The value of a hit eval test is that returned by its
3141method. The value of a hit header, body, rawbody, uri, or full test
3142which has the "multiple" tflag is the number of times the test hit.
3143The value of any other type of hit test is "1".
3144
3145For example:
3146
3147meta META2 (3 * TEST1 - 2 * TEST2) > 0
3148
3149Note that Perl builtins and functions, like C<abs()>, B<can't> be
3150used, and will be treated as rule names.
3151
3152If you want to define a meta-rule, but do not want its individual sub-rules to
3153count towards the final score unless the entire meta-rule matches, give the
3154sub-rules names that start with '__' (two underscores). SpamAssassin will
3155ignore these for scoring.
3156
3157=cut
3158
3159 push (@cmds, {
3160 setting => 'meta',
3161 is_frequent => 1,
3162 is_priv => 1,
3163
# spent 322ms (21.5+301) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3174] which was called 465 times, avg 693µs/call: # 465 times (21.5ms+301ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 693µs/call
code => sub {
31644652.85ms my ($self, $key, $value, $line) = @_;
31654653.43ms my @values = split(/\s+/, $value, 2);
3166465966µs if (@values != 2) {
3167 return $MISSING_REQUIRED_VALUE;
3168 }
31694655.83ms4651.46ms if ($values[1] =~ /\*\s*\*/) {
# spent 1.46ms making 465 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
3170 info("config: found invalid '**' or '* *' operator in meta command");
3171 return $INVALID_VALUE;
3172 }
31734658.28ms465299ms $self->{parser}->add_test (@values, $TYPE_META_TESTS);
# spent 299ms making 465 calls to Mail::SpamAssassin::Conf::Parser::add_test, avg 643µs/call
3174 }
3175111µs });
3176
3177=item reuse SYMBOLIC_TEST_NAME [ OLD_SYMBOLIC_TEST_NAME_1 ... ]
3178
3179Defines the name of a test that should be "reused" during the scoring
3180process. If a message has an X-Spam-Status header that shows a hit for
3181this rule or any of the old rule names given, a hit will be added for
3182this rule when B<mass-check --reuse> is used. Examples:
3183
3184C<reuse SPF_PASS>
3185
3186C<reuse MY_NET_RULE_V2 MY_NET_RULE_V1>
3187
3188The actual logic for reuse tests is done by
3189B<Mail::SpamAssassin::Plugin::Reuse>.
3190
3191=cut
3192
3193 push (@cmds, {
3194 setting => 'reuse',
3195 is_priv => 1,
3196
# spent 2.70ms (2.22+477µs) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] which was called 77 times, avg 35µs/call: # 77 times (2.22ms+477µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 35µs/call
code => sub {
319777363µs my ($self, $key, $value, $line) = @_;
3198771.20ms77401µs if ($value !~ /\s*(\w+)(?:\s+(?:\w+(?:\s+\w+)*))?\s*$/) {
# spent 401µs making 77 calls to Mail::SpamAssassin::Conf::CORE:match, avg 5µs/call
3199 return $INVALID_VALUE;
3200 }
320177251µs my $rule_name = $1;
3202 # don't overwrite tests, just define them so scores, priorities work
3203771.03ms if (!exists $self->{tests}->{$rule_name}) {
3204110µs177µs $self->{parser}->add_test($rule_name, undef, $TYPE_EMPTY_TESTS);
# spent 77µs making 1 call to Mail::SpamAssassin::Conf::Parser::add_test
3205 }
3206 }
3207110µs });
3208
3209=item tflags SYMBOLIC_TEST_NAME flags
3210
3211Used to set flags on a test. Parameter is a space-separated list of flag
3212names or flag name = value pairs.
3213These flags are used in the score-determination back end system for details
3214of the test's behaviour. Please see C<bayes_auto_learn> for more information
3215about tflag interaction with those systems. The following flags can be set:
3216
3217=over 4
3218
3219=item net
3220
3221The test is a network test, and will not be run in the mass checking system
3222or if B<-L> is used, therefore its score should not be modified.
3223
3224=item nice
3225
3226The test is intended to compensate for common false positives, and should be
3227assigned a negative score.
3228
3229=item userconf
3230
3231The test requires user configuration before it can be used (like
3232language-specific tests).
3233
3234=item learn
3235
3236The test requires training before it can be used.
3237
3238=item noautolearn
3239
3240The test will explicitly be ignored when calculating the score for
3241learning systems.
3242
3243=item autolearn_force
3244
3245The test will be subject to less stringent autolearn thresholds.
3246
3247Normally, SpamAssassin will require 3 points from the header and 3
3248points from the body to be auto-learned as spam. This option keeps
3249the threshold at 6 points total but changes it to have no regard to the
3250source of the points.
3251
3252=item noawl
3253
3254This flag is specific when using AWL plugin.
3255
3256Normally, AWL plugin normalizes scores via auto-whitelist. In some scenarios
3257it works against the system administrator when trying to add some rules to
3258correct miss-classified email. When AWL plugin searches the email and finds
3259the noawl flag it will exit without normalizing the score nor storing the
3260value in db.
3261
3262=item multiple
3263
3264The test will be evaluated multiple times, for use with meta rules.
3265Only affects header, body, rawbody, uri, and full tests.
3266
3267=item maxhits=N
3268
3269If B<multiple> is specified, limit the number of hits found to N.
3270If the rule is used in a meta that counts the hits (e.g. __RULENAME > 5),
3271this is a way to avoid wasted extra work (use "tflags multiple maxhits=6").
3272
3273For example:
3274
3275 uri __KAM_COUNT_URIS /^./
3276 tflags __KAM_COUNT_URIS multiple maxhits=16
3277 describe __KAM_COUNT_URIS A multiple match used to count URIs in a message
3278
3279 meta __KAM_HAS_0_URIS (__KAM_COUNT_URIS == 0)
3280 meta __KAM_HAS_1_URIS (__KAM_COUNT_URIS >= 1)
3281 meta __KAM_HAS_2_URIS (__KAM_COUNT_URIS >= 2)
3282 meta __KAM_HAS_3_URIS (__KAM_COUNT_URIS >= 3)
3283 meta __KAM_HAS_4_URIS (__KAM_COUNT_URIS >= 4)
3284 meta __KAM_HAS_5_URIS (__KAM_COUNT_URIS >= 5)
3285 meta __KAM_HAS_10_URIS (__KAM_COUNT_URIS >= 10)
3286 meta __KAM_HAS_15_URIS (__KAM_COUNT_URIS >= 15)
3287
3288=item ips_only
3289
3290This flag is specific to rules invoking an URIDNSBL plugin,
3291it is documented there.
3292
3293=item domains_only
3294
3295This flag is specific to rules invoking an URIDNSBL plugin,
3296it is documented there.
3297
3298=item ns
3299
3300This flag is specific to rules invoking an URIDNSBL plugin,
3301it is documented there.
3302
3303=item a
3304
3305This flag is specific to rules invoking an URIDNSBL plugin,
3306it is documented there.
3307
3308=back
3309
3310=cut
3311
331216µs push (@cmds, {
3313 setting => 'tflags',
3314 is_frequent => 1,
3315 is_priv => 1,
3316 type => $CONF_TYPE_HASH_KEY_VALUE,
3317 });
3318
3319=item priority SYMBOLIC_TEST_NAME n
3320
3321Assign a specific priority to a test. All tests, except for DNS and Meta
3322tests, are run in increasing priority value order (negative priority values
3323are run before positive priority values). The default test priority is 0
3324(zero).
3325
3326The values <-99999999999999> and <-99999999999998> have a special meaning
3327internally, and should not be used.
3328
3329=cut
3330
333116µs push (@cmds, {
3332 setting => 'priority',
3333 is_priv => 1,
3334 type => $CONF_TYPE_HASH_KEY_VALUE,
3335 });
3336
3337=back
3338
3339=head1 ADMINISTRATOR SETTINGS
3340
3341These settings differ from the ones above, in that they are considered 'more
3342privileged' -- even more than the ones in the B<PRIVILEGED SETTINGS> section.
3343No matter what C<allow_user_rules> is set to, these can never be set from a
3344user's C<user_prefs> file when spamc/spamd is being used. However, all
3345settings can be used by local programs run directly by the user.
3346
3347=over 4
3348
3349=item version_tag string
3350
3351This tag is appended to the SA version in the X-Spam-Status header. You should
3352include it when modify your ruleset, especially if you plan to distribute it.
3353A good choice for I<string> is your last name or your initials followed by a
3354number which you increase with each change.
3355
3356The version_tag will be lowercased, and any non-alphanumeric or period
3357character will be replaced by an underscore.
3358
3359e.g.
3360
3361 version_tag myrules1 # version=2.41-myrules1
3362
3363=cut
3364
3365 push (@cmds, {
3366 setting => 'version_tag',
3367 is_admin => 1,
3368 code => sub {
3369 my ($self, $key, $value, $line) = @_;
3370 if ($value eq '') {
3371 return $MISSING_REQUIRED_VALUE;
3372 }
3373 my $tag = lc($value);
3374 $tag =~ tr/a-z0-9./_/c;
3375 foreach (@Mail::SpamAssassin::EXTRA_VERSION) {
3376 if($_ eq $tag) { $tag = undef; last; }
3377 }
3378 push(@Mail::SpamAssassin::EXTRA_VERSION, $tag) if($tag);
3379 }
3380110µs });
3381
3382=item test SYMBOLIC_TEST_NAME (ok|fail) Some string to test against
3383
3384Define a regression testing string. You can have more than one regression test
3385string per symbolic test name. Simply specify a string that you wish the test
3386to match.
3387
3388These tests are only run as part of the test suite - they should not affect the
3389general running of SpamAssassin.
3390
3391=cut
3392
3393 push (@cmds, {
3394 setting => 'test',
3395 is_admin => 1,
3396
# spent 215µs within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3402] which was called 36 times, avg 6µs/call: # 36 times (215µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 6µs/call
code => sub {
339736414µs return unless defined $COLLECT_REGRESSION_TESTS;
3398 my ($self, $key, $value, $line) = @_;
3399 local ($1,$2,$3);
3400 if ($value !~ /^(\S+)\s+(ok|fail)\s+(.*)$/) { return $INVALID_VALUE; }
3401 $self->{parser}->add_regression_test($1, $2, $3);
3402 }
3403110µs });
3404
3405=item rbl_timeout t [t_min] [zone] (default: 15 3)
3406
3407All DNS queries are made at the beginning of a check and we try to read
3408the results at the end. This value specifies the maximum period of time
3409(in seconds) to wait for a DNS query. If most of the DNS queries have
3410succeeded for a particular message, then SpamAssassin will not wait for
3411the full period to avoid wasting time on unresponsive server(s), but will
3412shrink the timeout according to a percentage of queries already completed.
3413As the number of queries remaining approaches 0, the timeout value will
3414gradually approach a t_min value, which is an optional second parameter
3415and defaults to 0.2 * t. If t is smaller than t_min, the initial timeout
3416is set to t_min. Here is a chart of queries remaining versus the timeout
3417in seconds, for the default 15 second / 3 second timeout setting:
3418
3419 queries left 100% 90% 80% 70% 60% 50% 40% 30% 20% 10% 0%
3420 timeout 15 14.9 14.5 13.9 13.1 12.0 10.7 9.1 7.3 5.3 3
3421
3422For example, if 20 queries are made at the beginning of a message check
3423and 16 queries have returned (leaving 20%), the remaining 4 queries should
3424finish within 7.3 seconds since their query started or they will be timed out.
3425Note that timed out queries are only aborted when there is nothing else left
3426for SpamAssassin to do - long evaluation of other rules may grant queries
3427additional time.
3428
3429If a parameter 'zone' is specified (it must end with a letter, which
3430distinguishes it from other numeric parametrs), then the setting only
3431applies to DNS queries against the specified DNS domain (host, domain or
3432RBL (sub)zone). Matching is case-insensitive, the actual domain may be a
3433subdomain of the specified zone.
3434
3435=cut
3436
3437 push (@cmds, {
3438 setting => 'rbl_timeout',
3439 is_admin => 1,
3440 default => 15,
3441 code => sub {
3442 my ($self, $key, $value, $line) = @_;
3443 unless (defined $value && $value !~ /^$/) {
3444 return $MISSING_REQUIRED_VALUE;
3445 }
3446 local ($1,$2,$3);
3447 unless ($value =~ /^ ( \+? \d+ (?: \. \d*)? [smhdw]? )
3448 (?: \s+ ( \+? \d+ (?: \. \d*)? [smhdw]? ) )?
3449 (?: \s+ (\S* [a-zA-Z]) )? $/xsi) {
3450 return $INVALID_VALUE;
3451 }
3452 my($timeout, $timeout_min, $zone) = ($1, $2, $3);
3453 foreach ($timeout, $timeout_min) {
3454 if (defined $_ && s/\s*([smhdw])\z//i) {
3455 $_ *= { s => 1, m => 60, h => 3600,
3456 d => 24*3600, w => 7*24*3600 }->{lc $1};
3457 }
3458 }
3459 if (!defined $zone) { # a global setting
3460 $self->{rbl_timeout} = 0 + $timeout;
3461 $self->{rbl_timeout_min} = 0 + $timeout_min if defined $timeout_min;
3462 }
3463 else { # per-zone settings
3464 $zone =~ s/^\.//; $zone =~ s/\.\z//; # strip leading and trailing dot
3465 $zone = lc $zone;
3466 $self->{by_zone}{$zone}{rbl_timeout} = 0 + $timeout;
3467 $self->{by_zone}{$zone}{rbl_timeout_min} =
3468 0 + $timeout_min if defined $timeout_min;
3469 }
3470 },
3471113µs type => $CONF_TYPE_DURATION,
3472 });
3473
3474=item util_rb_tld tld1 tld2 ...
3475
3476This option maintains list of valid TLDs in the RegistryBoundaries code.
3477TLDs include things like com, net, org, etc.
3478
3479=cut
3480
3481 # DO NOT UPDATE THIS HARDCODED LIST!! It is only as fallback for
3482 # transitional period and to be removed later. TLDs are now maintained in
3483 # sa-update 20_aux_tlds.cf.
34841112µs foreach (qw/
3485 ac academy accountants active actor ad ae aero af ag agency ai airforce al am an
3486 ao aq ar archi army arpa as asia associates at attorney au auction audio autos
3487 aw ax axa az ba bar bargains bayern bb bd be beer berlin best bf bg bh bi bid
3488 bike bio biz bj black blackfriday blue bm bmw bn bnpparibas bo boo boutique br
3489 brussels bs bt build builders business buzz bv bw by bz bzh ca cab camera camp
3490 cancerresearch capetown capital caravan cards care career careers cash cat
3491 catering cc cd center ceo cern cf cg ch cheap christmas church ci citic city ck
3492 cl claims cleaning click clinic clothing club cm cn co codes coffee college
3493 cologne com community company computer condos construction consulting
3494 contractors cooking cool coop country cr credit creditcard cruises cu cuisinella
3495 cv cw cx cy cymru cz dad dance dating day de deals degree democrat dental
3496 dentist desi diamonds diet digital direct directory discount dj dk dm dnp do
3497 domains durban dz eat ec edu education ee eg email engineer engineering
3498 enterprises equipment er es esq estate et eu eus events exchange expert exposed
3499 fail farm feedback fi finance financial fish fishing fitness fj fk flights
3500 florist fm fo foo foundation fr frl frogans fund furniture futbol ga gal gallery
3501 gb gbiz gd ge gent gf gg gh gi gift gifts gives gl glass global globo gm gmail
3502 gmo gn gop gov gp gq gr graphics gratis green gripe gs gt gu guide guitars guru
3503 gw gy hamburg haus healthcare help here hiphop hiv hk hm hn holdings holiday
3504 homes horse host hosting house how hr ht hu id ie il im immo immobilien in
3505 industries info ing ink institute insure int international investments io iq ir
3506 is it je jetzt jm jo jobs joburg jp juegos kaufen ke kg kh ki kim kitchen kiwi
3507 km kn koeln kp kr krd kred kw ky kz la lacaixa land lawyer lb lc lease lgbt li
3508 life lighting limited limo link lk loans london lotto lr ls lt ltda lu luxe
3509 luxury lv ly ma maison management mango market marketing mc md me media meet
3510 melbourne meme menu mg mh miami mil mini mk ml mm mn mo mobi moda moe monash
3511 mortgage moscow motorcycles mov mp mq mr ms mt mu museum mv mw mx my mz na
3512 nagoya name navy nc ne net network neustar new nf ng ngo nhk ni ninja nl no np
3513 nr nra nrw nu nyc nz okinawa om ong onl ooo org organic otsuka ovh pa paris
3514 partners parts pe pf pg ph photo photography photos physio pics pictures pink
3515 pizza pk pl place plumbing pm pn post pr praxi press pro prod productions
3516 properties property ps pt pub pw py qa qpon quebec re realtor recipes red rehab
3517 reise reisen ren rentals repair report republican rest restaurant reviews rich
3518 rio ro rocks rodeo rs rsvp ru ruhr rw ryukyu sa saarland sarl sb sc sca scb
3519 schmidt schule scot sd se services sexy sg sh shiksha shoes si singles sj sk sl
3520 sm sn so social software sohu solar solutions soy space spiegel sr st su
3521 supplies supply support surf surgery suzuki sv sx sy systems sz tatar tattoo tax
3522 tc td technology tel tf tg th tienda tips tirol tj tk tl tm tn to today tokyo
3523 tools top town toys tr trade training travel tt tv tw tz ua ug uk university
3524 uno uol us uy uz va vacations vc ve vegas ventures versicherung vet vg vi viajes
3525 villas vision vlaanderen vn vodka vote voting voto voyage vu wales wang watch
3526 webcam website wed wf whoswho wien wiki williamhill works ws wtc wtf xn--1qqw23a
3527 xn--3bst00m xn--3ds443g xn--3e0b707e xn--45brj9c xn--4gbrim xn--55qw42g
3528 xn--55qx5d xn--6frz82g xn--6qq986b3xl xn--80adxhks xn--80ao21a xn--80asehdb
3529 xn--80aswg xn--90a3ac xn--c1avg xn--cg4bki xn--clchc0ea0b2g2a9gcd xn--czr694b
3530 xn--czru2d xn--d1acj3b xn--fiq228c5hs xn--fiq64b xn--fiqs8s xn--fiqz9s
3531 xn--fpcrj9c3d xn--fzc2c9e2c xn--gecrj9c xn--h2brj9c xn--i1b6b1a6a2e xn--io0a7i
3532 xn--j1amh xn--j6w193g xn--kprw13d xn--kpry57d xn--kput3i xn--l1acc
3533 xn--lgbbat1ad8j xn--mgb9awbf xn--mgba3a4f16a xn--mgbaam7a8h xn--mgbab2bd
3534 xn--mgbayh7gpa xn--mgbbh1a71e xn--mgbc0a9azcg xn--mgberp4a5d4ar xn--mgbx4cd0ab
3535 xn--ngbc5azd xn--nqv7f xn--nqv7fs00ema xn--o3cw4h xn--ogbpf8fl xn--p1ai
3536 xn--pgbs0dh xn--q9jyb4c xn--rhqv96g xn--s9brj9c xn--ses554g xn--unup4y xn--vhquv
3537 xn--wgbh1c xn--wgbl6a xn--xhq521b xn--xkc2al3hye2a xn--xkc2dl3a5ee0h
3538 xn--yfro4i67o xn--ygbi2ammx xn--zfr164b xxx xyz yachts yandex ye yokohama
3539 youtube yt za zm zone zw
354069912.5ms /) { $self->{valid_tlds}{lc $_} = 1; }
3541
3542 push (@cmds, {
3543 setting => 'util_rb_tld',
3544 is_admin => 1,
3545
# spent 15.9ms (13.5+2.34) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3557] which was called 128 times, avg 124µs/call: # 128 times (13.5ms+2.34ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 124µs/call
code => sub {
3546128561µs my ($self, $key, $value, $line) = @_;
35471281.06ms128326µs unless (defined $value && $value !~ /^$/) {
# spent 326µs making 128 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
3548 return $MISSING_REQUIRED_VALUE;
3549 }
35501281.84ms1281.09ms unless ($value =~ /^[^\s.]+(?:\s+[^\s.]+)*$/) {
# spent 1.09ms making 128 calls to Mail::SpamAssassin::Conf::CORE:match, avg 9µs/call
3551 return $INVALID_VALUE;
3552 }
35531282.51ms foreach (split(/\s+/, $value)) {
355414887.34ms $self->{valid_tlds}{lc $_} = 1;
3555 }
35561281.60ms128923µs dbg("config: added tld list - $value");
# spent 923µs making 128 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call
3557 }
3558138µs });
3559
3560=item util_rb_2tld 2tld-1.tld 2tld-2.tld ...
3561
3562This option maintains list of valid 2nd-level TLDs in the RegistryBoundaries
3563code. 2TLDs include things like co.uk, fed.us, etc.
3564
3565=cut
3566
3567 # DO NOT UPDATE THIS HARDCODED LIST!! It is only as fallback for
3568 # transitional period and to be removed later. TLDs are now maintained in
3569 # sa-update 20_aux_tlds.cf.
35701244µs foreach (qw/
3571 com.ac edu.ac gov.ac mil.ac net.ac org.ac nom.ad ac.ae co.ae com.ae gov.ae
3572 mil.ae name.ae net.ae org.ae pro.ae sch.ae com.af edu.af gov.af net.af
3573 co.ag com.ag net.ag nom.ag org.ag com.ai edu.ai gov.ai net.ai off.ai
3574 org.ai com.al edu.al gov.al net.al org.al com.an edu.an net.an org.an
3575 co.ao ed.ao gv.ao it.ao og.ao pb.ao com.ar edu.ar gov.ar int.ar mil.ar
3576 net.ar org.ar e164.arpa in-addr.arpa ip6.arpa iris.arpa uri.arpa urn.arpa
3577 ac.at co.at gv.at or.at priv.at act.au asn.au com.au conf.au csiro.au
3578 edu.au gov.au id.au info.au net.au nsw.au nt.au org.au otc.au oz.au qld.au
3579 sa.au tas.au telememo.au vic.au wa.au com.aw biz.az com.az edu.az gov.az
3580 info.az int.az mil.az name.az net.az org.az pp.az co.ba com.ba edu.ba
3581 gov.ba mil.ba net.ba org.ba rs.ba unbi.ba unsa.ba com.bb edu.bb gov.bb
3582 net.bb org.bb ac.bd com.bd edu.bd gov.bd mil.bd net.bd org.bd ac.be
3583 belgie.be dns.be fgov.be gov.bf biz.bh cc.bh com.bh edu.bh gov.bh info.bh
3584 net.bh org.bh com.bm edu.bm gov.bm net.bm org.bm com.bn edu.bn net.bn
3585 org.bn com.bo edu.bo gob.bo gov.bo int.bo mil.bo net.bo org.bo tv.bo
3586 adm.br adv.br agr.br am.br arq.br art.br ato.br bio.br bmd.br cim.br
3587 cng.br cnt.br com.br coop.br dpn.br eco.br ecn.br edu.br eng.br esp.br
3588 etc.br eti.br far.br fm.br fnd.br fot.br fst.br g12.br ggf.br gov.br
3589 imb.br ind.br inf.br jor.br lel.br mat.br med.br mil.br mus.br net.br
3590 nom.br not.br ntr.br odo.br org.br ppg.br pro.br psc.br psi.br qsl.br
3591 rec.br slg.br srv.br tmp.br trd.br tur.br tv.br vet.br zlg.br com.bs
3592 net.bs org.bs com.bt edu.bt gov.bt net.bt org.bt co.bw org.bw gov.by
3593 mil.by com.bz net.bz org.bz ab.ca bc.ca gc.ca mb.ca nb.ca nf.ca nl.ca
3594 ns.ca nt.ca nu.ca on.ca pe.ca qc.ca sk.ca yk.ca co.ck edu.ck gov.ck net.ck
3595 org.ck ac.cn ah.cn bj.cn com.cn cq.cn edu.cn fj.cn gd.cn gov.cn gs.cn
3596 gx.cn gz.cn ha.cn hb.cn he.cn hi.cn hk.cn hl.cn hn.cn jl.cn js.cn jx.cn
3597 ln.cn mo.cn net.cn nm.cn nx.cn org.cn qh.cn sc.cn sd.cn sh.cn sn.cn sx.cn
3598 tj.cn tw.cn xj.cn xz.cn yn.cn zj.cn arts.co com.co edu.co firm.co gov.co
3599 info.co int.co mil.co net.co nom.co org.co rec.co web.co lkd.co.im
3600 ltd.co.im plc.co.im co.cm com.cm net.cm au.com br.com cn.com de.com eu.com
3601 gb.com hu.com no.com qc.com ru.com sa.com se.com uk.com us.com uy.com
3602 za.com ac.cr co.cr ed.cr fi.cr go.cr or.cr sa.cr com.cu edu.cu gov.cu
3603 inf.cu net.cu org.cu gov.cx ac.cy biz.cy com.cy ekloges.cy gov.cy ltd.cy
3604 name.cy net.cy org.cy parliament.cy press.cy pro.cy tm.cy co.dk com.dm
3605 edu.dm gov.dm net.dm org.dm art.do com.do edu.do gob.do gov.do mil.do
3606 net.do org.do sld.do web.do art.dz asso.dz com.dz edu.dz gov.dz net.dz
3607 org.dz pol.dz com.ec edu.ec fin.ec gov.ec info.ec k12.ec med.ec mil.ec
3608 net.ec org.ec pro.ec gob.ec co.ee com.ee edu.ee fie.ee med.ee org.ee
3609 pri.ee com.eg edu.eg eun.eg gov.eg mil.eg net.eg org.eg sci.eg com.er
3610 edu.er gov.er ind.er mil.er net.er org.er com.es edu.es gob.es nom.es
3611 org.es biz.et com.et edu.et gov.et info.et name.et net.et org.et aland.fi
3612 ac.fj biz.fj com.fj gov.fj id.fj info.fj mil.fj name.fj net.fj org.fj
3613 pro.fj school.fj ac.fk co.fk com.fk gov.fk net.fk nom.fk org.fk tm.fr
3614 asso.fr nom.fr prd.fr presse.fr com.fr gouv.fr com.ge edu.ge gov.ge mil.ge
3615 net.ge org.ge pvt.ge ac.gg alderney.gg co.gg gov.gg guernsey.gg ind.gg
3616 ltd.gg net.gg org.gg sark.gg sch.gg com.gh edu.gh gov.gh mil.gh org.gh
3617 com.gi edu.gi gov.gi ltd.gi mod.gi org.gi ac.gn com.gn gov.gn net.gn
3618 org.gn asso.gp com.gp edu.gp net.gp org.gp com.gr edu.gr gov.gr net.gr
3619 org.gr com.gt edu.gt gob.gt ind.gt mil.gt net.gt org.gt com.gu edu.gu
3620 gov.gu mil.gu net.gu org.gu com.hk edu.hk gov.hk idv.hk net.hk org.hk
3621 com.hn edu.hn gob.hn mil.hn net.hn org.hn com.hr from.hr iz.hr name.hr
3622 adult.ht art.ht asso.ht com.ht coop.ht edu.ht firm.ht gouv.ht info.ht
3623 med.ht net.ht org.ht perso.ht pol.ht pro.ht rel.ht shop.ht 2000.hu
3624 agrar.hu bolt.hu casino.hu city.hu co.hu erotica.hu erotika.hu film.hu
3625 forum.hu games.hu hotel.hu info.hu ingatlan.hu jogasz.hu konyvelo.hu
3626 lakas.hu media.hu news.hu org.hu priv.hu reklam.hu sex.hu shop.hu sport.hu
3627 suli.hu szex.hu tm.hu tozsde.hu utazas.hu video.hu ac.id co.id go.id
3628 mil.id net.id or.id sch.id web.id gov.ie ac.il co.il gov.il idf.il k12.il
3629 muni.il net.il org.il ac.im co.im gov.im net.im nic.im org.im ac.in co.in
3630 edu.in ernet.in firm.in gen.in gov.in ind.in mil.in net.in nic.in org.in
3631 res.in com.io gov.io mil.io net.io org.io ac.ir co.ir gov.ir id.ir net.ir
3632 org.ir sch.ir edu.it gov.it ac.je co.je gov.je ind.je jersey.je ltd.je
3633 net.je org.je sch.je com.jm edu.jm gov.jm net.jm org.jm com.jo edu.jo
3634 gov.jo mil.jo net.jo org.jo ac.jp ad.jp aichi.jp akita.jp aomori.jp
3635 chiba.jp co.jp ed.jp ehime.jp fukui.jp fukuoka.jp fukushima.jp gifu.jp
3636 go.jp gov.jp gr.jp gunma.jp hiroshima.jp hokkaido.jp hyogo.jp ibaraki.jp
3637 ishikawa.jp iwate.jp kagawa.jp kagoshima.jp kanagawa.jp kanazawa.jp
3638 kawasaki.jp kitakyushu.jp kobe.jp kochi.jp kumamoto.jp kyoto.jp lg.jp
3639 matsuyama.jp mie.jp miyagi.jp miyazaki.jp nagano.jp nagasaki.jp nagoya.jp
3640 nara.jp ne.jp net.jp niigata.jp oita.jp okayama.jp okinawa.jp or.jp org.jp
3641 osaka.jp saga.jp saitama.jp sapporo.jp sendai.jp shiga.jp shimane.jp
3642 shizuoka.jp takamatsu.jp tochigi.jp tokushima.jp tokyo.jp tottori.jp
3643 toyama.jp utsunomiya.jp wakayama.jp yamagata.jp yamaguchi.jp yamanashi.jp
3644 yokohama.jp ac.ke co.ke go.ke ne.ke new.ke or.ke sc.ke com.kg edu.kg
3645 gov.kg mil.kg net.kg org.kg com.kh edu.kh gov.kh mil.kh net.kh org.kh
3646 per.kh ac.kr busan.kr chungbuk.kr chungnam.kr co.kr daegu.kr daejeon.kr
3647 es.kr gangwon.kr go.kr gwangju.kr gyeongbuk.kr gyeonggi.kr gyeongnam.kr
3648 hs.kr incheon.kr jeju.kr jeonbuk.kr jeonnam.kr kg.kr kyonggi.kr mil.kr
3649 ms.kr ne.kr or.kr pe.kr re.kr sc.kr seoul.kr ulsan.kr com.kw edu.kw gov.kw
3650 mil.kw net.kw org.kw com.ky edu.ky gov.ky net.ky org.ky com.kz edu.kz
3651 gov.kz mil.kz net.kz org.kz com.la net.la org.la com.lb edu.lb gov.lb
3652 mil.lb net.lb org.lb com.lc edu.lc gov.lc net.lc org.lc assn.lk com.lk
3653 edu.lk gov.lk grp.lk hotel.lk int.lk ltd.lk net.lk ngo.lk org.lk sch.lk
3654 soc.lk web.lk com.lr edu.lr gov.lr net.lr org.lr co.ls org.ls gov.lt
3655 mil.lt asn.lv com.lv conf.lv edu.lv gov.lv id.lv mil.lv net.lv org.lv
3656 biz.ly com.ly edu.ly gov.ly id.ly med.ly net.ly org.ly plc.ly sch.ly ac.ma
3657 co.ma gov.ma net.ma org.ma press.ma asso.mc tm.mc ac.me co.me edu.me
3658 gov.me its.me net.me org.me priv.me com.mg edu.mg gov.mg mil.mg nom.mg
3659 org.mg prd.mg tm.mg army.mil navy.mil com.mk org.mk com.mm edu.mm gov.mm
3660 net.mm org.mm edu.mn gov.mn org.mn com.mo edu.mo gov.mo net.mo org.mo
3661 music.mobi weather.mobi co.mp edu.mp gov.mp net.mp org.mp com.mt edu.mt
3662 gov.mt net.mt org.mt tm.mt uu.mt co.mu com.mu aero.mv biz.mv com.mv
3663 coop.mv edu.mv gov.mv info.mv int.mv mil.mv museum.mv name.mv net.mv
3664 org.mv pro.mv ac.mw co.mw com.mw coop.mw edu.mw gov.mw int.mw museum.mw
3665 net.mw org.mw com.mx edu.mx gob.mx net.mx org.mx com.my edu.my gov.my
3666 mil.my name.my net.my org.my alt.na com.na cul.na edu.na net.na org.na
3667 telecom.na unam.na com.nc net.nc org.nc de.net gb.net uk.net ac.ng com.ng
3668 edu.ng gov.ng net.ng org.ng sch.ng ac.ni biz.ni com.ni edu.ni gob.ni in.ni
3669 info.ni int.ni mil.ni net.ni nom.ni org.ni web.ni fhs.no folkebibl.no
3670 fylkesbibl.no herad.no idrett.no kommune.no mil.no museum.no priv.no
3671 stat.no tel.no vgs.no com.np edu.np gov.np mil.np net.np org.np biz.nr
3672 co.nr com.nr edu.nr fax.nr gov.nr info.nr mob.nr mobil.nr mobile.nr net.nr
3673 org.nr tel.nr tlf.nr ac.nz co.nz cri.nz geek.nz gen.nz govt.nz iwi.nz
3674 maori.nz mil.nz net.nz org.nz school.nz ac.om biz.om co.om com.om edu.om
3675 gov.om med.om mil.om mod.om museum.om net.om org.om pro.om sch.om dk.org
3676 eu.org abo.pa ac.pa com.pa edu.pa gob.pa ing.pa med.pa net.pa nom.pa
3677 org.pa sld.pa com.pe edu.pe gob.pe mil.pe net.pe nom.pe org.pe com.pf
3678 edu.pf org.pf ac.pg com.pg net.pg com.ph edu.ph gov.ph mil.ph net.ph
3679 ngo.ph org.ph biz.pk com.pk edu.pk fam.pk gob.pk gok.pk gon.pk gop.pk
3680 gos.pk gov.pk net.pk org.pk web.pk art.pl biz.pl com.pl edu.pl gov.pl
3681 info.pl mil.pl net.pl ngo.pl org.pl biz.pr com.pr edu.pr gov.pr info.pr
3682 isla.pr name.pr net.pr org.pr pro.pr cpa.pro law.pro med.pro com.ps edu.ps
3683 gov.ps net.ps org.ps plo.ps sec.ps com.pt edu.pt gov.pt int.pt net.pt
3684 nome.pt org.pt publ.pt com.py edu.py gov.py net.py org.py com.qa edu.qa
3685 gov.qa net.qa org.qa asso.re com.re nom.re arts.ro com.ro firm.ro info.ro
3686 nom.ro nt.ro org.ro rec.ro store.ro tm.ro www.ro ac.rs co.rs edu.rs gov.rs
3687 in.rs org.rs ac.ru com.ru edu.ru gov.ru int.ru mil.ru net.ru org.ru pp.ru
3688 ac.rw co.rw com.rw edu.rw gouv.rw gov.rw int.rw mil.rw net.rw com.sa
3689 edu.sa gov.sa med.sa net.sa org.sa pub.sa sch.sa com.sb edu.sb gov.sb
3690 net.sb org.sb com.sc edu.sc gov.sc net.sc org.sc com.sd edu.sd gov.sd
3691 info.sd med.sd net.sd org.sd sch.sd tv.sd ab.se ac.se bd.se brand.se c.se
3692 d.se e.se f.se fh.se fhsk.se fhv.se g.se h.se i.se k.se komforb.se
3693 kommunalforbund.se komvux.se lanarb.se lanbib.se m.se mil.se n.se
3694 naturbruksgymn.se o.se org.se parti.se pp.se press.se s.se sshn.se t.se
3695 tm.se u.se w.se x.se y.se z.se com.sg edu.sg gov.sg idn.sg net.sg org.sg
3696 per.sg com.sh edu.sh gov.sh mil.sh net.sh org.sh edu.sk gov.sk mil.sk
3697 co.st com.st consulado.st edu.st embaixada.st gov.st mil.st net.st org.st
3698 principe.st saotome.st store.st com.sv edu.sv gob.sv org.sv red.sv com.sy
3699 gov.sy net.sy org.sy at.tf bg.tf ca.tf ch.tf cz.tf de.tf edu.tf eu.tf
3700 int.tf net.tf pl.tf ru.tf sg.tf us.tf ac.th co.th go.th in.th mi.th net.th
3701 or.th ac.tj biz.tj co.tj com.tj edu.tj go.tj gov.tj int.tj mil.tj name.tj
3702 net.tj org.tj web.tj com.tn edunet.tn ens.tn fin.tn gov.tn ind.tn info.tn
3703 intl.tn nat.tn net.tn org.tn rnrt.tn rns.tn rnu.tn tourism.tn gov.to
3704 av.tr bbs.tr bel.tr biz.tr com.tr dr.tr edu.tr gen.tr gov.tr
3705 info.tr k12.tr mil.tr name.tr net.tr org.tr pol.tr tel.tr web.tr aero.tt
3706 at.tt au.tt be.tt biz.tt ca.tt co.tt com.tt coop.tt de.tt dk.tt edu.tt
3707 es.tt eu.tt fr.tt gov.tt info.tt int.tt it.tt jobs.tt mobi.tt museum.tt
3708 name.tt net.tt nic.tt org.tt pro.tt se.tt travel.tt uk.tt us.tt co.tv
3709 gov.tv club.tw com.tw ebiz.tw edu.tw game.tw gov.tw idv.tw mil.tw net.tw
3710 org.tw ac.tz co.tz go.tz ne.tz or.tz cherkassy.ua chernigov.ua
3711 chernovtsy.ua ck.ua cn.ua co.ua com.ua crimea.ua cv.ua dn.ua
3712 dnepropetrovsk.ua donetsk.ua dp.ua edu.ua gov.ua if.ua in.ua
3713 ivano-frankivsk.ua kh.ua kharkov.ua kherson.ua khmelnitskiy.ua kiev.ua
3714 kirovograd.ua km.ua kr.ua ks.ua kv.ua lg.ua lugansk.ua lutsk.ua lviv.ua
3715 mk.ua net.ua nikolaev.ua od.ua odessa.ua org.ua pl.ua poltava.ua rovno.ua
3716 rv.ua sebastopol.ua sumy.ua te.ua ternopil.ua uzhgorod.ua vinnica.ua vn.ua
3717 zaporizhzhe.ua zhitomir.ua zp.ua zt.ua ac.ug co.ug go.ug ne.ug or.ug sc.ug
3718 ac.uk bl.uk british-library.uk co.uk edu.uk gov.uk icnet.uk jet.uk ltd.uk
3719 me.uk mod.uk national-library-scotland.uk net.uk nhs.uk nic.uk nls.uk
3720 org.uk parliament.uk plc.uk police.uk sch.uk ak.us al.us ar.us az.us ca.us
3721 co.us ct.us dc.us de.us dni.us fed.us fl.us ga.us hi.us ia.us id.us il.us
3722 in.us isa.us kids.us ks.us ky.us la.us ma.us md.us me.us mi.us mn.us mo.us
3723 ms.us mt.us nc.us nd.us ne.us nh.us nj.us nm.us nsn.us nv.us ny.us oh.us
3724 ok.us or.us pa.us ri.us sc.us sd.us tn.us tx.us ut.us va.us vt.us wa.us
3725 wi.us wv.us wy.us com.uy edu.uy gub.uy mil.uy net.uy org.uy vatican.va
3726 arts.ve bib.ve co.ve com.ve edu.ve firm.ve gov.ve info.ve int.ve mil.ve
3727 net.ve nom.ve org.ve rec.ve store.ve tec.ve web.ve co.vi com.vi edu.vi
3728 gov.vi net.vi org.vi ac.vn biz.vn com.vn edu.vn gov.vn health.vn info.vn
3729 int.vn name.vn net.vn org.vn pro.vn ch.vu com.vu de.vu edu.vu fr.vu net.vu
3730 org.vu com.ws edu.ws gov.ws net.ws org.ws com.ye edu.ye gov.ye mil.ye
3731 net.ye org.ye ac.za alt.za bourse.za city.za co.za edu.za gov.za law.za
3732 mil.za net.za ngo.za nom.za org.za school.za tm.za web.za ac.zm co.zm
3733 com.zm edu.zm gov.zm org.zm sch.zm ac.zw co.zw gov.zw org.zw
373415876.43ms /) { $self->{two_level_domains}{lc $_} = 1; }
3735
3736 push (@cmds, {
3737 setting => 'util_rb_2tld',
3738 is_admin => 1,
3739
# spent 28.2ms (23.4+4.75) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3750] which was called 459 times, avg 61µs/call: # 459 times (23.4ms+4.75ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 61µs/call
code => sub {
37404592.15ms my ($self, $key, $value, $line) = @_;
37414594.51ms4591.77ms unless (defined $value && $value !~ /^$/) {
# spent 1.77ms making 459 calls to Mail::SpamAssassin::Conf::CORE:match, avg 4µs/call
3742 return $MISSING_REQUIRED_VALUE;
3743 }
37444595.62ms4592.99ms unless ($value =~ /^[^\s.]+\.[^\s.]+(?:\s+[^\s.]+\.[^\s.]+)*$/) {
# spent 2.99ms making 459 calls to Mail::SpamAssassin::Conf::CORE:match, avg 7µs/call
3745 return $INVALID_VALUE;
3746 }
37474597.48ms foreach (split(/\s+/, $value)) {
374818689.17ms $self->{two_level_domains}{lc $_} = 1;
3749 }
3750 }
3751115µs });
3752
3753=item util_rb_3tld 3tld1.some.tld 3tld2.other.tld ...
3754
3755This option maintains list of valid 3rd-level TLDs in the RegistryBoundaries
3756code. 3TLDs include things like demon.co.uk, plc.co.im, etc.
3757
3758=cut
3759
3760 # DO NOT UPDATE THIS HARDCODED LIST!! It is only as fallback for
3761 # transitional period and to be removed later. TLDs are now maintained in
3762 # sa-update 20_aux_tlds.cf.
376315µs foreach (qw/
3764 demon.co.uk esc.edu.ar lkd.co.im plc.co.im
3765417µs /) { $self->{three_level_domains}{lc $_} = 1; }
3766
3767 push (@cmds, {
3768 setting => 'util_rb_3tld',
3769 is_admin => 1,
3770
# spent 1.91ms (1.52+389µs) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3781] which was called 48 times, avg 40µs/call: # 48 times (1.52ms+389µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 40µs/call
code => sub {
377148222µs my ($self, $key, $value, $line) = @_;
377248439µs48154µs unless (defined $value && $value !~ /^$/) {
# spent 154µs making 48 calls to Mail::SpamAssassin::Conf::CORE:match, avg 3µs/call
3773 return $MISSING_REQUIRED_VALUE;
3774 }
377548516µs48235µs unless ($value =~ /^[^\s.]+\.[^\s.]+\.[^\s.]+(?:\s+[^\s.]+\.[^\s.]+\.[^\s.]+)*$/) {
# spent 235µs making 48 calls to Mail::SpamAssassin::Conf::CORE:match, avg 5µs/call
3776 return $INVALID_VALUE;
3777 }
377848516µs foreach (split(/\s+/, $value)) {
377948302µs $self->{three_level_domains}{lc $_} = 1;
3780 }
3781 }
3782110µs });
3783
3784=item clear_util_rb
3785
3786Empty internal list of valid TLDs (including 2nd and 3rd level) which
3787RegistryBoundaries code uses. Only useful if you want to override the
3788standard lists supplied by sa-update.
3789
3790=cut
3791
3792 push (@cmds, {
3793 setting => 'clear_util_rb',
3794 type => $CONF_TYPE_NOARGS,
3795
# spent 1.20ms (1.19+14µs) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3804] which was called: # once (1.19ms+14µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
379616µs my ($self, $key, $value, $line) = @_;
379713µs unless (!defined $value || $value eq '') {
3798 return $INVALID_VALUE;
3799 }
38001365µs $self->{valid_tlds} = ();
38011778µs $self->{two_level_domains} = ();
380217µs $self->{three_level_domains} = ();
3803122µs114µs dbg("config: cleared tld lists");
# spent 14µs making 1 call to Mail::SpamAssassin::Logger::dbg
3804 }
3805115µs });
3806
3807=item bayes_path /path/filename (default: ~/.spamassassin/bayes)
3808
3809This is the directory and filename for Bayes databases. Several databases
3810will be created, with this as the base directory and filename, with C<_toks>,
3811C<_seen>, etc. appended to the base. The default setting results in files
3812called C<~/.spamassassin/bayes_seen>, C<~/.spamassassin/bayes_toks>, etc.
3813
3814By default, each user has their own in their C<~/.spamassassin> directory with
3815mode 0700/0600. For system-wide SpamAssassin use, you may want to reduce disk
3816space usage by sharing this across all users. However, Bayes appears to be
3817more effective with individual user databases.
3818
3819=cut
3820
3821 push (@cmds, {
3822 setting => 'bayes_path',
3823 is_admin => 1,
3824 default => '__userstate__/bayes',
3825 type => $CONF_TYPE_STRING,
3826
# spent 132µs (92+40) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3835] which was called: # once (92µs+40µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
3827112µs my ($self, $key, $value, $line) = @_;
3828128µs16µs unless (defined $value && $value !~ /^$/) {
# spent 6µs making 1 call to Mail::SpamAssassin::Conf::CORE:match
3829 return $MISSING_REQUIRED_VALUE;
3830 }
3831161µs135µs if (-d $value) {
# spent 35µs making 1 call to Mail::SpamAssassin::Conf::CORE:ftdir
3832 return $INVALID_VALUE;
3833 }
3834116µs $self->{bayes_path} = $value;
3835 }
3836112µs });
3837
3838=item bayes_file_mode (default: 0700)
3839
3840The file mode bits used for the Bayesian filtering database files.
3841
3842Make sure you specify this using the 'x' mode bits set, as it may also be used
3843to create directories. However, if a file is created, the resulting file will
3844not have any execute bits set (the umask is set to 111). The argument is a
3845string of octal digits, it is converted to a numeric value internally.
3846
3847=cut
3848
3849 push (@cmds, {
3850 setting => 'bayes_file_mode',
3851 is_admin => 1,
3852 default => '0700',
3853 type => $CONF_TYPE_NUMERIC,
3854
# spent 88µs (44+45) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3858] which was called: # once (44µs+45µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm
code => sub {
385518µs my ($self, $key, $value, $line) = @_;
3856120µs17µs if ($value !~ /^0?[0-7]{3}$/) { return $INVALID_VALUE }
# spent 7µs making 1 call to Mail::SpamAssassin::Conf::CORE:match
3857122µs138µs $self->{bayes_file_mode} = untaint_var($value);
# spent 38µs making 1 call to Mail::SpamAssassin::Util::untaint_var
3858 }
3859113µs });
3860
3861=item bayes_store_module Name::Of::BayesStore::Module
3862
3863If this option is set, the module given will be used as an alternate
3864to the default bayes storage mechanism. It must conform to the
3865published storage specification (see
3866Mail::SpamAssassin::BayesStore). For example, set this to
3867Mail::SpamAssassin::BayesStore::SQL to use the generic SQL storage
3868module.
3869
3870=cut
3871
3872 push (@cmds, {
3873 setting => 'bayes_store_module',
3874 is_admin => 1,
3875 default => '',
3876 type => $CONF_TYPE_STRING,
3877 code => sub {
3878 my ($self, $key, $value, $line) = @_;
3879 local ($1);
3880 if ($value !~ /^([_A-Za-z0-9:]+)$/) { return $INVALID_VALUE; }
3881 $self->{bayes_store_module} = $1;
3882 }
3883118µs });
3884
3885=item bayes_sql_dsn DBI::databasetype:databasename:hostname:port
3886
3887Used for BayesStore::SQL storage implementation.
3888
3889This option give the connect string used to connect to the SQL based Bayes storage.
3890
3891=cut
3892
389316µs push (@cmds, {
3894 setting => 'bayes_sql_dsn',
3895 is_admin => 1,
3896 default => '',
3897 type => $CONF_TYPE_STRING,
3898 });
3899
3900=item bayes_sql_username
3901
3902Used by BayesStore::SQL storage implementation.
3903
3904This option gives the username used by the above DSN.
3905
3906=cut
3907
390816µs push (@cmds, {
3909 setting => 'bayes_sql_username',
3910 is_admin => 1,
3911 default => '',
3912 type => $CONF_TYPE_STRING,
3913 });
3914
3915=item bayes_sql_password
3916
3917Used by BayesStore::SQL storage implementation.
3918
3919This option gives the password used by the above DSN.
3920
3921=cut
3922
392316µs push (@cmds, {
3924 setting => 'bayes_sql_password',
3925 is_admin => 1,
3926 default => '',
3927 type => $CONF_TYPE_STRING,
3928 });
3929
3930=item bayes_sql_username_authorized ( 0 | 1 ) (default: 0)
3931
3932Whether to call the services_authorized_for_username plugin hook in BayesSQL.
3933If the hook does not determine that the user is allowed to use bayes or is
3934invalid then then database will not be initialized.
3935
3936NOTE: By default the user is considered invalid until a plugin returns
3937a true value. If you enable this, but do not have a proper plugin
3938loaded, all users will turn up as invalid.
3939
3940The username passed into the plugin can be affected by the
3941bayes_sql_override_username config option.
3942
3943=cut
3944
394515µs push (@cmds, {
3946 setting => 'bayes_sql_username_authorized',
3947 is_admin => 1,
3948 default => 0,
3949 type => $CONF_TYPE_BOOL,
3950 });
3951
3952=item user_scores_dsn DBI:databasetype:databasename:hostname:port
3953
3954If you load user scores from an SQL database, this will set the DSN
3955used to connect. Example: C<DBI:mysql:spamassassin:localhost>
3956
3957If you load user scores from an LDAP directory, this will set the DSN used to
3958connect. You have to write the DSN as an LDAP URL, the components being the
3959host and port to connect to, the base DN for the search, the scope of the
3960search (base, one or sub), the single attribute being the multivalued attribute
3961used to hold the configuration data (space separated pairs of key and value,
3962just as in a file) and finally the filter being the expression used to filter
3963out the wanted username. Note that the filter expression is being used in a
3964sprintf statement with the username as the only parameter, thus is can hold a
3965single __USERNAME__ expression. This will be replaced with the username.
3966
3967Example: C<ldap://localhost:389/dc=koehntopp,dc=de?saconfig?uid=__USERNAME__>
3968
3969=cut
3970
397115µs push (@cmds, {
3972 setting => 'user_scores_dsn',
3973 is_admin => 1,
3974 default => '',
3975 type => $CONF_TYPE_STRING,
3976 });
3977
3978=item user_scores_sql_username username
3979
3980The authorized username to connect to the above DSN.
3981
3982=cut
3983
398415µs push (@cmds, {
3985 setting => 'user_scores_sql_username',
3986 is_admin => 1,
3987 default => '',
3988 type => $CONF_TYPE_STRING,
3989 });
3990
3991=item user_scores_sql_password password
3992
3993The password for the database username, for the above DSN.
3994
3995=cut
3996
399716µs push (@cmds, {
3998 setting => 'user_scores_sql_password',
3999 is_admin => 1,
4000 default => '',
4001 type => $CONF_TYPE_STRING,
4002 });
4003
4004=item user_scores_sql_custom_query query
4005
4006This option gives you the ability to create a custom SQL query to
4007retrieve user scores and preferences. In order to work correctly your
4008query should return two values, the preference name and value, in that
4009order. In addition, there are several "variables" that you can use
4010as part of your query, these variables will be substituted for the
4011current values right before the query is run. The current allowed
4012variables are:
4013
4014=over 4
4015
4016=item _TABLE_
4017
4018The name of the table where user scores and preferences are stored. Currently
4019hardcoded to userpref, to change this value you need to create a new custom
4020query with the new table name.
4021
4022=item _USERNAME_
4023
4024The current user's username.
4025
4026=item _MAILBOX_
4027
4028The portion before the @ as derived from the current user's username.
4029
4030=item _DOMAIN_
4031
4032The portion after the @ as derived from the current user's username, this
4033value may be null.
4034
4035=back
4036
4037The query must be one continuous line in order to parse correctly.
4038
4039Here are several example queries, please note that these are broken up
4040for easy reading, in your config it should be one continuous line.
4041
4042=over 4
4043
4044=item Current default query:
4045
4046C<SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '@GLOBAL' ORDER BY username ASC>
4047
4048=item Use global and then domain level defaults:
4049
4050C<SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '@GLOBAL' OR username = '@~'||_DOMAIN_ ORDER BY username ASC>
4051
4052=item Maybe global prefs should override user prefs:
4053
4054C<SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '@GLOBAL' ORDER BY username DESC>
4055
4056=back
4057
4058=cut
4059
406016µs push (@cmds, {
4061 setting => 'user_scores_sql_custom_query',
4062 is_admin => 1,
4063 default => undef,
4064 type => $CONF_TYPE_STRING,
4065 });
4066
4067=item user_scores_ldap_username
4068
4069This is the Bind DN used to connect to the LDAP server. It defaults
4070to the empty string (""), allowing anonymous binding to work.
4071
4072Example: C<cn=master,dc=koehntopp,dc=de>
4073
4074=cut
4075
407616µs push (@cmds, {
4077 setting => 'user_scores_ldap_username',
4078 is_admin => 1,
4079 default => '',
4080 type => $CONF_TYPE_STRING,
4081 });
4082
4083=item user_scores_ldap_password
4084
4085This is the password used to connect to the LDAP server. It defaults
4086to the empty string ("").
4087
4088=cut
4089
409016µs push (@cmds, {
4091 setting => 'user_scores_ldap_password',
4092 is_admin => 1,
4093 default => '',
4094 type => $CONF_TYPE_STRING,
4095 });
4096
4097=item user_scores_fallback_to_global (default: 1)
4098
4099Fall back to global scores and settings if userprefs can't be loaded
4100from SQL or LDAP, instead of passing the message through unprocessed.
4101
4102=cut
4103
410416µs push (@cmds, {
4105 setting => 'user_scores_fallback_to_global',
4106 is_admin => 1,
4107 default => 1,
4108 type => $CONF_TYPE_BOOL,
4109 });
4110
4111=item loadplugin PluginModuleName [/path/module.pm]
4112
4113Load a SpamAssassin plugin module. The C<PluginModuleName> is the perl module
4114name, used to create the plugin object itself.
4115
4116C</path/to/module.pm> is the file to load, containing the module's perl code;
4117if it's specified as a relative path, it's considered to be relative to the
4118current configuration file. If it is omitted, the module will be loaded
4119using perl's search path (the C<@INC> array).
4120
4121See C<Mail::SpamAssassin::Plugin> for more details on writing plugins.
4122
4123=cut
4124
4125 push (@cmds, {
4126 setting => 'loadplugin',
4127 is_admin => 1,
4128
# spent 510ms (2.13+508) within Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:4145] which was called 27 times, avg 18.9ms/call: # 27 times (2.13ms+508ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438 of Mail/SpamAssassin/Conf/Parser.pm, avg 18.9ms/call
code => sub {
412927168µs my ($self, $key, $value, $line) = @_;
41302766µs if ($value eq '') {
4131 return $MISSING_REQUIRED_VALUE;
4132 }
41332746µs my ($package, $path);
413427113µs local ($1,$2);
413527742µs54361µs if ($value =~ /^(\S+)\s+(\S+)$/) {
# spent 361µs making 54 calls to Mail::SpamAssassin::Conf::CORE:match, avg 7µs/call
4136 ($package, $path) = ($1, $2);
4137 } elsif ($value =~ /^\S+$/) {
41382788µs ($package, $path) = ($value, undef);
4139 } else {
4140 return $INVALID_VALUE;
4141 }
4142 # is blindly untainting safe? it is no worse than before
414327557µs541.04ms $_ = untaint_var($_) for ($package,$path);
# spent 1.04ms making 54 calls to Mail::SpamAssassin::Util::untaint_var, avg 19µs/call
414427603µs27507ms $self->load_plugin ($package, $path);
# spent 507ms making 27 calls to Mail::SpamAssassin::Conf::load_plugin, avg 18.8ms/call
4145 }
4146113µs });
4147
4148=item tryplugin PluginModuleName [/path/module.pm]
4149
4150Same as C<loadplugin>, but silently ignored if the .pm file cannot be found in
4151the filesystem.
4152
4153=cut
4154
4155 push (@cmds, {
4156 setting => 'tryplugin',
4157 is_admin => 1,
4158 code => sub {
4159 my ($self, $key, $value, $line) = @_;
4160 if ($value eq '') {
4161 return $MISSING_REQUIRED_VALUE;
4162 }
4163 my ($package, $path);
4164 local ($1,$2);
4165 if ($value =~ /^(\S+)\s+(\S+)$/) {
4166 ($package, $path) = ($1, $2);
4167 } elsif ($value =~ /^\S+$/) {
4168 ($package, $path) = ($value, undef);
4169 } else {
4170 return $INVALID_VALUE;
4171 }
4172 # is blindly untainting safe? it is no worse than before
4173 $_ = untaint_var($_) for ($package,$path);
4174 $self->load_plugin ($package, $path, 1);
4175 }
4176110µs });
4177
4178=item ignore_always_matching_regexps (Default: 0)
4179
4180Ignore any rule which contains a regexp which always matches.
4181Currently only catches regexps which contain '||', or which begin or
4182end with a '|'. Also ignore rules with C<some> combinatorial explosions.
4183
4184=cut
4185
418616µs push (@cmds, {
4187 setting => 'ignore_always_matching_regexps',
4188 is_admin => 1,
4189 default => 0,
4190 type => $CONF_TYPE_BOOL,
4191 });
4192
4193=back
4194
4195=head1 PREPROCESSING OPTIONS
4196
4197=over 4
4198
4199=item include filename
4200
4201Include configuration lines from C<filename>. Relative paths are considered
4202relative to the current configuration file or user preferences file.
4203
4204=item if (boolean perl expression)
4205
4206Used to support conditional interpretation of the configuration
4207file. Lines between this and a corresponding C<else> or C<endif> line
4208will be ignored unless the expression evaluates as true
4209(in the perl sense; that is, defined and non-0 and non-empty string).
4210
4211The conditional accepts a limited subset of perl for security -- just enough to
4212perform basic arithmetic comparisons. The following input is accepted:
4213
4214=over 4
4215
4216=item numbers, whitespace, arithmetic operations and grouping
4217
4218Namely these characters and ranges:
4219
4220 ( ) - + * / _ . , < = > ! ~ 0-9 whitespace
4221
4222=item version
4223
4224This will be replaced with the version number of the currently-running
4225SpamAssassin engine. Note: The version used is in the internal SpamAssassin
4226version format which is C<x.yyyzzz>, where x is major version, y is minor
4227version, and z is maintenance version. So 3.0.0 is C<3.000000>, and 3.4.80
4228is C<3.004080>.
4229
4230=item perl_version
4231
4232(Introduced in 3.4.1) This will be replaced with the version number of the
4233currently-running perl engine. Note: The version used is in the $] version
4234format which is C<x.yyyzzz>, where x is major version, y is minor version,
4235and z is maintenance version. So 5.8.8 is C<5.008008>, and 5.10.0 is
4236C<5.010000>. Use to protect rules that incorporate RE syntax elements
4237introduced in later versions of perl, such as the C<++> non-backtracking
4238match introduced in perl 5.10. For example:
4239
4240 # Avoid lint error on older perl installs
4241 # Check SA version first to avoid warnings on checking perl_version on older SA
4242 if version > 3.004001 && perl_version >= 5.018000
4243 body INVALID_RE_SYNTAX_IN_PERL_BEFORE_5_18 /(?[ \p{Thai} & \p{Digit} ])/
4244 endif
4245
4246Note that the above will still generate a warning on perl older than 5.10.0;
4247to avoid that warning do this instead:
4248
4249 # Avoid lint error on older perl installs
4250 if can(Mail::SpamAssassin::Conf::perl_min_version_5010000)
4251 body INVALID_RE_SYNTAX_IN_PERL_5_8 /\w++/
4252 endif
4253
4254Warning: a can() test is only defined for perl 5.10.0!
4255
4256
4257=item plugin(Name::Of::Plugin)
4258
4259This is a function call that returns C<1> if the plugin named
4260C<Name::Of::Plugin> is loaded, or C<undef> otherwise.
4261
4262=item has(Name::Of::Package::function_name)
4263
4264This is a function call that returns C<1> if the perl package named
4265C<Name::Of::Package> includes a function called C<function_name>, or C<undef>
4266otherwise. Note that packages can be SpamAssassin plugins or built-in classes,
4267there's no difference in this respect. Internally this invokes UNIVERSAL::can.
4268
4269=item can(Name::Of::Package::function_name)
4270
4271This is a function call that returns C<1> if the perl package named
4272C<Name::Of::Package> includes a function called C<function_name>
4273B<and> that function returns a true value when called with no arguments,
4274otherwise C<undef> is returned.
4275
4276Is similar to C<has>, except that it also calls the named function,
4277testing its return value (unlike the perl function UNIVERSAL::can).
4278This makes it possible for a 'feature' function to determine its result
4279value at run time.
4280
4281=back
4282
4283If the end of a configuration file is reached while still inside a
4284C<if> scope, a warning will be issued, but parsing will restart on
4285the next file.
4286
4287For example:
4288
4289 if (version > 3.000000)
4290 header MY_FOO ...
4291 endif
4292
4293 loadplugin MyPlugin plugintest.pm
4294
4295 if plugin (MyPlugin)
4296 header MY_PLUGIN_FOO eval:check_for_foo()
4297 score MY_PLUGIN_FOO 0.1
4298 endif
4299
4300=item ifplugin PluginModuleName
4301
4302An alias for C<if plugin(PluginModuleName)>.
4303
4304=item else
4305
4306Used to support conditional interpretation of the configuration
4307file. Lines between this and a corresponding C<endif> line,
4308will be ignored unless the conditional expression evaluates as false
4309(in the perl sense; that is, not defined and not 0 and non-empty string).
4310
4311=item require_version n.nnnnnn
4312
4313Indicates that the entire file, from this line on, requires a certain
4314version of SpamAssassin to run. If a different (older or newer) version
4315of SpamAssassin tries to read the configuration from this file, it will
4316output a warning instead, and ignore it.
4317
4318Note: The version used is in the internal SpamAssassin version format which is
4319C<x.yyyzzz>, where x is major version, y is minor version, and z is maintenance
4320version. So 3.0.0 is C<3.000000>, and 3.4.80 is C<3.004080>.
4321
4322=cut
4323
4324 push (@cmds, {
4325 setting => 'require_version',
4326 type => $CONF_TYPE_STRING,
4327 code => sub {
4328 }
432918µs });
4330
4331=back
4332
4333=head1 TEMPLATE TAGS
4334
4335The following C<tags> can be used as placeholders in certain options.
4336They will be replaced by the corresponding value when they are used.
4337
4338Some tags can take an argument (in parentheses). The argument is
4339optional, and the default is shown below.
4340
4341 _YESNO_ "Yes" for spam, "No" for nonspam (=ham)
4342 _YESNO(spam_str,ham_str)_ returns the first argument ("Yes" if missing)
4343 for spam, and the second argument ("No" if missing) for ham
4344 _YESNOCAPS_ "YES" for spam, "NO" for nonspam (=ham)
4345 _YESNOCAPS(spam_str,ham_str)_ same as _YESNO(...)_, but uppercased
4346 _SCORE(PAD)_ message score, if PAD is included and is either spaces or
4347 zeroes, then pad scores with that many spaces or zeroes
4348 (default, none) ie: _SCORE(0)_ makes 2.4 become 02.4,
4349 _SCORE(00)_ is 002.4. 12.3 would be 12.3 and 012.3
4350 respectively.
4351 _REQD_ message threshold
4352 _VERSION_ version (eg. 3.0.0 or 3.1.0-r26142-foo1)
4353 _SUBVERSION_ sub-version/code revision date (eg. 2004-01-10)
4354 _RULESVERSION_ comma-separated list of rules versions, retrieved from
4355 an '# UPDATE version' comment in rules files; if there is
4356 more than one set of rules (update channels) the order
4357 is unspecified (currently sorted by names of files);
4358 _HOSTNAME_ hostname of the machine the mail was processed on
4359 _REMOTEHOSTNAME_ hostname of the machine the mail was sent from, only
4360 available with spamd
4361 _REMOTEHOSTADDR_ ip address of the machine the mail was sent from, only
4362 available with spamd
4363 _BAYES_ bayes score
4364 _TOKENSUMMARY_ number of new, neutral, spammy, and hammy tokens found
4365 _BAYESTC_ number of new tokens found
4366 _BAYESTCLEARNED_ number of seen tokens found
4367 _BAYESTCSPAMMY_ number of spammy tokens found
4368 _BAYESTCHAMMY_ number of hammy tokens found
4369 _HAMMYTOKENS(N)_ the N most significant hammy tokens (default, 5)
4370 _SPAMMYTOKENS(N)_ the N most significant spammy tokens (default, 5)
4371 _DATE_ rfc-2822 date of scan
4372 _STARS(*)_ one "*" (use any character) for each full score point
4373 (note: limited to 50 'stars')
4374 _SENDERDOMAIN_ a domain name of the envelope sender address, lowercased
4375 _AUTHORDOMAIN_ a domain name of the author address (the From header
4376 field), lowercased; note that RFC 5322 allows a mail
4377 message to have multiple authors - currently only the
4378 domain name of the first email address is returned
4379 _RELAYSTRUSTED_ relays used and deemed to be trusted (see the
4380 'X-Spam-Relays-Trusted' pseudo-header)
4381 _RELAYSUNTRUSTED_ relays used that can not be trusted (see the
4382 'X-Spam-Relays-Untrusted' pseudo-header)
4383 _RELAYSINTERNAL_ relays used and deemed to be internal (see the
4384 'X-Spam-Relays-Internal' pseudo-header)
4385 _RELAYSEXTERNAL_ relays used and deemed to be external (see the
4386 'X-Spam-Relays-External' pseudo-header)
4387 _LASTEXTERNALIP_ IP address of client in the external-to-internal
4388 SMTP handover
4389 _LASTEXTERNALRDNS_ reverse-DNS of client in the external-to-internal
4390 SMTP handover
4391 _LASTEXTERNALHELO_ HELO string used by client in the external-to-internal
4392 SMTP handover
4393 _AUTOLEARN_ autolearn status ("ham", "no", "spam", "disabled",
4394 "failed", "unavailable")
4395 _AUTOLEARNSCORE_ portion of message score used by autolearn
4396 _TESTS(,)_ tests hit separated by "," (or other separator)
4397 _TESTSSCORES(,)_ as above, except with scores appended (eg. AWL=-3.0,...)
4398 _SUBTESTS(,)_ subtests (start with "__") hit separated by ","
4399 (or other separator)
4400 _DCCB_ DCC's "Brand"
4401 _DCCR_ DCC's results
4402 _PYZOR_ Pyzor results
4403 _RBL_ full results for positive RBL queries in DNS URI format
4404 _LANGUAGES_ possible languages of mail
4405 _PREVIEW_ content preview
4406 _REPORT_ terse report of tests hit (for header reports)
4407 _SUMMARY_ summary of tests hit for standard report (for body reports)
4408 _CONTACTADDRESS_ contents of the 'report_contact' setting
4409 _HEADER(NAME)_ includes the value of a message header. value is the same
4410 as is found for header rules (see elsewhere in this doc)
4411 _TIMING_ timing breakdown report
4412 _ADDEDHEADERHAM_ resulting header fields as requested by add_header for spam
4413 _ADDEDHEADERSPAM_ resulting header fields as requested by add_header for ham
4414 _ADDEDHEADER_ same as ADDEDHEADERHAM for ham or ADDEDHEADERSPAM for spam
4415
4416If a tag reference uses the name of a tag which is not in this list or defined
4417by a loaded plugin, the reference will be left intact and not replaced by any
4418value.
4419
4420The C<HAMMYTOKENS> and C<SPAMMYTOKENS> tags have an optional second argument
4421which specifies a format. See the B<HAMMYTOKENS/SPAMMYTOKENS TAG FORMAT>
4422section, below, for details.
4423
4424=head2 HAMMYTOKENS/SPAMMYTOKENS TAG FORMAT
4425
4426The C<HAMMYTOKENS> and C<SPAMMYTOKENS> tags have an optional second argument
4427which specifies a format: C<_SPAMMYTOKENS(N,FMT)_>, C<_HAMMYTOKENS(N,FMT)_>
4428The following formats are available:
4429
4430=over 4
4431
4432=item short
4433
4434Only the tokens themselves are listed.
4435I<For example, preference file entry:>
4436
4437C<add_header all Spammy _SPAMMYTOKENS(2,short)_>
4438
4439I<Results in message header:>
4440
4441C<X-Spam-Spammy: remove.php, UD:jpg>
4442
4443Indicating that the top two spammy tokens found are C<remove.php>
4444and C<UD:jpg>. (The token itself follows the last colon, the
4445text before the colon indicates something about the token.
4446C<UD> means the token looks like it might be part of a domain name.)
4447
4448=item compact
4449
4450The token probability, an abbreviated declassification distance (see
4451example), and the token are listed.
4452I<For example, preference file entry:>
4453
4454C<add_header all Spammy _SPAMMYTOKENS(2,compact)_>
4455
4456I<Results in message header:>
4457
4458C<0.989-6--remove.php, 0.988-+--UD:jpg>
4459
4460Indicating that the probabilities of the top two tokens are 0.989 and
44610.988, respectively. The first token has a declassification distance
4462of 6, meaning that if the token had appeared in at least 6 more ham
4463messages it would not be considered spammy. The C<+> for the second
4464token indicates a declassification distance greater than 9.
4465
4466=item long
4467
4468Probability, declassification distance, number of times seen in a ham
4469message, number of times seen in a spam message, age and the token are
4470listed.
4471
4472I<For example, preference file entry:>
4473
4474C<add_header all Spammy _SPAMMYTOKENS(2,long)_>
4475
4476I<Results in message header:>
4477
4478C<X-Spam-Spammy: 0.989-6--0h-4s--4d--remove.php, 0.988-33--2h-25s--1d--UD:jpg>
4479
4480In addition to the information provided by the compact option,
4481the long option shows that the first token appeared in zero
4482ham messages and four spam messages, and that it was last
4483seen four days ago. The second token appeared in two ham messages,
448425 spam messages and was last seen one day ago.
4485(Unlike the C<compact> option, the long option shows declassification
4486distances that are greater than 9.)
4487
4488=back
4489
4490=cut
4491
4492131µs return \@cmds;
4493}
4494
4495###########################################################################
4496
4497# settings that were once part of core, but are now in (possibly-optional)
4498# bundled plugins. These will be warned about, but do not generate a fatal
4499# error when "spamassassin --lint" is run like a normal syntax error would.
4500
450113µs@MIGRATED_SETTINGS = qw{
4502 ok_languages
4503};
4504
4505###########################################################################
4506
4507
# spent 29.8ms (350µs+29.5) within Mail::SpamAssassin::Conf::new which was called: # once (350µs+29.5ms) by Mail::SpamAssassin::new at line 431 of Mail/SpamAssassin.pm
sub new {
450812µs my $class = shift;
450912µs $class = ref($class) || $class;
451016µs my $self = {
4511 main => shift,
4512 registered_commands => [],
451312µs }; bless ($self, $class);
4514
4515120µs130µs $self->{parser} = Mail::SpamAssassin::Conf::Parser->new($self);
# spent 30µs making 1 call to Mail::SpamAssassin::Conf::Parser::new
4516128µs222.7ms $self->{parser}->register_commands($self->set_default_commands());
# spent 20.4ms making 1 call to Mail::SpamAssassin::Conf::set_default_commands # spent 2.28ms making 1 call to Mail::SpamAssassin::Conf::Parser::register_commands
4517
451814µs $self->{errors} = 0;
451913µs $self->{plugins_loaded} = { };
4520
452113µs $self->{tests} = { };
452216µs $self->{test_types} = { };
452318µs $self->{scoreset} = [ {}, {}, {}, {} ];
452413µs $self->{scoreset_current} = 0;
4525110µs140µs $self->set_score_set (0);
# spent 40µs making 1 call to Mail::SpamAssassin::Conf::set_score_set
452613µs $self->{tflags} = { };
452713µs $self->{source_file} = { };
4528
4529 # keep descriptions in a slow but space-efficient single-string
4530 # data structure
4531235µs115µs tie %{$self->{descriptions}}, 'Mail::SpamAssassin::Util::TieOneStringHash'
4532 or warn "tie failed";
4533
4534 # after parsing, tests are refiled into these hashes for each test type.
4535 # this allows e.g. a full-text test to be rewritten as a body test in
4536 # the user's user_prefs file.
453714µs $self->{body_tests} = { };
453813µs $self->{uri_tests} = { };
453913µs $self->{uri_evals} = { }; # not used/implemented yet
454013µs $self->{head_tests} = { };
454113µs $self->{head_evals} = { };
454213µs $self->{body_evals} = { };
454313µs $self->{full_tests} = { };
454413µs $self->{full_evals} = { };
454513µs $self->{rawbody_tests} = { };
454613µs $self->{rawbody_evals} = { };
454713µs $self->{meta_tests} = { };
454813µs $self->{eval_plugins} = { };
454914µs $self->{duplicate_rules} = { };
4550
4551 # testing stuff
455214µs $self->{regression_tests} = { };
4553
455413µs $self->{rewrite_header} = { };
455513µs $self->{want_rebuild_for_type} = { };
455613µs $self->{user_defined_rules} = { };
455713µs $self->{headers_spam} = [ ];
455813µs $self->{headers_ham} = [ ];
4559
456013µs $self->{bayes_ignore_headers} = [ ];
456113µs $self->{bayes_ignore_from} = { };
456212µs $self->{bayes_ignore_to} = { };
4563
456413µs $self->{whitelist_auth} = { };
456512µs $self->{def_whitelist_auth} = { };
456612µs $self->{whitelist_from} = { };
456712µs $self->{whitelist_allows_relays} = { };
456812µs $self->{blacklist_from} = { };
456913µs $self->{whitelist_from_rcvd} = { };
457012µs $self->{def_whitelist_from_rcvd} = { };
4571
457212µs $self->{blacklist_to} = { };
457312µs $self->{whitelist_to} = { };
457413µs $self->{more_spam_to} = { };
457512µs $self->{all_spam_to} = { };
4576
4577111µs14.43ms $self->{trusted_networks} = $self->new_netset('trusted_networks',1);
# spent 4.43ms making 1 call to Mail::SpamAssassin::Conf::new_netset
457819µs12.24ms $self->{internal_networks} = $self->new_netset('internal_networks',1);
# spent 2.24ms making 1 call to Mail::SpamAssassin::Conf::new_netset
457918µs166µs $self->{msa_networks} = $self->new_netset('msa_networks',0); # no loopback IP
# spent 66µs making 1 call to Mail::SpamAssassin::Conf::new_netset
458013µs $self->{trusted_networks_configured} = 0;
458113µs $self->{internal_networks_configured} = 0;
4582
4583 # Make sure we add in X-Spam-Checker-Version
458427µs { my $r = [ "Checker-Version",
4585 "SpamAssassin _VERSION_ (_SUBVERSION_) on _HOSTNAME_" ];
458627µs push(@{$self->{headers_spam}}, $r);
458727µs push(@{$self->{headers_ham}}, $r);
4588 }
4589
4590 # RFC 6891: A good compromise may be the use of an EDNS maximum payload size
4591 # of 4096 octets as a starting point.
459214µs $self->{dns_options}->{edns} = 4096;
4593
4594 # these should potentially be settable by end-users
4595 # perhaps via plugin?
459612µs $self->{num_check_received} = 9;
459713µs $self->{bayes_expiry_pct} = 0.75;
459813µs $self->{bayes_expiry_period} = 43200;
459912µs $self->{bayes_expiry_max_exponent} = 9;
4600
460113µs $self->{encapsulated_content_description} = 'original message before SpamAssassin';
4602
4603110µs $self;
4604}
4605
4606sub mtime {
4607 my $self = shift;
4608 if (@_) {
4609 $self->{mtime} = shift;
4610 }
4611 return $self->{mtime};
4612}
4613
4614###########################################################################
4615
4616sub parse_scores_only {
4617 my ($self) = @_;
4618 $_[0]->{parser}->parse ($_[1], 1);
4619}
4620
4621
# spent 5.03s (24µs+5.03) within Mail::SpamAssassin::Conf::parse_rules which was called: # once (24µs+5.03s) by Mail::SpamAssassin::init at line 1759 of Mail/SpamAssassin.pm
sub parse_rules {
462212µs my ($self) = @_;
4623123µs15.03s $_[0]->{parser}->parse ($_[1], 0);
# spent 5.03s making 1 call to Mail::SpamAssassin::Conf::Parser::parse
4624}
4625
4626###########################################################################
4627
4628
# spent 86µs (67+19) within Mail::SpamAssassin::Conf::set_score_set which was called 2 times, avg 43µs/call: # once (38µs+7µs) by Mail::SpamAssassin::init at line 1781 of Mail/SpamAssassin.pm # once (28µs+12µs) by Mail::SpamAssassin::Conf::new at line 4525
sub set_score_set {
462925µs my ($self, $set) = @_;
4630212µs $self->{scores} = $self->{scoreset}->[$set];
463126µs $self->{scoreset_current} = $set;
4632239µs219µs dbg("config: score set $set chosen.");
# spent 19µs making 2 calls to Mail::SpamAssassin::Logger::dbg, avg 9µs/call
4633}
4634
4635sub get_score_set {
4636 my($self) = @_;
4637 return $self->{scoreset_current};
4638}
4639
4640sub get_rule_types {
4641 my ($self) = @_;
4642 return @rule_types;
4643}
4644
4645sub get_rule_keys {
4646 my ($self, $test_type, $priority) = @_;
4647
4648 # special case rbl_evals since they do not have a priority
4649 if ($test_type eq 'rbl_evals') {
4650 return keys(%{$self->{$test_type}});
4651 }
4652
4653 if (defined($priority)) {
4654 return keys(%{$self->{$test_type}->{$priority}});
4655 }
4656 else {
4657 my @rules;
4658 foreach my $pri (keys(%{$self->{priorities}})) {
4659 push(@rules, keys(%{$self->{$test_type}->{$pri}}));
4660 }
4661 return @rules;
4662 }
4663}
4664
4665sub get_rule_value {
4666 my ($self, $test_type, $rulename, $priority) = @_;
4667
4668 # special case rbl_evals since they do not have a priority
4669 if ($test_type eq 'rbl_evals') {
4670 return keys(%{$self->{$test_type}->{$rulename}});
4671 }
4672
4673 if (defined($priority)) {
4674 return $self->{$test_type}->{$priority}->{$rulename};
4675 }
4676 else {
4677 foreach my $pri (keys(%{$self->{priorities}})) {
4678 if (exists($self->{$test_type}->{$pri}->{$rulename})) {
4679 return $self->{$test_type}->{$pri}->{$rulename};
4680 }
4681 }
4682 return; # if we get here we didn't find the rule
4683 }
4684}
4685
4686sub delete_rule {
4687 my ($self, $test_type, $rulename, $priority) = @_;
4688
4689 # special case rbl_evals since they do not have a priority
4690 if ($test_type eq 'rbl_evals') {
4691 return delete($self->{$test_type}->{$rulename});
4692 }
4693
4694 if (defined($priority)) {
4695 return delete($self->{$test_type}->{$priority}->{$rulename});
4696 }
4697 else {
4698 foreach my $pri (keys(%{$self->{priorities}})) {
4699 if (exists($self->{$test_type}->{$pri}->{$rulename})) {
4700 return delete($self->{$test_type}->{$pri}->{$rulename});
4701 }
4702 }
4703 return; # if we get here we didn't find the rule
4704 }
4705}
4706
4707# trim_rules ($regexp)
4708#
4709# Remove all rules that don't match the given regexp (or are sub-rules of
4710# meta-tests that match the regexp).
4711
4712sub trim_rules {
4713 my ($self, $regexp) = @_;
4714
4715 my @all_rules;
4716
4717 foreach my $rule_type ($self->get_rule_types()) {
4718 push(@all_rules, $self->get_rule_keys($rule_type));
4719 }
4720
4721 my @rules_to_keep = grep(/$regexp/, @all_rules);
4722
4723 if (@rules_to_keep == 0) {
4724 die "config: trim_rules: all rules excluded, nothing to test\n";
4725 }
4726
4727 my @meta_tests = grep(/$regexp/, $self->get_rule_keys('meta_tests'));
4728 foreach my $meta (@meta_tests) {
4729 push(@rules_to_keep, $self->add_meta_depends($meta))
4730 }
4731
4732 my %rules_to_keep_hash;
4733
4734 foreach my $rule (@rules_to_keep) {
4735 $rules_to_keep_hash{$rule} = 1;
4736 }
4737
4738 foreach my $rule_type ($self->get_rule_types()) {
4739 foreach my $rulekey ($self->get_rule_keys($rule_type)) {
4740 $self->delete_rule($rule_type, $rulekey)
4741 if (!$rules_to_keep_hash{$rulekey});
4742 }
4743 }
4744} # trim_rules()
4745
4746sub add_meta_depends {
4747 my ($self, $meta) = @_;
4748
4749 my @rules;
4750 my @tokens = $self->get_rule_value('meta_tests', $meta) =~ m/(\w+)/g;
4751
4752 @tokens = grep(!/^\d+$/, @tokens);
4753 # @tokens now only consists of sub-rules
4754
4755 foreach my $token (@tokens) {
4756 die "config: meta test $meta depends on itself\n" if $token eq $meta;
4757 push(@rules, $token);
4758
4759 # If the sub-rule is a meta-test, recurse
4760 if ($self->get_rule_value('meta_tests', $token)) {
4761 push(@rules, $self->add_meta_depends($token));
4762 }
4763 } # foreach my $token (@tokens)
4764
4765 return @rules;
4766} # add_meta_depends()
4767
4768
# spent 244ms within Mail::SpamAssassin::Conf::is_rule_active which was called 5382 times, avg 45µs/call: # 5382 times (244ms+0s) by Mail::SpamAssassin::Plugin::URIDNSBL::parsed_metadata at line 368 of Mail/SpamAssassin/Plugin/URIDNSBL.pm, avg 45µs/call
sub is_rule_active {
4769538211.4ms my ($self, $test_type, $rulename, $priority) = @_;
4770
4771 # special case rbl_evals since they do not have a priority
477253829.63ms if ($test_type eq 'rbl_evals') {
4773 return 0 unless ($self->{$test_type}->{$rulename});
4774 return ($self->{scores}->{$rulename});
4775 }
4776
4777 # first determine if the rule is defined
4778538217.3ms if (defined($priority)) {
4779 # we have a specific priority
4780 return 0 unless ($self->{$test_type}->{$priority}->{$rulename});
4781 }
4782 else {
4783 # no specific priority so we must loop over all currently defined
4784 # priorities to see if the rule is defined
478553829.58ms my $found_p = 0;
47861076438.3ms foreach my $pri (keys %{$self->{priorities}}) {
4787538252.6ms if ($self->{$test_type}->{$pri}->{$rulename}) {
478853828.74ms $found_p = 1;
4789538224.9ms last;
4790 }
4791 }
479253828.99ms return 0 unless ($found_p);
4793 }
4794
4795538290.9ms return ($self->{scores}->{$rulename});
4796}
4797
4798###########################################################################
4799
4800# treats a bitset argument as a bit vector of all possible port numbers (8 kB)
4801# and sets bit values to $value (0 or 1) in the specified range of port numbers
4802#
4803
# spent 80.1ms (80.1+22µs) within Mail::SpamAssassin::Conf::set_ports_range which was called 190 times, avg 422µs/call: # 190 times (80.1ms+22µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1685] at line 1683, avg 422µs/call
sub set_ports_range {
4804190887µs my($bitset_ref, $port_range_lo, $port_range_hi, $value) = @_;
4805190365µs $port_range_lo = 0 if $port_range_lo < 0;
4806190320µs $port_range_hi = 65535 if $port_range_hi > 65535;
4807190337µs if (!defined $$bitset_ref) { # provide a sensible default
480819µs122µs wipe_ports_range($bitset_ref, 1); # turn on all bits 0..65535
# spent 22µs making 1 call to Mail::SpamAssassin::Conf::wipe_ports_range
480912.55ms vec($$bitset_ref,$_,1) = 0 for 0..1023; # avoid 0 and privileged ports
4810 } elsif ($$bitset_ref eq '') { # repopulate the bitset (late configuration)
4811 wipe_ports_range($bitset_ref, 0); # turn off all bits 0..65535
4812 }
4813190319µs $value = !$value ? 0 : 1;
481419045.9ms for (my $j = $port_range_lo; $j <= $port_range_hi; $j++) {
48151157829.7ms vec($$bitset_ref,$j,1) = $value;
4816 }
4817}
4818
4819
# spent 22µs within Mail::SpamAssassin::Conf::wipe_ports_range which was called: # once (22µs+0s) by Mail::SpamAssassin::Conf::set_ports_range at line 4808
sub wipe_ports_range {
482012µs my($bitset_ref, $value) = @_;
482114µs $value = !$value ? "\000" : "\377";
4822119µs $$bitset_ref = $value x 8192; # quickly turn all bits 0..65535 on or off
4823}
4824
4825###########################################################################
4826
4827sub add_to_addrlist {
4828 my $self = shift; $self->{parser}->add_to_addrlist(@_);
4829}
4830sub add_to_addrlist_rcvd {
4831 my $self = shift; $self->{parser}->add_to_addrlist_rcvd(@_);
4832}
4833sub remove_from_addrlist {
4834 my $self = shift; $self->{parser}->remove_from_addrlist(@_);
4835}
4836sub remove_from_addrlist_rcvd {
4837 my $self = shift; $self->{parser}->remove_from_addrlist_rcvd(@_);
4838}
4839
4840###########################################################################
4841
4842sub regression_tests {
4843 my $self = shift;
4844 if (@_ == 1) {
4845 # we specified a symbolic name, return the strings
4846 my $name = shift;
4847 my $tests = $self->{regression_tests}->{$name};
4848 return @$tests;
4849 }
4850 else {
4851 # no name asked for, just return the symbolic names we have tests for
4852 return keys %{$self->{regression_tests}};
4853 }
4854}
4855
4856###########################################################################
4857
4858
# spent 7.67s (31µs+7.67) within Mail::SpamAssassin::Conf::finish_parsing which was called: # once (31µs+7.67s) by Mail::SpamAssassin::init at line 1760 of Mail/SpamAssassin.pm
sub finish_parsing {
485912µs my ($self, $user) = @_;
4860121µs17.67s $self->{parser}->finish_parsing($user);
# spent 7.67s making 1 call to Mail::SpamAssassin::Conf::Parser::finish_parsing
4861}
4862
4863###########################################################################
4864
4865
# spent 28µs within Mail::SpamAssassin::Conf::found_any_rules which was called: # once (28µs+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 947 of Mail/SpamAssassin/Conf/Parser.pm
sub found_any_rules {
486613µs my ($self) = @_;
486716µs if (!defined $self->{found_any_rules}) {
4868211µs $self->{found_any_rules} = (scalar keys %{$self->{tests}} > 0);
4869 }
4870112µs return $self->{found_any_rules};
4871}
4872
4873###########################################################################
4874
4875sub get_description_for_rule {
4876 my ($self, $rule) = @_;
4877 # as silly as it looks, localized $1 here prevents an outer $1 from getting
4878 # tainted by the expression or assignment in the next line, bug 6148
4879 local($1);
4880 my $rule_descr = $self->{descriptions}->{$rule};
4881 return $rule_descr;
4882}
4883
4884###########################################################################
4885
4886sub maybe_header_only {
4887 my($self,$rulename) = @_;
4888 my $type = $self->{test_types}->{$rulename};
4889
4890 if ($rulename =~ /AUTOLEARNTEST/i) {
4891 dbg("config: auto-learn: $rulename - Test type is $self->{test_types}->{$rulename}.");
4892 }
4893
4894 return 0 if (!defined ($type));
4895
4896 if (($type == $TYPE_HEAD_TESTS) || ($type == $TYPE_HEAD_EVALS)) {
4897 return 1;
4898
4899 } elsif ($type == $TYPE_META_TESTS) {
4900 my $tflags = $self->{tflags}->{$rulename};
4901 $tflags ||= '';
4902 if ($tflags =~ m/\bnet\b/i) {
4903 return 0;
4904 } else {
4905 return 1;
4906 }
4907 }
4908
4909 return 0;
4910}
4911
4912sub maybe_body_only {
4913 my($self,$rulename) = @_;
4914 my $type = $self->{test_types}->{$rulename};
4915
4916 if ($rulename =~ /AUTOLEARNTEST/i) {
4917 dbg("config: auto-learn: $rulename - Test type is $self->{test_types}->{$rulename}.");
4918 }
4919
4920 return 0 if (!defined ($type));
4921
4922 if (($type == $TYPE_BODY_TESTS) || ($type == $TYPE_BODY_EVALS)
4923 || ($type == $TYPE_URI_TESTS) || ($type == $TYPE_URI_EVALS))
4924 {
4925 # some rawbody go off of headers...
4926 return 1;
4927
4928 } elsif ($type == $TYPE_META_TESTS) {
4929 my $tflags = $self->{tflags}->{$rulename}; $tflags ||= '';
4930 if ($tflags =~ m/\bnet\b/i) {
4931 return 0;
4932 } else {
4933 return 1;
4934 }
4935 }
4936
4937 return 0;
4938}
4939
4940###########################################################################
4941
4942
# spent 507ms (701µs+506) within Mail::SpamAssassin::Conf::load_plugin which was called 27 times, avg 18.8ms/call: # 27 times (701µs+506ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:4145] at line 4144, avg 18.8ms/call
sub load_plugin {
49432794µs my ($self, $package, $path, $silent) = @_;
49442748µs if ($path) {
4945 $path = $self->{parser}->fix_path_relative_to_current_file($path);
4946 }
4947 # it wouldn't hurt to do some checking on validity of $package
4948 # and $path before untainting them
494927530µs54506ms $self->{main}->{plugins}->load_plugin(untaint_var($package), $path, $silent);
# spent 506ms making 27 calls to Mail::SpamAssassin::PluginHandler::load_plugin, avg 18.7ms/call # spent 612µs making 27 calls to Mail::SpamAssassin::Util::untaint_var, avg 23µs/call
4950}
4951
4952
# spent 304µs within Mail::SpamAssassin::Conf::load_plugin_succeeded which was called 27 times, avg 11µs/call: # 27 times (304µs+0s) by Mail::SpamAssassin::PluginHandler::load_plugin at line 137 of Mail/SpamAssassin/PluginHandler.pm, avg 11µs/call
sub load_plugin_succeeded {
49532787µs my ($self, $plugin, $package, $path) = @_;
495427263µs $self->{plugins_loaded}->{$package} = 1;
4955}
4956
4957
# spent 1.78ms within Mail::SpamAssassin::Conf::register_eval_rule which was called 192 times, avg 9µs/call: # 192 times (1.78ms+0s) by Mail::SpamAssassin::Plugin::register_eval_rule at line 1030 of Mail/SpamAssassin/Plugin.pm, avg 9µs/call
sub register_eval_rule {
4958192409µs my ($self, $pluginobj, $nameofsub) = @_;
49591921.81ms $self->{eval_plugins}->{$nameofsub} = $pluginobj;
4960}
4961
4962###########################################################################
4963
4964sub clone {
4965 my ($self, $source, $dest) = @_;
4966
4967 unless (defined $source) {
4968 $source = $self;
4969 }
4970 unless (defined $dest) {
4971 $dest = $self;
4972 }
4973
4974 my %done;
4975
4976 # keys that should not be copied in ->clone().
4977 # bug 4179: include want_rebuild_for_type, so that if a user rule
4978 # is defined, its method will be recompiled for future scans in
4979 # order to *remove* the generated method calls
4980 my @NON_COPIED_KEYS = qw(
4981 main eval_plugins plugins_loaded registered_commands sed_path_cache parser
4982 scoreset scores want_rebuild_for_type
4983 );
4984
4985 # special cases. first, skip anything that cannot be changed
4986 # by users, and the stuff we take care of here
4987 foreach my $var (@NON_COPIED_KEYS) {
4988 $done{$var} = undef;
4989 }
4990
4991 # keys that should can be copied using a ->clone() method, in ->clone()
4992 my @CLONABLE_KEYS = qw(
4993 internal_networks trusted_networks msa_networks
4994 );
4995
4996 foreach my $key (@CLONABLE_KEYS) {
4997 $dest->{$key} = $source->{$key}->clone();
4998 $done{$key} = undef;
4999 }
5000
5001 # two-level hashes
5002 foreach my $key (qw(uri_host_lists askdns)) {
5003 my $v = $source->{$key};
5004 my $dest_key_ref = $dest->{$key} = {}; # must start from scratch!
5005 while(my($k2,$v2) = each %{$v}) {
5006 %{$dest_key_ref->{$k2}} = %{$v2};
5007 }
5008 $done{$key} = undef;
5009 }
5010
5011 # bug 4179: be smarter about cloning the rule-type structures;
5012 # some are like this: $self->{type}->{priority}->{name} = 'value';
5013 # which is an extra level that the below code won't deal with
5014 foreach my $t (@rule_types) {
5015 foreach my $k (keys %{$source->{$t}}) {
5016 my $v = $source->{$t}->{$k};
5017 my $i = ref $v;
5018 if ($i eq 'HASH') {
5019 %{$dest->{$t}->{$k}} = %{$v};
5020 }
5021 elsif ($i eq 'ARRAY') {
5022 @{$dest->{$t}->{$k}} = @{$v};
5023 }
5024 else {
5025 $dest->{$t}->{$k} = $v;
5026 }
5027 }
5028 $done{$t} = undef;
5029 }
5030
5031 # and now, copy over all the rest -- the less complex cases.
5032 while(my($k,$v) = each %{$source}) {
5033 next if exists $done{$k}; # we handled it above
5034 $done{$k} = undef;
5035 my $i = ref($v);
5036
5037 # Not a reference, or a scalar? Just copy the value over.
5038 if ($i eq '') {
5039 $dest->{$k} = $v;
5040 }
5041 elsif ($i eq 'SCALAR') {
5042 $dest->{$k} = $$v;
5043 }
5044 elsif ($i eq 'ARRAY') {
5045 @{$dest->{$k}} = @{$v};
5046 }
5047 elsif ($i eq 'HASH') {
5048 %{$dest->{$k}} = %{$v};
5049 }
5050 else {
5051 # throw a warning for debugging -- should never happen in normal usage
5052 warn "config: dup unknown type $k, $i\n";
5053 }
5054 }
5055
5056 foreach my $cmd (@{$self->{registered_commands}}) {
5057 my $k = $cmd->{setting};
5058 next if exists $done{$k}; # we handled it above
5059 $done{$k} = undef;
5060 $dest->{$k} = $source->{$k};
5061 }
5062
5063 # scoresets
5064 delete $dest->{scoreset};
5065 for my $i (0 .. 3) {
5066 %{$dest->{scoreset}->[$i]} = %{$source->{scoreset}->[$i]};
5067 }
5068
5069 # deal with $conf->{scores}, it needs to be a reference into the scoreset
5070 # hash array dealy. Do it at the end since scoreset_current isn't set
5071 # otherwise.
5072 $dest->{scores} = $dest->{scoreset}->[$dest->{scoreset_current}];
5073
5074 # ensure we don't copy the path cache from the master
5075 delete $dest->{sed_path_cache};
5076
5077 return 1;
5078}
5079
5080###########################################################################
5081
5082sub free_uncompiled_rule_source {
5083 my ($self) = @_;
5084
5085 if (!$self->{main}->{keep_config_parsing_metadata} &&
5086 !$self->{allow_user_rules})
5087 {
5088 delete $self->{if_stack};
5089 #delete $self->{source_file};
5090 #delete $self->{meta_dependencies};
5091 }
5092}
5093
5094
# spent 6.73ms (103µs+6.63) within Mail::SpamAssassin::Conf::new_netset which was called 3 times, avg 2.24ms/call: # once (53µs+4.38ms) by Mail::SpamAssassin::Conf::new at line 4577 # once (34µs+2.20ms) by Mail::SpamAssassin::Conf::new at line 4578 # once (16µs+50µs) by Mail::SpamAssassin::Conf::new at line 4579
sub new_netset {
509537µs my ($self, $netset_name, $add_loopback) = @_;
5096329µs3240µs my $set = Mail::SpamAssassin::NetSet->new($netset_name);
# spent 240µs making 3 calls to Mail::SpamAssassin::NetSet::new, avg 80µs/call
509738µs if ($add_loopback) {
5098216µs24.73ms $set->add_cidr('127.0.0.0/8');
# spent 4.73ms making 2 calls to Mail::SpamAssassin::NetSet::add_cidr, avg 2.36ms/call
5099214µs21.66ms $set->add_cidr('::1');
# spent 1.66ms making 2 calls to Mail::SpamAssassin::NetSet::add_cidr, avg 831µs/call
5100 }
5101326µs return $set;
5102}
5103
5104###########################################################################
5105
5106sub finish {
5107 my ($self) = @_;
5108 untie %{$self->{descriptions}};
5109 %{$self} = ();
5110}
5111
5112###########################################################################
5113
5114sub sa_die { Mail::SpamAssassin::sa_die(@_); }
5115
5116###########################################################################
5117
5118# subroutines available to conditionalize rules, for example:
5119# if (can(Mail::SpamAssassin::Conf::feature_originating_ip_headers))
5120
512119µs
# spent 10µs within Mail::SpamAssassin::Conf::feature_originating_ip_headers which was called: # once (10µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm
sub feature_originating_ip_headers { 1 }
5122110µs
# spent 8µs within Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid which was called: # once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm
sub feature_dns_local_ports_permit_avoid { 1 }
5123sub feature_bayes_auto_learn_on_error { 1 }
5124sub feature_uri_host_listed { 1 }
5125110µs
# spent 9µs within Mail::SpamAssassin::Conf::feature_yesno_takes_args which was called: # once (9µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm
sub feature_yesno_takes_args { 1 }
512624237µs
# spent 301µs within Mail::SpamAssassin::Conf::feature_bug6558_free which was called 24 times, avg 13µs/call: # 24 times (301µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm, avg 13µs/call
sub feature_bug6558_free { 1 }
5127sub feature_edns { 1 } # supports 'dns_options edns' config option
5128sub feature_dns_query_restriction { 1 } # supported config option
5129220µs
# spent 19µs within Mail::SpamAssassin::Conf::feature_registryboundaries which was called 2 times, avg 10µs/call: # 2 times (19µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm, avg 10µs/call
sub feature_registryboundaries { 1 } # replaces deprecated registrarboundaries
5130766µs
# spent 70µs within Mail::SpamAssassin::Conf::perl_min_version_5010000 which was called 7 times, avg 10µs/call: # 7 times (70µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 595 of Mail/SpamAssassin/Conf/Parser.pm, avg 10µs/call
sub perl_min_version_5010000 { return $] >= 5.010000 } # perl version check ("perl_version" not neatly backwards-compatible)
5131
5132###########################################################################
5133
5134132µs1;
5135__END__
 
# spent 35µs within Mail::SpamAssassin::Conf::CORE:ftdir which was called: # once (35µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3835] at line 3831
sub Mail::SpamAssassin::Conf::CORE:ftdir; # opcode
# spent 31.7ms within Mail::SpamAssassin::Conf::CORE:match which was called 7701 times, avg 4µs/call: # 2323 times (10.6ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:280] at line 252, avg 5µs/call # 1387 times (4.82ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2951, avg 3µs/call # 811 times (2.10ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:280] at line 239, avg 3µs/call # 655 times (2.78ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3010, avg 4µs/call # 465 times (1.46ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3174] at line 3169, avg 3µs/call # 459 times (2.99ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3750] at line 3744, avg 7µs/call # 459 times (1.77ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3750] at line 3741, avg 4µs/call # 247 times (847µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1685] at line 1669, avg 3µs/call # 175 times (637µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2954, avg 4µs/call # 128 times (1.09ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3557] at line 3550, avg 9µs/call # 128 times (326µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3557] at line 3547, avg 3µs/call # 116 times (513µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2964, avg 4µs/call # 77 times (401µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] at line 3198, avg 5µs/call # 54 times (361µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:4145] at line 4135, avg 7µs/call # 48 times (235µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3781] at line 3775, avg 5µs/call # 48 times (154µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3781] at line 3772, avg 3µs/call # 40 times (149µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3079, avg 4µs/call # 19 times (67µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] at line 428, avg 4µs/call # 19 times (48µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] at line 425, avg 3µs/call # 15 times (95µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2694, avg 6µs/call # 13 times (74µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3113, avg 6µs/call # 5 times (72µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] at line 906, avg 14µs/call # 5 times (15µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] at line 911, avg 3µs/call # 2 times (6µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1419] at line 1411, avg 3µs/call # once (8µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:1054] at line 1042 # once (7µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3858] at line 3856 # once (6µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3835] at line 3828
sub Mail::SpamAssassin::Conf::CORE:match; # opcode
# spent 103µs within Mail::SpamAssassin::Conf::CORE:qr which was called 15 times, avg 7µs/call: # 15 times (103µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2697, avg 7µs/call
sub Mail::SpamAssassin::Conf::CORE:qr; # opcode
# spent 584µs within Mail::SpamAssassin::Conf::CORE:regcomp which was called 15 times, avg 39µs/call: # 15 times (584µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2697, avg 39µs/call
sub Mail::SpamAssassin::Conf::CORE:regcomp; # opcode
# spent 5.10ms within Mail::SpamAssassin::Conf::CORE:subst which was called 2338 times, avg 2µs/call: # 2323 times (5.07ms+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:280] at line 249, avg 2µs/call # 5 times (13µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] at line 919, avg 3µs/call # 5 times (12µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] at line 921, avg 2µs/call # 5 times (11µs+0s) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:935] at line 920, avg 2µs/call
sub Mail::SpamAssassin::Conf::CORE:subst; # opcode