You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by km...@apache.org on 2015/04/29 19:04:11 UTC

svn commit: r1676792 [11/17] - in /spamassassin/site/full/3.4.x: ./ doc/

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Razor2.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Razor2.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Razor2.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Razor2.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,27 @@
+NAME
+    Mail::SpamAssassin::Plugin::Razor2 - perform Razor check of messages
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::Razor2
+
+DESCRIPTION
+    Vipul's Razor is a distributed, collaborative, spam detection and
+    filtering network based on user submissions of spam. Detection is done
+    with signatures that efficiently spot mutating spam content and user
+    input is validated through reputation assignments.
+
+    See http://razor.sourceforge.net/ for more information about Razor.
+
+USER SETTINGS
+    use_razor2 (0|1) (default: 1)
+        Whether to use Razor2, if it is available.
+
+ADMINISTRATOR SETTINGS
+    razor_timeout n (default: 5)
+        How many seconds you wait for Razor to complete before you go on
+        without the results
+
+    razor_config filename
+        Define the filename used to store Razor's configuration settings.
+        Currently this is left to Razor to decide.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,56 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RelayCountry - add message metadata indicating the country code of each relay</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+	<li><a href="#requirement">REQUIREMENT</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>RelayCountry - add message metadata indicating the country code of each relay</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::RelayCountry</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>The RelayCountry plugin attempts to determine the domain country codes
+of each relay used in the delivery path of messages and add that information
+to the message metadata as &quot;X-Relay-Countries&quot;, or the <code>_RELAYCOUNTRY_</code>
+header markup.</p>
+<p>
+</p>
+<hr />
+<h1><a name="requirement">REQUIREMENT</a></h1>
+<p>This plugin requires the Geo::IP module from CPAN. For backward
+compatibility IP::Country::Fast is used if Geo::IP is not installed.</p>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_RelayCountry.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,17 @@
+NAME
+    RelayCountry - add message metadata indicating the country code of each
+    relay
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::RelayCountry
+
+DESCRIPTION
+    The RelayCountry plugin attempts to determine the domain country codes
+    of each relay used in the delivery path of messages and add that
+    information to the message metadata as "X-Relay-Countries", or the
+    "_RELAYCOUNTRY_" header markup.
+
+REQUIREMENT
+    This plugin requires the Geo::IP module from CPAN. For backward
+    compatibility IP::Country::Fast is used if Geo::IP is not installed.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,107 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::ReplaceTags - tags for SpamAssassin rules</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#rule_definitions_and_privileged_settings">RULE DEFINITIONS AND PRIVILEGED SETTINGS</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::ReplaceTags - tags for SpamAssassin rules</p>
+<p>The plugin allows rules to contain regular expression tags to be used in
+regular expression rules.  The tags make it much easier to maintain
+complicated rules.</p>
+<p>Warning: This plugin relies on data structures specific to this version of
+SpamAssasin; it is not guaranteed to work with other versions of SpamAssassin.</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin    Mail::SpamAssassin::Plugin::ReplaceTags</pre>
+<pre>
+  replace_start &lt;
+  replace_end   &gt;</pre>
+<pre>
+  replace_tag   A       [a@]
+  replace_tag   G       [gk]
+  replace_tag   I       [il|!1y\?\xcc\xcd\xce\xcf\xec\xed\xee\xef]
+  replace_tag   R       [r3]
+  replace_tag   V       (?:[vu]|\\\/)
+  replace_tag   SP      [\s~_-]</pre>
+<pre>
+  body          VIAGRA_OBFU     /(?!viagra)&lt;V&gt;+&lt;SP&gt;*&lt;I&gt;+&lt;SP&gt;*&lt;A&gt;+&lt;SP&gt;*&lt;G&gt;+&lt;SP&gt;*&lt;R&gt;+&lt;SP&gt;*&lt;A&gt;+/i
+  describe      VIAGRA_OBFU     Attempt to obfuscate &quot;viagra&quot;</pre>
+<pre>
+  replace_rules VIAGRA_OBFU</pre>
+<p>
+</p>
+<hr />
+<h1><a name="rule_definitions_and_privileged_settings">RULE DEFINITIONS AND PRIVILEGED SETTINGS</a></h1>
+<dl>
+<dt><strong><a name="replace_tag_tagname_expression" class="item">replace_tag tagname expression</a></strong></dt>
+
+<dd>
+<p>Assign a valid regular expression to tagname.</p>
+<p>Note: It is not recommended to put quantifiers inside the tag, it's better to
+put them inside the rule itself for greater flexibility.</p>
+</dd>
+<dt><strong><a name="replace_pre_tagname_expression" class="item">replace_pre tagname expression</a></strong></dt>
+
+<dd>
+<p>Assign a valid regular expression to tagname.  The expression will be
+placed before each tag that is replaced.</p>
+</dd>
+<dt><strong><a name="replace_inter_tagname_expression" class="item">replace_inter tagname expression</a></strong></dt>
+
+<dd>
+<p>Assign a valid regular expression to tagname.  The expression will be
+placed between each two immediately adjacent tags that are replaced.</p>
+</dd>
+<dt><strong><a name="replace_post_tagname_expression" class="item">replace_post tagname expression</a></strong></dt>
+
+<dd>
+<p>Assign a valid regular expression to tagname.  The expression will be
+placed after each tag that is replaced.</p>
+</dd>
+<dt><strong><a name="replace_rules_list_of_tests" class="item">replace_rules list_of_tests</a></strong></dt>
+
+<dd>
+<p>Specify a list of symbolic test names (separated by whitespace) of tests which
+should be modified using replacement tags.  Only simple regular expression
+body, header, uri, full, rawbody tests are supported.</p>
+</dd>
+<dt><strong><a name="replace_start_string" class="item">replace_start string</a></strong></dt>
+
+<dt><strong><a name="replace_end_string" class="item">replace_end string</a></strong></dt>
+
+<dd>
+<p>String(s) which indicate the start and end of a tag inside a rule.  Only tags
+enclosed by the start and end strings are found and replaced.</p>
+</dd>
+</dl>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_ReplaceTags.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,60 @@
+NAME
+    Mail::SpamAssassin::Plugin::ReplaceTags - tags for SpamAssassin rules
+
+    The plugin allows rules to contain regular expression tags to be used in
+    regular expression rules. The tags make it much easier to maintain
+    complicated rules.
+
+    Warning: This plugin relies on data structures specific to this version
+    of SpamAssasin; it is not guaranteed to work with other versions of
+    SpamAssassin.
+
+SYNOPSIS
+      loadplugin    Mail::SpamAssassin::Plugin::ReplaceTags
+
+      replace_start <
+      replace_end   >
+
+      replace_tag   A       [a@]
+      replace_tag   G       [gk]
+      replace_tag   I       [il|!1y\?\xcc\xcd\xce\xcf\xec\xed\xee\xef]
+      replace_tag   R       [r3]
+      replace_tag   V       (?:[vu]|\\\/)
+      replace_tag   SP      [\s~_-]
+
+      body          VIAGRA_OBFU     /(?!viagra)<V>+<SP>*<I>+<SP>*<A>+<SP>*<G>+<SP>*<R>+<SP>*<A>+/i
+      describe      VIAGRA_OBFU     Attempt to obfuscate "viagra"
+
+      replace_rules VIAGRA_OBFU
+
+RULE DEFINITIONS AND PRIVILEGED SETTINGS
+    replace_tag tagname expression
+        Assign a valid regular expression to tagname.
+
+        Note: It is not recommended to put quantifiers inside the tag, it's
+        better to put them inside the rule itself for greater flexibility.
+
+    replace_pre tagname expression
+        Assign a valid regular expression to tagname. The expression will be
+        placed before each tag that is replaced.
+
+    replace_inter tagname expression
+        Assign a valid regular expression to tagname. The expression will be
+        placed between each two immediately adjacent tags that are replaced.
+
+    replace_post tagname expression
+        Assign a valid regular expression to tagname. The expression will be
+        placed after each tag that is replaced.
+
+    replace_rules list_of_tests
+        Specify a list of symbolic test names (separated by whitespace) of
+        tests which should be modified using replacement tags. Only simple
+        regular expression body, header, uri, full, rawbody tests are
+        supported.
+
+    replace_start string
+    replace_end string
+        String(s) which indicate the start and end of a tag inside a rule.
+        Only tags enclosed by the start and end strings are found and
+        replaced.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,54 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::Reuse - For reusing old rule hits during a mass-check</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::Reuse - For reusing old rule hits during a mass-check</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin    Mail::SpamAssassin::Plugin::Reuse</pre>
+<pre>
+  ifplugin      Mail::SpamAssassin::Plugin::Reuse</pre>
+<pre>
+  reuse NETWORK_RULE [ NETWORK_RULE_OLD_NAME ]</pre>
+<pre>
+  endif</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>The purpose of this plugin is to work in conjunction with <strong>mass-check
+--reuse</strong> to map rules hit in input messages to rule hits in the
+mass-check output.</p>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Reuse.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,18 @@
+NAME
+    Mail::SpamAssassin::Plugin::Reuse - For reusing old rule hits during a
+    mass-check
+
+SYNOPSIS
+      loadplugin    Mail::SpamAssassin::Plugin::Reuse
+
+      ifplugin      Mail::SpamAssassin::Plugin::Reuse
+
+      reuse NETWORK_RULE [ NETWORK_RULE_OLD_NAME ]
+
+      endif
+
+DESCRIPTION
+    The purpose of this plugin is to work in conjunction with mass-check
+    --reuse to map rules hit in input messages to rule hits in the
+    mass-check output.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,50 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::Rule2XSBody - speed up SpamAssassin by compiling regexps</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::Rule2XSBody - speed up SpamAssassin by compiling regexps</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::Rule2XSBody</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>This plugin will use native-code object files representing the ruleset,
+in order to provide significant speedups in rule evaluation.</p>
+<p>Note that <code>sa-compile</code> must be run in advance, in order to compile the
+ruleset using <code>re2c</code> and the C compiler.  See the <code>sa-compile</code>
+documentation for more details.</p>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Rule2XSBody.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,15 @@
+NAME
+    Mail::SpamAssassin::Plugin::Rule2XSBody - speed up SpamAssassin by
+    compiling regexps
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::Rule2XSBody
+
+DESCRIPTION
+    This plugin will use native-code object files representing the ruleset,
+    in order to provide significant speedups in rule evaluation.
+
+    Note that "sa-compile" must be run in advance, in order to compile the
+    ruleset using "re2c" and the C compiler. See the "sa-compile"
+    documentation for more details.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,769 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::SPF - perform SPF verification tests</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+	<li><a href="#user_settings">USER SETTINGS</a></li>
+	<li><a href="#administrator_options">ADMINISTRATOR OPTIONS</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::SPF - perform SPF verification tests</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::SPF</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>This plugin checks a message against Sender Policy Framework (SPF)
+records published by the domain owners in DNS to fight email address
+forgery and make it easier to identify spams.</p>
+<p>
+</p>
+<hr />
+<h1><a name="user_settings">USER SETTINGS</a></h1>
+<dl>
+<dt><strong><a name="whitelist_from_spf_user_example_com" class="item">whitelist_from_spf <a href="mailto:user@example.com">user@example.com</a></a></strong></dt>
+
+<dd>
+<p>Works similarly to whitelist_from, except that in addition to matching
+a sender address, a check against the domain's SPF record must pass.
+The first parameter is an address to whitelist, and the second is a string
+to match the relay's rDNS.</p>
+<p>Just like whitelist_from, multiple addresses per line, separated by spaces,
+are OK. Multiple <code>whitelist_from_spf</code> lines are also OK.</p>
+<p>The headers checked for whitelist_from_spf addresses are the same headers
+used for SPF checks (Envelope-From, Return-Path, X-Envelope-From, etc).</p>
+<p>Since this whitelist requires an SPF check to be made, network tests must be
+enabled. It is also required that your trust path be correctly configured.
+See the section on <code>trusted_networks</code> for more info on trust paths.</p>
+<p>e.g.</p>
+<pre>
+  whitelist_from_spf joe@example.com fred@example.com
+  whitelist_from_spf *@example.com</pre>
+</dd>
+<dt><strong><a name="def_whitelist_from_spf_user_example_com" class="item">def_whitelist_from_spf <a href="mailto:user@example.com">user@example.com</a></a></strong></dt>
+
+<dd>
+<p>Same as <code>whitelist_from_spf</code>, but used for the default whitelist entries
+in the SpamAssassin distribution.  The whitelist score is lower, because
+these are often targets for spammer spoofing.</p>
+</dd>
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="administrator_options">ADMINISTRATOR OPTIONS</a></h1>
+<dl>
+<dt><strong><a name="n" class="item">spf_timeout n		(default: 5)</a></strong></dt>
+
+<dd>
+<p>How many seconds to wait for an SPF query to complete, before scanning
+continues without the SPF result. A numeric value is optionally suffixed
+by a time unit (s, m, h, d, w, indicating seconds (default), minutes, hours,
+days, weeks).</p>
+</dd>
+<dt><strong><a name="do_not_use_mail_spf" class="item">do_not_use_mail_spf (0|1)		(default: 0)</a></strong></dt>
+
+<dd>
+<p>By default the plugin will try to use the Mail::SPF module for SPF checks if
+it can be loaded.  If Mail::SPF cannot be used the plugin will fall back to
+using the legacy Mail::SPF::Query module if it can be loaded.</p>
+<p>Use this option to stop the plugin from using Mail::SPF and cause it to try to
+use Mail::SPF::Query instead.</p>
+</dd>
+<dt><strong><a name="do_not_use_mail_spf_query" class="item">do_not_use_mail_spf_query (0|1)	(default: 0)</a></strong></dt>
+
+<dd>
+<p>As above, but instead stop the plugin from trying to use Mail::SPF::Query and
+cause it to only try to use Mail::SPF.</p>
+</dd>
+<dt><strong><a name="ignore_received_spf_header" class="item">ignore_received_spf_header (0|1)	(default: 0)</a></strong></dt>
+
+<dd>
+<p>By default, to avoid unnecessary DNS lookups, the plugin will try to use the
+SPF results found in any <code>Received-SPF</code> headers it finds in the message that
+could only have been added by an internal relay.</p>
+<p>Set this option to 1 to ignore any <code>Received-SPF</code> headers present and to have
+the plugin perform the SPF check itself.</p>
+<p>Note that unless the plugin finds an <code>identity=helo</code>, or some unsupported
+identity, it will assume that the result is a mfrom SPF check result.  The
+only identities supported are <code>mfrom</code>, <code>mailfrom</code> and <code>helo</code>.</p>
+</dd>
+<dt><strong><a name="use_newest_received_spf_header" class="item">use_newest_received_spf_header (0|1)	(default: 0)</a></strong></dt>
+
+<dd>
+<p>By default, when using <code>Received-SPF</code> headers, the plugin will attempt to use
+the oldest (bottom most) <code>Received-SPF</code> headers, that were added by internal
+relays, that it can parse results from since they are the most likely to be
+accurate.  This is done so that if you have an incoming mail setup where one
+of your primary MXes doesn't know about a secondary MX (or your MXes don't
+know about some sort of forwarding relay that SA considers trusted+internal)
+but SA is aware of the actual domain boundary (internal_networks setting) SA
+will use the results that are most accurate.</p>
+<p>Use this option to start with the newest (top most) <code>Received-SPF</code> headers,
+working downwards until results are successfully parsed.</p>
+</dd>
+<dt><strong><a name="has_check_for_spf_errors" class="item">has_check_for_spf_errors</a></strong></dt>
+
+<dd>
+<p>Adds capability check for &quot;if can()&quot; for check_for_spf_permerror, check_for_spf_temperror, check_for_spf_helo_permerror and check_for_spf_helo_permerror</p>
+<pre>
+
+=cut</pre>
+<p>sub has_check_for_spf_errors { 1 }</p>
+<p># SPF support
+sub check_for_spf_pass {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_pass};
+}</p>
+<p>sub check_for_spf_neutral {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_neutral};
+}</p>
+<p>sub check_for_spf_none {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_none};
+}</p>
+<p>sub check_for_spf_fail {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  if ($scanner-&gt;{spf_failure_comment}) {
+    $scanner-&gt;test_log ($scanner-&gt;{spf_failure_comment});
+  }
+  $scanner-&gt;{spf_fail};
+}</p>
+<p>sub check_for_spf_softfail {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_softfail};
+}</p>
+<p>sub check_for_spf_permerror {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_permerror};
+}</p>
+<p>sub check_for_spf_temperror {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 0) unless $scanner-&gt;{spf_checked};
+  $scanner-&gt;{spf_temperror};
+}</p>
+<p>sub check_for_spf_helo_pass {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_pass};
+}</p>
+<p>sub check_for_spf_helo_neutral {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_neutral};
+}</p>
+<p>sub check_for_spf_helo_none {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_none};
+}</p>
+<p>sub check_for_spf_helo_fail {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  if ($scanner-&gt;{spf_helo_failure_comment}) {
+    $scanner-&gt;test_log ($scanner-&gt;{spf_helo_failure_comment});
+  }
+  $scanner-&gt;{spf_helo_fail};
+}</p>
+<p>sub check_for_spf_helo_softfail {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_softfail};
+}</p>
+<p>sub check_for_spf_helo_permerror {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_permerror};
+}</p>
+<p>sub check_for_spf_helo_temperror {
+  my ($self, $scanner) = @_;
+  $self-&gt;_check_spf ($scanner, 1) unless $scanner-&gt;{spf_helo_checked};
+  $scanner-&gt;{spf_helo_temperror};
+}</p>
+<p>sub check_for_spf_whitelist_from {
+  my ($self, $scanner) = @_;
+  $self-&gt;<code>_check_spf_whitelist($scanner)</code> unless $scanner-&gt;{spf_whitelist_from_checked};
+  $scanner-&gt;{spf_whitelist_from};
+}</p>
+<p>sub check_for_def_spf_whitelist_from {
+  my ($self, $scanner) = @_;
+  $self-&gt;<code>_check_def_spf_whitelist($scanner)</code> unless $scanner-&gt;{def_spf_whitelist_from_checked};
+  $scanner-&gt;{def_spf_whitelist_from};
+}</p>
+<p>sub _check_spf {
+  my ($self, $scanner, $ishelo) = @_;</p>
+<pre>
+  my $timer = $self-&gt;{main}-&gt;time_method(&quot;check_spf&quot;);</pre>
+<pre>
+  # we can re-use results from any *INTERNAL* Received-SPF header in the message...
+  # we can't use results from trusted but external hosts since (i) spf checks are
+  # supposed to be done &quot;on the domain boundary&quot;, (ii) even if an external header 
+  # has a result that matches what we would get, the check was probably done on a
+  # different envelope (like the apache.org list servers checking the ORCPT and
+  # then using a new envelope to send the mail from the list) and (iii) if the
+  # checks are being done right and the envelope isn't being changed it's 99%
+  # likely that the trusted+external host really should be defined as part of your
+  # internal network
+  if ($scanner-&gt;{conf}-&gt;{ignore_received_spf_header}) {
+    dbg(&quot;spf: ignoring any Received-SPF headers from internal hosts, by admin setting&quot;);
+  } elsif ($scanner-&gt;{checked_for_received_spf_header}) {
+    dbg(&quot;spf: already checked for Received-SPF headers, proceeding with DNS based checks&quot;);
+  } else {
+    $scanner-&gt;{checked_for_received_spf_header} = 1;
+    dbg(&quot;spf: checking to see if the message has a Received-SPF header that we can use&quot;);</pre>
+<pre>
+    my @internal_hdrs = split(&quot;\n&quot;, $scanner-&gt;get('ALL-INTERNAL'));
+    unless ($scanner-&gt;{conf}-&gt;{use_newest_received_spf_header}) {
+      # look for the LAST (earliest in time) header, it'll be the most accurate
+      @internal_hdrs = reverse(@internal_hdrs);
+    } else {
+      dbg(&quot;spf: starting with the newest Received-SPF headers first&quot;);
+    }</pre>
+<pre>
+    foreach my $hdr (@internal_hdrs) {
+      local($1,$2);
+      if ($hdr =~ /^received-spf:/i) {
+        dbg(&quot;spf: found a Received-SPF header added by an internal host: $hdr&quot;);</pre>
+<pre>
+        # old version:
+        # Received-SPF: pass (herse.apache.org: domain of spamassassin@dostech.ca
+        #       designates 69.61.78.188 as permitted sender)</pre>
+<pre>
+        # new version:
+        # Received-SPF: pass (dostech.ca: 69.61.78.188 is authorized to use
+        #       'spamassassin@dostech.ca' in 'mfrom' identity (mechanism 'mx' matched))
+        #       receiver=FC5-VPC; identity=mfrom; envelope-from=&quot;spamassassin@dostech.ca&quot;;
+        #       helo=smtp.dostech.net; client-ip=69.61.78.188</pre>
+<pre>
+        # Received-SPF: pass (dostech.ca: 69.61.78.188 is authorized to use 'dostech.ca'
+        #       in 'helo' identity (mechanism 'mx' matched)) receiver=FC5-VPC; identity=helo;
+        #       helo=dostech.ca; client-ip=69.61.78.188</pre>
+<pre>
+        # <a href="http://www.openspf.org/RFC_4408#header-field">http://www.openspf.org/RFC_4408#header-field</a>
+        # wtf - for some reason something is sticking an extra space between the header name and field value
+        if ($hdr =~ /^received-spf:\s*(pass|neutral|(?:soft)?fail|none)\b(?:.*\bidentity=(\S+?);?\b)?/i) {
+          my $result = lc($1);</pre>
+<pre>
+          my $identity = '';    # we assume it's a mfrom check if we can't tell otherwise
+          if (defined $2) {
+            $identity = lc($2);
+            if ($identity eq 'mfrom' || $identity eq 'mailfrom') {
+              next if $scanner-&gt;{spf_checked};
+              $identity = '';
+            } elsif ($identity eq 'helo') {
+              next if $scanner-&gt;{spf_helo_checked};
+              $identity = 'helo_';
+            } else {
+              dbg(&quot;spf: found unknown identity value, cannot use: $identity&quot;);
+              next;     # try the next Received-SPF header, if any
+            }
+          } else {
+            next if $scanner-&gt;{spf_checked};
+          }</pre>
+<pre>
+          # we'd set these if we actually did the check
+          $scanner-&gt;{&quot;spf_${identity}checked&quot;} = 1;
+          $scanner-&gt;{&quot;spf_${identity}pass&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}neutral&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}none&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}fail&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}softfail&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}failure_comment&quot;} = undef;</pre>
+<pre>
+          # and the result
+          $scanner-&gt;{&quot;spf_${identity}${result}&quot;} = 1;
+          dbg(&quot;spf: re-using %s result from Received-SPF header: %s&quot;,
+              ($identity ? 'helo' : 'mfrom'), $result);</pre>
+<pre>
+          # if we've got *both* the mfrom and helo results we're done
+          return if ($scanner-&gt;{spf_checked} &amp;&amp; $scanner-&gt;{spf_helo_checked});</pre>
+<pre>
+        } else {
+          dbg(&quot;spf: could not parse result from existing Received-SPF header&quot;);
+        }</pre>
+<pre>
+      } elsif ($hdr =~ /^Authentication-Results:.*;\s*SPF\s*=\s*([^;]*)/i) {
+        dbg(&quot;spf: found an Authentication-Results header added by an internal host: $hdr&quot;);</pre>
+<pre>
+        # RFC 5451 header parser - added by D. Stussy 2010-09-09:
+        # Authentication-Results: mail.example.com; SPF=none smtp.mailfrom=example.org (comment)</pre>
+<pre>
+        my $tmphdr = $1;
+        if ($tmphdr =~ /^(pass|neutral|(?:hard|soft)?fail|none)(?:[^;]*?\bsmtp\.(\S+)\s*=[^;]+)?/i) {
+          my $result = lc($1);
+          $result = 'fail'  if $result eq 'hardfail';  # RFC5451 permits this</pre>
+<pre>
+          my $identity = '';    # we assume it's a mfrom check if we can't tell otherwise
+          if (defined $2) {
+            $identity = lc($2);
+            if ($identity eq 'mfrom' || $identity eq 'mailfrom') {
+              next if $scanner-&gt;{spf_checked};
+              $identity = '';
+            } elsif ($identity eq 'helo') {
+              next if $scanner-&gt;{spf_helo_checked};
+              $identity = 'helo_';
+            } else {
+              dbg(&quot;spf: found unknown identity value, cannot use: $identity&quot;);
+              next;     # try the next Authentication-Results header, if any
+            }
+          } else {
+            next if $scanner-&gt;{spf_checked};
+          }</pre>
+<pre>
+          # we'd set these if we actually did the check
+          $scanner-&gt;{&quot;spf_${identity}checked&quot;} = 1;
+          $scanner-&gt;{&quot;spf_${identity}pass&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}neutral&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}none&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}fail&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}softfail&quot;} = 0;
+          $scanner-&gt;{&quot;spf_${identity}failure_comment&quot;} = undef;</pre>
+<pre>
+          # and the result
+          $scanner-&gt;{&quot;spf_${identity}${result}&quot;} = 1;
+          dbg(&quot;spf: re-using %s result from Authentication-Results header: %s&quot;,
+               ($identity ? 'helo' : 'mfrom'), $result);</pre>
+<pre>
+          # if we've got *both* the mfrom and helo results we're done
+          return if ($scanner-&gt;{spf_checked} &amp;&amp; $scanner-&gt;{spf_helo_checked});</pre>
+<pre>
+        } else {
+          dbg(&quot;spf: could not parse result from existing Authentication-Results header&quot;);
+        }
+      }
+    }
+    # we can return if we've found the one we're being asked to get
+    return if ( ($ishelo &amp;&amp; $scanner-&gt;{spf_helo_checked}) ||
+                (!$ishelo &amp;&amp; $scanner-&gt;{spf_checked}) );
+  }</pre>
+<pre>
+  # abort if dns or an spf module isn't available
+  return unless $scanner-&gt;is_dns_available();
+  return if $self-&gt;{no_spf_module};</pre>
+<pre>
+  # select the SPF module we're going to use
+  unless (defined $self-&gt;{has_mail_spf}) {
+    my $eval_stat;
+    eval {
+      die(&quot;Mail::SPF disabled by admin setting\n&quot;) if $scanner-&gt;{conf}-&gt;{do_not_use_mail_spf};</pre>
+<pre>
+      require Mail::SPF;
+      if (!defined $Mail::SPF::VERSION || $Mail::SPF::VERSION &lt; 2.001) {
+        die &quot;Mail::SPF 2.001 or later required, this is &quot;.
+          (defined $Mail::SPF::VERSION ? $Mail::SPF::VERSION : 'unknown').&quot;\n&quot;;
+      }
+      # Mail::SPF::Server can be re-used, and we get to use our own resolver object!
+      $self-&gt;{spf_server} = Mail::SPF::Server-&gt;new(
+                                hostname     =&gt; $scanner-&gt;get_tag('HOSTNAME'),
+                                dns_resolver =&gt; $self-&gt;{main}-&gt;{resolver},
+                                max_dns_interactive_terms =&gt; 15);
+      # Bug 7112: max_dns_interactive_terms defaults to 10, but even 14 is
+      # not enough for ebay.com, setting it to 15
+      1;
+    } or do {
+      $eval_stat = $@ ne '' ? $@ : &quot;errno=$!&quot;;  chomp $eval_stat;
+    };</pre>
+<pre>
+    if (!defined($eval_stat)) {
+      dbg(&quot;spf: using Mail::SPF for SPF checks&quot;);
+      $self-&gt;{has_mail_spf} = 1;
+    } else {
+      # strip the @INC paths... users are going to see it and think there's a problem even though
+      # we're going to fall back to Mail::SPF::Query (which will display the same paths if it fails)
+      $eval_stat =~ s#^Can't locate Mail/SPFd.pm in \@INC .*#Can't locate Mail/SPFd.pm#;
+      dbg(&quot;spf: cannot load Mail::SPF module or create Mail::SPF::Server object: $eval_stat&quot;);
+      dbg(&quot;spf: attempting to use legacy Mail::SPF::Query module instead&quot;);</pre>
+<pre>
+      undef $eval_stat;
+      eval {
+        die(&quot;Mail::SPF::Query disabled by admin setting\n&quot;) if $scanner-&gt;{conf}-&gt;{do_not_use_mail_spf_query};</pre>
+<pre>
+        require Mail::SPF::Query;
+        if (!defined $Mail::SPF::Query::VERSION || $Mail::SPF::Query::VERSION &lt; 1.996) {
+          die &quot;Mail::SPF::Query 1.996 or later required, this is &quot;.
+            (defined $Mail::SPF::Query::VERSION ? $Mail::SPF::Query::VERSION : 'unknown').&quot;\n&quot;;
+        }
+        1;
+      } or do {
+        $eval_stat = $@ ne '' ? $@ : &quot;errno=$!&quot;;  chomp $eval_stat;
+      };</pre>
+<pre>
+      if (!defined($eval_stat)) {
+        dbg(&quot;spf: using Mail::SPF::Query for SPF checks&quot;);
+        $self-&gt;{has_mail_spf} = 0;
+      } else {
+        dbg(&quot;spf: cannot load Mail::SPF::Query module: $eval_stat&quot;);
+        dbg(&quot;spf: one of Mail::SPF or Mail::SPF::Query is required for SPF checks, SPF checks disabled&quot;);
+        $self-&gt;{no_spf_module} = 1;
+        return;
+      }
+    }
+  }</pre>
+<pre>
+  # skip SPF checks if the A/MX records are nonexistent for the From
+  # domain, anyway, to avoid crappy messages from slowing us down
+  # (bug 3016)
+  return if $scanner-&gt;check_for_from_dns();</pre>
+<pre>
+  if ($ishelo) {
+    # SPF HELO-checking variant
+    $scanner-&gt;{spf_helo_checked} = 1;
+    $scanner-&gt;{spf_helo_pass} = 0;
+    $scanner-&gt;{spf_helo_neutral} = 0;
+    $scanner-&gt;{spf_helo_none} = 0;
+    $scanner-&gt;{spf_helo_fail} = 0;
+    $scanner-&gt;{spf_helo_softfail} = 0;
+    $scanner-&gt;{spf_helo_permerror} = 0;
+    $scanner-&gt;{spf_helo_temperror} = 0;
+    $scanner-&gt;{spf_helo_failure_comment} = undef;
+  } else {
+    # SPF on envelope sender (where possible)
+    $scanner-&gt;{spf_checked} = 1;
+    $scanner-&gt;{spf_pass} = 0;
+    $scanner-&gt;{spf_neutral} = 0;
+    $scanner-&gt;{spf_none} = 0;
+    $scanner-&gt;{spf_fail} = 0;
+    $scanner-&gt;{spf_softfail} = 0;
+    $scanner-&gt;{spf_permerror} = 0;
+    $scanner-&gt;{spf_temperror} = 0;
+    $scanner-&gt;{spf_failure_comment} = undef;
+  }</pre>
+<pre>
+  my $lasthop = $self-&gt;_get_relay($scanner);
+  if (!defined $lasthop) {
+    dbg(&quot;spf: no suitable relay for spf use found, skipping SPF%s check&quot;,
+        $ishelo ? '-helo' : '');
+    return;
+  }</pre>
+<pre>
+  my $ip = $lasthop-&gt;{ip};      # always present
+  my $helo = $lasthop-&gt;{helo};  # could be missing
+  $scanner-&gt;{sender} = '' unless $scanner-&gt;{sender_got};</pre>
+<pre>
+  if ($ishelo) {
+    unless ($helo) {
+      dbg(&quot;spf: cannot check HELO, HELO value unknown&quot;);
+      return;
+    }
+    dbg(&quot;spf: checking HELO (helo=$helo, ip=$ip)&quot;);
+  } else {
+    $self-&gt;_get_sender($scanner) unless $scanner-&gt;{sender_got};</pre>
+<pre>
+    # TODO: we're supposed to use the helo domain as the sender identity (for
+    # mfrom checks) if the sender is the null sender, however determining that
+    # it's the null sender, and not just a failure to get the envelope isn't
+    # exactly trivial... so for now we'll just skip the check</pre>
+<pre>
+    if (!$scanner-&gt;{sender}) {
+      # we already dbg'd that we couldn't get an Envelope-From and can't do SPF
+      return;
+    }
+    dbg(&quot;spf: checking EnvelopeFrom (helo=%s, ip=%s, envfrom=%s)&quot;,
+        ($helo ? $helo : ''), $ip, $scanner-&gt;{sender});
+  }</pre>
+<pre>
+  # this test could probably stand to be more strict, but try to test
+  # any invalid HELO hostname formats with a header rule
+  if ($ishelo &amp;&amp; ($helo =~ /^[\[!]?\d+\.\d+\.\d+\.\d+[\]!]?$/ || $helo =~ /^[^.]+$/)) {
+    dbg(&quot;spf: cannot check HELO of '$helo', skipping&quot;);
+    return;
+  }</pre>
+<pre>
+  if ($helo &amp;&amp; $scanner-&gt;server_failed_to_respond_for_domain($helo)) {
+    dbg(&quot;spf: we had a previous timeout on '$helo', skipping&quot;);
+    return;
+  }</pre>
+<pre>
+  my ($result, $comment, $text, $err);</pre>
+<pre>
+  # use Mail::SPF if it was available, otherwise use the legacy Mail::SPF::Query
+  if ($self-&gt;{has_mail_spf}) {</pre>
+<pre>
+    # TODO: currently we won't get to here for a mfrom check with a null sender
+    my $identity = $ishelo ? $helo : ($scanner-&gt;{sender}); # || $helo);</pre>
+<pre>
+    unless ($identity) {
+      dbg(&quot;spf: cannot determine %s identity, skipping %s SPF check&quot;,
+          ($ishelo ? 'helo' : 'mfrom'),  ($ishelo ? 'helo' : 'mfrom') );
+      return;
+    }
+    $helo ||= 'unknown';  # only used for macro expansion in the mfrom explanation</pre>
+<pre>
+    my $request;
+    eval {
+      $request = Mail::SPF::Request-&gt;new( scope         =&gt; $ishelo ? 'helo' : 'mfrom',
+                                          identity      =&gt; $identity,
+                                          ip_address    =&gt; $ip,
+                                          helo_identity =&gt; $helo );
+      1;
+    } or do {
+      my $eval_stat = $@ ne '' ? $@ : &quot;errno=$!&quot;;  chomp $eval_stat;
+      dbg(&quot;spf: cannot create Mail::SPF::Request object: $eval_stat&quot;);
+      return;
+    };</pre>
+<pre>
+    my $timeout = $scanner-&gt;{conf}-&gt;{spf_timeout};</pre>
+<pre>
+    my $timer = Mail::SpamAssassin::Timeout-&gt;new(
+                { secs =&gt; $timeout, deadline =&gt; $scanner-&gt;{master_deadline} });
+    $err = $timer-&gt;run_and_catch(sub {</pre>
+<pre>
+      my $query = $self-&gt;{spf_server}-&gt;process($request);</pre>
+<pre>
+      $result = $query-&gt;code;
+      $comment = $query-&gt;authority_explanation if $query-&gt;can(&quot;authority_explanation&quot;);
+      $text = $query-&gt;text;</pre>
+<pre>
+    });</pre>
+<pre>
+  } else {</pre>
+<pre>
+    if (!$helo) {
+      dbg(&quot;spf: cannot get HELO, cannot use Mail::SPF::Query, consider installing Mail::SPF&quot;);
+      return;
+    }</pre>
+<pre>
+    # TODO: if we start doing checks on the null sender using the helo domain
+    # be sure to fix this so that it uses the correct sender identity
+    my $query;
+    eval {
+      $query = Mail::SPF::Query-&gt;new (ip =&gt; $ip,
+                                    sender =&gt; $scanner-&gt;{sender},
+                                    helo =&gt; $helo,
+                                    debug =&gt; 0,
+                                    trusted =&gt; 0);
+      1;
+    } or do {
+      my $eval_stat = $@ ne '' ? $@ : &quot;errno=$!&quot;;  chomp $eval_stat;
+      dbg(&quot;spf: cannot create Mail::SPF::Query object: $eval_stat&quot;);
+      return;
+    };</pre>
+<pre>
+    my $timeout = $scanner-&gt;{conf}-&gt;{spf_timeout};</pre>
+<pre>
+    my $timer = Mail::SpamAssassin::Timeout-&gt;new(
+                { secs =&gt; $timeout, deadline =&gt; $scanner-&gt;{master_deadline} });
+    $err = $timer-&gt;run_and_catch(sub {</pre>
+<pre>
+      ($result, $comment) = $query-&gt;result();</pre>
+<pre>
+    });</pre>
+<pre>
+  } # end of differences between Mail::SPF and Mail::SPF::Query</pre>
+<pre>
+  if ($err) {
+    chomp $err;
+    warn(&quot;spf: lookup failed: $err\n&quot;);
+    return 0;
+  }</pre>
+<pre>
+  $result ||= 'timeout';        # bug 5077
+  $comment ||= '';
+  $comment =~ s/\s+/ /gs;       # no newlines please
+  $text ||= '';
+  $text =~ s/\s+/ /gs;          # no newlines please</pre>
+<pre>
+  if ($ishelo) {
+    if ($result eq 'pass') { $scanner-&gt;{spf_helo_pass} = 1; }
+    elsif ($result eq 'neutral') { $scanner-&gt;{spf_helo_neutral} = 1; }
+    elsif ($result eq 'none') { $scanner-&gt;{spf_helo_none} = 1; }
+    elsif ($result eq 'fail') { $scanner-&gt;{spf_helo_fail} = 1; }
+    elsif ($result eq 'softfail') { $scanner-&gt;{spf_helo_softfail} = 1; }
+    elsif ($result eq 'permerror') { $scanner-&gt;{spf_helo_permerror} = 1; }
+    elsif ($result eq 'temperror') { $scanner-&gt;{spf_helo_temperror} = 1; }
+    elsif ($result eq 'error') { $scanner-&gt;{spf_helo_temperror} = 1; }</pre>
+<pre>
+    if ($result eq 'fail') {    # RFC 4408 6.2
+      $scanner-&gt;{spf_helo_failure_comment} = &quot;SPF failed: $comment&quot;;
+    }
+  } else {
+    if ($result eq 'pass') { $scanner-&gt;{spf_pass} = 1; }
+    elsif ($result eq 'neutral') { $scanner-&gt;{spf_neutral} = 1; }
+    elsif ($result eq 'none') { $scanner-&gt;{spf_none} = 1; }
+    elsif ($result eq 'fail') { $scanner-&gt;{spf_fail} = 1; }
+    elsif ($result eq 'softfail') { $scanner-&gt;{spf_softfail} = 1; }
+    elsif ($result eq 'permerror') { $scanner-&gt;{spf_permerror} = 1; }
+    elsif ($result eq 'temperror') { $scanner-&gt;{spf_temperror} = 1; }
+    elsif ($result eq 'error') { $scanner-&gt;{spf_temperror} = 1; }</pre>
+<pre>
+    if ($result eq 'fail') {    # RCF 4408 6.2
+      $scanner-&gt;{spf_failure_comment} = &quot;SPF failed: $comment&quot;;
+    }
+  }</pre>
+<pre>
+  dbg(&quot;spf: query for $scanner-&gt;{sender}/$ip/$helo: result: $result, comment: $comment, text: $text&quot;);
+}</pre>
+<p>sub _get_relay {
+  my ($self, $scanner) = @_;</p>
+<pre>
+  # dos: first external relay, not first untrusted
+  return $scanner-&gt;{relays_external}-&gt;[0];
+}</pre>
+<p>sub _get_sender {
+  my ($self, $scanner) = @_;
+  my $sender;</p>
+<pre>
+  $scanner-&gt;{sender_got} = 1;
+  $scanner-&gt;{sender} = '';</pre>
+<pre>
+  my $relay = $self-&gt;_get_relay($scanner);
+  if (defined $relay) {
+    $sender = $relay-&gt;{envfrom};
+  }</pre>
+<pre>
+  if ($sender) {
+    dbg(&quot;spf: found Envelope-From in first external Received header&quot;);
+  }
+  else {
+    # We cannot use the env-from data, since it went through 1 or more relays 
+    # since the untrusted sender and they may have rewritten it.
+    if ($scanner-&gt;{num_relays_trusted} &gt; 0 &amp;&amp; !$scanner-&gt;{conf}-&gt;{always_trust_envelope_sender}) {
+      dbg(&quot;spf: relayed through one or more trusted relays, cannot use header-based Envelope-From, skipping&quot;);
+      return;
+    }</pre>
+<pre>
+    # we can (apparently) use whatever the current Envelope-From was,
+    # from the Return-Path, X-Envelope-From, or whatever header.
+    # it's better to get it from Received though, as that is updated
+    # hop-by-hop.
+    $sender = $scanner-&gt;get(&quot;EnvelopeFrom:addr&quot;);
+  }</pre>
+<pre>
+  if (!$sender) {
+    dbg(&quot;spf: cannot get Envelope-From, cannot use SPF&quot;);
+    return;  # avoid setting $scanner-&gt;{sender} to undef
+  }</pre>
+<pre>
+  return $scanner-&gt;{sender} = lc $sender;
+}</pre>
+<p>sub _check_spf_whitelist {
+  my ($self, $scanner) = @_;</p>
+<pre>
+  $scanner-&gt;{spf_whitelist_from_checked} = 1;
+  $scanner-&gt;{spf_whitelist_from} = 0;</pre>
+<pre>
+  # if we've already checked for an SPF PASS and didn't get it don't waste time
+  # checking to see if the sender address is in the spf whitelist
+  if ($scanner-&gt;{spf_checked} &amp;&amp; !$scanner-&gt;{spf_pass}) {
+    dbg(&quot;spf: whitelist_from_spf: already checked spf and didn't get pass, skipping whitelist check&quot;);
+    return;
+  }</pre>
+<pre>
+  $self-&gt;_get_sender($scanner) unless $scanner-&gt;{sender_got};</pre>
+<pre>
+  unless ($scanner-&gt;{sender}) {
+    dbg(&quot;spf: spf_whitelist_from: could not find useable envelope sender&quot;);
+    return;
+  }</pre>
+<pre>
+  $scanner-&gt;{spf_whitelist_from} = $self-&gt;_wlcheck($scanner,'whitelist_from_spf');
+  if (!$scanner-&gt;{spf_whitelist_from}) {
+    $scanner-&gt;{spf_whitelist_from} = $self-&gt;_wlcheck($scanner, 'whitelist_auth');
+  }</pre>
+<pre>
+  # if the message doesn't pass SPF validation, it can't pass an SPF whitelist
+  if ($scanner-&gt;{spf_whitelist_from}) {
+    if ($self-&gt;check_for_spf_pass($scanner)) {
+      dbg(&quot;spf: whitelist_from_spf: $scanner-&gt;{sender} is in user's WHITELIST_FROM_SPF and passed SPF check&quot;);
+    } else {
+      dbg(&quot;spf: whitelist_from_spf: $scanner-&gt;{sender} is in user's WHITELIST_FROM_SPF but failed SPF check&quot;);
+      $scanner-&gt;{spf_whitelist_from} = 0;
+    }
+  } else {
+    dbg(&quot;spf: whitelist_from_spf: $scanner-&gt;{sender} is not in user's WHITELIST_FROM_SPF&quot;);
+  }
+}</pre>
+<p>sub _check_def_spf_whitelist {
+  my ($self, $scanner) = @_;</p>
+<pre>
+  $scanner-&gt;{def_spf_whitelist_from_checked} = 1;
+  $scanner-&gt;{def_spf_whitelist_from} = 0;</pre>
+<pre>
+  # if we've already checked for an SPF PASS and didn't get it don't waste time
+  # checking to see if the sender address is in the spf whitelist
+  if ($scanner-&gt;{spf_checked} &amp;&amp; !$scanner-&gt;{spf_pass}) {
+    dbg(&quot;spf: def_spf_whitelist_from: already checked spf and didn't get pass, skipping whitelist check&quot;);
+    return;
+  }</pre>
+<pre>
+  $self-&gt;_get_sender($scanner) unless $scanner-&gt;{sender_got};</pre>
+<pre>
+  unless ($scanner-&gt;{sender}) {
+    dbg(&quot;spf: def_spf_whitelist_from: could not find useable envelope sender&quot;);
+    return;
+  }</pre>
+<pre>
+  $scanner-&gt;{def_spf_whitelist_from} = $self-&gt;_wlcheck($scanner,'def_whitelist_from_spf');
+  if (!$scanner-&gt;{def_spf_whitelist_from}) {
+    $scanner-&gt;{def_spf_whitelist_from} = $self-&gt;_wlcheck($scanner, 'def_whitelist_auth');
+  }</pre>
+<pre>
+  # if the message doesn't pass SPF validation, it can't pass an SPF whitelist
+  if ($scanner-&gt;{def_spf_whitelist_from}) {
+    if ($self-&gt;check_for_spf_pass($scanner)) {
+      dbg(&quot;spf: def_whitelist_from_spf: $scanner-&gt;{sender} is in DEF_WHITELIST_FROM_SPF and passed SPF check&quot;);
+    } else {
+      dbg(&quot;spf: def_whitelist_from_spf: $scanner-&gt;{sender} is in DEF_WHITELIST_FROM_SPF but failed SPF check&quot;);
+      $scanner-&gt;{def_spf_whitelist_from} = 0;
+    }
+  } else {
+    dbg(&quot;spf: def_whitelist_from_spf: $scanner-&gt;{sender} is not in DEF_WHITELIST_FROM_SPF&quot;);
+  }
+}</pre>
+<p>sub _wlcheck {
+  my ($self, $scanner, $param) = @_;
+  if (defined ($scanner-&gt;{conf}-&gt;{$param}-&gt;{$scanner-&gt;{sender}})) {
+    return 1;
+  } else {
+    study $scanner-&gt;{sender};  # study is a no-op since perl 5.16.0
+    foreach my $regexp (values %{$scanner-&gt;{conf}-&gt;{$param}}) {
+      if ($scanner-&gt;{sender} =~ qr/$regexp/i) {
+        return 1;
+      }
+    }
+  }
+  return 0;
+}</p>
+<p>###########################################################################</p>
+<p>1;</p>
+</dd>
+</dl>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SPF.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,92 @@
+NAME
+    Mail::SpamAssassin::Plugin::SPF - perform SPF verification tests
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::SPF
+
+DESCRIPTION
+    This plugin checks a message against Sender Policy Framework (SPF)
+    records published by the domain owners in DNS to fight email address
+    forgery and make it easier to identify spams.
+
+USER SETTINGS
+    whitelist_from_spf user@example.com
+        Works similarly to whitelist_from, except that in addition to
+        matching a sender address, a check against the domain's SPF record
+        must pass. The first parameter is an address to whitelist, and the
+        second is a string to match the relay's rDNS.
+
+        Just like whitelist_from, multiple addresses per line, separated by
+        spaces, are OK. Multiple "whitelist_from_spf" lines are also OK.
+
+        The headers checked for whitelist_from_spf addresses are the same
+        headers used for SPF checks (Envelope-From, Return-Path,
+        X-Envelope-From, etc).
+
+        Since this whitelist requires an SPF check to be made, network tests
+        must be enabled. It is also required that your trust path be
+        correctly configured. See the section on "trusted_networks" for more
+        info on trust paths.
+
+        e.g.
+
+          whitelist_from_spf joe@example.com fred@example.com
+          whitelist_from_spf *@example.com
+
+    def_whitelist_from_spf user@example.com
+        Same as "whitelist_from_spf", but used for the default whitelist
+        entries in the SpamAssassin distribution. The whitelist score is
+        lower, because these are often targets for spammer spoofing.
+
+ADMINISTRATOR OPTIONS
+    spf_timeout n (default: 5)
+        How many seconds to wait for an SPF query to complete, before
+        scanning continues without the SPF result. A numeric value is
+        optionally suffixed by a time unit (s, m, h, d, w, indicating
+        seconds (default), minutes, hours, days, weeks).
+
+    do_not_use_mail_spf (0|1) (default: 0)
+        By default the plugin will try to use the Mail::SPF module for SPF
+        checks if it can be loaded. If Mail::SPF cannot be used the plugin
+        will fall back to using the legacy Mail::SPF::Query module if it can
+        be loaded.
+
+        Use this option to stop the plugin from using Mail::SPF and cause it
+        to try to use Mail::SPF::Query instead.
+
+    do_not_use_mail_spf_query (0|1) (default: 0)
+        As above, but instead stop the plugin from trying to use
+        Mail::SPF::Query and cause it to only try to use Mail::SPF.
+
+    ignore_received_spf_header (0|1) (default: 0)
+        By default, to avoid unnecessary DNS lookups, the plugin will try to
+        use the SPF results found in any "Received-SPF" headers it finds in
+        the message that could only have been added by an internal relay.
+
+        Set this option to 1 to ignore any "Received-SPF" headers present
+        and to have the plugin perform the SPF check itself.
+
+        Note that unless the plugin finds an "identity=helo", or some
+        unsupported identity, it will assume that the result is a mfrom SPF
+        check result. The only identities supported are "mfrom", "mailfrom"
+        and "helo".
+
+    use_newest_received_spf_header (0|1) (default: 0)
+        By default, when using "Received-SPF" headers, the plugin will
+        attempt to use the oldest (bottom most) "Received-SPF" headers, that
+        were added by internal relays, that it can parse results from since
+        they are the most likely to be accurate. This is done so that if you
+        have an incoming mail setup where one of your primary MXes doesn't
+        know about a secondary MX (or your MXes don't know about some sort
+        of forwarding relay that SA considers trusted+internal) but SA is
+        aware of the actual domain boundary (internal_networks setting) SA
+        will use the results that are most accurate.
+
+        Use this option to start with the newest (top most) "Received-SPF"
+        headers, working downwards until results are successfully parsed.
+
+    has_check_for_spf_errors
+        Adds capability check for "if can()" for check_for_spf_permerror,
+        check_for_spf_temperror, check_for_spf_helo_permerror and
+        check_for_spf_helo_permerror
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::Shortcircuit - short-circuit evaluation for certain rules</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+	<li><a href="#configuration_settings">CONFIGURATION SETTINGS</a></li>
+	<li><a href="#tags">TAGS</a></li>
+	<li><a href="#see_also">SEE ALSO</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::Shortcircuit - short-circuit evaluation for certain rules</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::Shortcircuit</pre>
+<pre>
+  report Content analysis details:   (_SCORE_ points, _REQD_ required, s/c _SCTYPE_)</pre>
+<pre>
+  add_header all Status &quot;_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ shortcircuit=_SCTYPE_ autolearn=_AUTOLEARN_ version=_VERSION_&quot;</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>This plugin implements simple, test-based shortcircuiting.  Shortcircuiting a
+test will force all other pending rules to be skipped, if that test is hit.
+In addition, a symbolic rule, <code>SHORTCIRCUIT</code>, will fire.</p>
+<p>Recomended usage is to use <code>priority</code> to set rules with strong S/O values (ie.
+1.0) to be run first, and make instant spam or ham classification based on
+that.</p>
+<p>
+</p>
+<hr />
+<h1><a name="configuration_settings">CONFIGURATION SETTINGS</a></h1>
+<p>The following configuration settings are used to control shortcircuiting:</p>
+<dl>
+<dt><strong><a name="shortcircuit_symbolic_test_name_ham_spam_on_off" class="item">shortcircuit SYMBOLIC_TEST_NAME {ham|spam|on|off}</a></strong></dt>
+
+<dd>
+<p>Shortcircuiting a test will force all other pending rules to be skipped, if
+that test is hit.</p>
+<p>Recomended usage is to use <code>priority</code> to set rules with strong S/O values (ie.
+1.0) to be run first, and make instant spam or ham classification based on
+that.</p>
+<p>To override a test that uses shortcircuiting, you can set the classification
+type to <a href="#off"><code>off</code></a>.</p>
+<dl>
+<dt><strong><a name="on" class="item">on</a></strong></dt>
+
+<dd>
+<p>Shortcircuits the rest of the tests, but does not make a strict classification
+of spam or ham.  Rather, it uses the default score for the rule being
+shortcircuited.  This would allow you, for example, to define a rule such as</p>
+<pre>
+  body TEST /test/
+  describe TEST test rule that scores barely over spam threshold
+  score TEST 5.5
+  priority TEST -100
+  shortcircuit TEST on</pre>
+<p>The result of a message hitting the above rule would be a final score of 5.5,
+as opposed to 100 (default) if it were classified as spam.</p>
+</dd>
+<dt><strong><a name="off" class="item">off</a></strong></dt>
+
+<dd>
+<p>Disables shortcircuiting on said rule.</p>
+</dd>
+<dt><strong><a name="spam" class="item">spam</a></strong></dt>
+
+<dd>
+<p>Shortcircuit the rule using a set of defaults; override the default score of
+this rule with the score from <code>shortcircuit_spam_score</code>, set the
+<code>noautolearn</code> tflag, and set priority to <code>-100</code>.  In other words,
+equivalent to:</p>
+<pre>
+  shortcircuit TEST on
+  priority TEST -100
+  score TEST 100
+  tflags TEST noautolearn</pre>
+</dd>
+<dt><strong><a name="ham" class="item">ham</a></strong></dt>
+
+<dd>
+<p>Shortcircuit the rule using a set of defaults; override the default score of
+this rule with the score from <code>shortcircuit_ham_score</code>, set the <code>noautolearn</code>
+and <code>nice</code> tflags, and set priority to <code>-100</code>.   In other words, equivalent
+to:</p>
+<pre>
+  shortcircuit TEST on
+  priority TEST -100
+  score TEST -100
+  tflags TEST noautolearn nice</pre>
+</dd>
+</dl>
+</dd>
+<dt><strong><a name="nn" class="item">shortcircuit_spam_score n.nn (default: 100)</a></strong></dt>
+
+<dd>
+<p>When shortcircuit is used on a rule, and the shortcircuit classification type
+is set to <a href="#spam"><code>spam</code></a>, this value should be applied in place of the default score
+for that rule.</p>
+</dd>
+<dt><strong>shortcircuit_ham_score n.nn (default: -100)</strong></dt>
+
+<dd>
+<p>When shortcircuit is used on a rule, and the shortcircuit classification type
+is set to <a href="#ham"><code>ham</code></a>, this value should be applied in place of the default score
+for that rule.</p>
+</dd>
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="tags">TAGS</a></h1>
+<p>The following tags are added to the set available for use in reports, headers
+etc.:</p>
+<pre>
+  _SC_              shortcircuit status (classification and rule name)
+  _SCRULE_          rulename that caused the shortcircuit 
+  _SCTYPE_          shortcircuit classification (&quot;spam&quot;, &quot;ham&quot;, &quot;default&quot;, &quot;none&quot;)</pre>
+<p>
+</p>
+<hr />
+<h1><a name="see_also">SEE ALSO</a></h1>
+<p><code>http://issues.apache.org/SpamAssassin/show_bug.cgi?id=3109</code></p>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Shortcircuit.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,95 @@
+NAME
+    Mail::SpamAssassin::Plugin::Shortcircuit - short-circuit evaluation for
+    certain rules
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::Shortcircuit
+
+      report Content analysis details:   (_SCORE_ points, _REQD_ required, s/c _SCTYPE_)
+
+      add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ shortcircuit=_SCTYPE_ autolearn=_AUTOLEARN_ version=_VERSION_"
+
+DESCRIPTION
+    This plugin implements simple, test-based shortcircuiting.
+    Shortcircuiting a test will force all other pending rules to be skipped,
+    if that test is hit. In addition, a symbolic rule, "SHORTCIRCUIT", will
+    fire.
+
+    Recomended usage is to use "priority" to set rules with strong S/O
+    values (ie. 1.0) to be run first, and make instant spam or ham
+    classification based on that.
+
+CONFIGURATION SETTINGS
+    The following configuration settings are used to control
+    shortcircuiting:
+
+    shortcircuit SYMBOLIC_TEST_NAME {ham|spam|on|off}
+        Shortcircuiting a test will force all other pending rules to be
+        skipped, if that test is hit.
+
+        Recomended usage is to use "priority" to set rules with strong S/O
+        values (ie. 1.0) to be run first, and make instant spam or ham
+        classification based on that.
+
+        To override a test that uses shortcircuiting, you can set the
+        classification type to "off".
+
+        on  Shortcircuits the rest of the tests, but does not make a strict
+            classification of spam or ham. Rather, it uses the default score
+            for the rule being shortcircuited. This would allow you, for
+            example, to define a rule such as
+
+              body TEST /test/
+              describe TEST test rule that scores barely over spam threshold
+              score TEST 5.5
+              priority TEST -100
+              shortcircuit TEST on
+
+            The result of a message hitting the above rule would be a final
+            score of 5.5, as opposed to 100 (default) if it were classified
+            as spam.
+
+        off Disables shortcircuiting on said rule.
+
+        spam
+            Shortcircuit the rule using a set of defaults; override the
+            default score of this rule with the score from
+            "shortcircuit_spam_score", set the "noautolearn" tflag, and set
+            priority to -100. In other words, equivalent to:
+
+              shortcircuit TEST on
+              priority TEST -100
+              score TEST 100
+              tflags TEST noautolearn
+
+        ham Shortcircuit the rule using a set of defaults; override the
+            default score of this rule with the score from
+            "shortcircuit_ham_score", set the "noautolearn" and "nice"
+            tflags, and set priority to -100. In other words, equivalent to:
+
+              shortcircuit TEST on
+              priority TEST -100
+              score TEST -100
+              tflags TEST noautolearn nice
+
+    shortcircuit_spam_score n.nn (default: 100)
+        When shortcircuit is used on a rule, and the shortcircuit
+        classification type is set to "spam", this value should be applied
+        in place of the default score for that rule.
+
+    shortcircuit_ham_score n.nn (default: -100)
+        When shortcircuit is used on a rule, and the shortcircuit
+        classification type is set to "ham", this value should be applied in
+        place of the default score for that rule.
+
+TAGS
+    The following tags are added to the set available for use in reports,
+    headers etc.:
+
+      _SC_              shortcircuit status (classification and rule name)
+      _SCRULE_          rulename that caused the shortcircuit 
+      _SCTYPE_          shortcircuit classification ("spam", "ham", "default", "none")
+
+SEE ALSO
+    "http://issues.apache.org/SpamAssassin/show_bug.cgi?id=3109"
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,84 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::SpamCop - perform SpamCop reporting of messages</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+	<li><a href="#user_options">USER OPTIONS</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::SpamCop - perform SpamCop reporting of messages</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::SpamCop</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>SpamCop is a service for reporting spam.  SpamCop determines the origin
+of unwanted email and reports it to the relevant Internet service
+providers.  By reporting spam, you have a positive impact on the
+problem.  Reporting unsolicited email also helps feed spam filtering
+systems, including, but not limited to, the SpamCop blacklist used in
+SpamAssassin as a DNSBL.</p>
+<p>Note that spam reports sent by this plugin to SpamCop each include the
+entire spam message.</p>
+<p>See <a href="http://www.spamcop.net/">http://www.spamcop.net/</a> for more information about SpamCop.</p>
+<p>
+</p>
+<hr />
+<h1><a name="user_options">USER OPTIONS</a></h1>
+<dl>
+<dt><strong><a name="com" class="item">spamcop_from_address <a href="mailto:user@example.com">user@example.com</a>   (default: none)</a></strong></dt>
+
+<dd>
+<p>This address is used during manual reports to SpamCop as the From:
+address.  You can use your normal email address.  If this is not set, a
+guess will be used as the From: address in SpamCop reports.</p>
+</dd>
+<dt><strong>spamcop_to_address <a href="mailto:user@example.com">user@example.com</a>   (default: generic reporting address)</strong></dt>
+
+<dd>
+<p>Your customized SpamCop report submission address.  You need to obtain
+this address by registering at <code>http://www.spamcop.net/</code>.  If this is
+not set, SpamCop reports will go to a generic reporting address for
+SpamAssassin users and your reports will probably have less weight in
+the SpamCop system.</p>
+</dd>
+<dt><strong><a name="spamcop_max_report_size" class="item">spamcop_max_report_size   (default: 50)</a></strong></dt>
+
+<dd>
+<p>Messages larger than this size (in kilobytes) will be truncated in
+report messages sent to SpamCop.  The default setting is the maximum
+size that SpamCop will accept at the time of release.</p>
+</dd>
+</dl>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_SpamCop.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,38 @@
+NAME
+    Mail::SpamAssassin::Plugin::SpamCop - perform SpamCop reporting of
+    messages
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::SpamCop
+
+DESCRIPTION
+    SpamCop is a service for reporting spam. SpamCop determines the origin
+    of unwanted email and reports it to the relevant Internet service
+    providers. By reporting spam, you have a positive impact on the problem.
+    Reporting unsolicited email also helps feed spam filtering systems,
+    including, but not limited to, the SpamCop blacklist used in
+    SpamAssassin as a DNSBL.
+
+    Note that spam reports sent by this plugin to SpamCop each include the
+    entire spam message.
+
+    See http://www.spamcop.net/ for more information about SpamCop.
+
+USER OPTIONS
+    spamcop_from_address user@example.com (default: none)
+        This address is used during manual reports to SpamCop as the From:
+        address. You can use your normal email address. If this is not set,
+        a guess will be used as the From: address in SpamCop reports.
+
+    spamcop_to_address user@example.com (default: generic reporting address)
+        Your customized SpamCop report submission address. You need to
+        obtain this address by registering at "http://www.spamcop.net/". If
+        this is not set, SpamCop reports will go to a generic reporting
+        address for SpamAssassin users and your reports will probably have
+        less weight in the SpamCop system.
+
+    spamcop_max_report_size (default: 50)
+        Messages larger than this size (in kilobytes) will be truncated in
+        report messages sent to SpamCop. The default setting is the maximum
+        size that SpamCop will accept at the time of release.
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,48 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Test - test plugin</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Test - test plugin</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::Test
+  header         MY_TEST_PLUGIN eval:check_test_plugin()</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>To try this plugin, write the above two lines in the synopsis to
+<code>/etc/mail/spamassassin/plugintest.cf</code>.</p>
+
+</body>
+
+</html>

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.txt
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.txt?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.txt (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_Test.txt Wed Apr 29 17:04:09 2015
@@ -0,0 +1,11 @@
+NAME
+    Test - test plugin
+
+SYNOPSIS
+      loadplugin     Mail::SpamAssassin::Plugin::Test
+      header         MY_TEST_PLUGIN eval:check_test_plugin()
+
+DESCRIPTION
+    To try this plugin, write the above two lines in the synopsis to
+    "/etc/mail/spamassassin/plugintest.cf".
+

Added: spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_TextCat.html
URL: http://svn.apache.org/viewvc/spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_TextCat.html?rev=1676792&view=auto
==============================================================================
--- spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_TextCat.html (added)
+++ spamassassin/site/full/3.4.x/doc/Mail_SpamAssassin_Plugin_TextCat.html Wed Apr 29 17:04:09 2015
@@ -0,0 +1,264 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Mail::SpamAssassin::Plugin::TextCat - TextCat language guesser</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+	<li><a href="#name">NAME</a></li>
+	<li><a href="#synopsis">SYNOPSIS</a></li>
+	<li><a href="#description">DESCRIPTION</a></li>
+	<li><a href="#user_options">USER OPTIONS</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Mail::SpamAssassin::Plugin::TextCat - TextCat language guesser</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+  loadplugin     Mail::SpamAssassin::Plugin::TextCat</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>This plugin will try to guess the language used in the message body text.</p>
+<p>You can use the &quot;ok_languages&quot; directive to set which languages are
+considered okay for incoming mail and if the guessed language is not okay,
+<code>UNWANTED_LANGUAGE_BODY</code> is triggered.</p>
+<p>It will always add the results to a &quot;X-Language&quot; name-value pair in the
+message metadata data structure. This may be useful as Bayes tokens and
+can also be used in rules for scoring. The results can also be added to
+marked-up messages using &quot;add_header&quot;, with the _LANGUAGES_ tag. See
+<a href="/Mail/SpamAssassin/Conf.html">the Mail::SpamAssassin::Conf manpage</a> for details.</p>
+<p>Note: the language cannot always be recognized with sufficient confidence.
+In that case, no action is taken.</p>
+<p>
+</p>
+<hr />
+<h1><a name="user_options">USER OPTIONS</a></h1>
+<dl>
+<dt><strong><a name="ok_languages_xx_yy_zz_default_all" class="item">ok_languages xx [ yy zz ... ]		(default: all)</a></strong></dt>
+
+<dd>
+<p>This option is used to specify which languages are considered okay for
+incoming mail.  SpamAssassin will try to detect the language used in the
+message body text.</p>
+<p>Note that the language cannot always be recognized with sufficient
+confidence. In that case, no action is taken.</p>
+<p>The rule <code>UNWANTED_LANGUAGE_BODY</code> is triggered if none of the languages
+detected are in the &quot;ok&quot; list. Note that this is the only effect of the
+&quot;ok&quot; list. It does not act as a whitelist against any other form of spam
+scanning.</p>
+<p>In your configuration, you must use the two or three letter language
+specifier in lowercase, not the English name for the language.  You may
+also specify <code>all</code> if a desired language is not listed, or if you want to
+allow any language.  The default setting is <code>all</code>.</p>
+<p>Examples:</p>
+<pre>
+  ok_languages all         (allow all languages)
+  ok_languages en          (only allow English)
+  ok_languages en ja zh    (allow English, Japanese, and Chinese)</pre>
+<p>Note: if there are multiple ok_languages lines, only the last one is used.</p>
+<p>Select the languages to allow from the list below:</p>
+<dl>
+<dt><strong><a name="af_afrikaans" class="item">af	- Afrikaans</a></strong></dt>
+
+<dt><strong><a name="am_amharic" class="item">am	- Amharic</a></strong></dt>
+
+<dt><strong><a name="ar_arabic" class="item">ar	- Arabic</a></strong></dt>
+
+<dt><strong><a name="be_byelorussian" class="item">be	- Byelorussian</a></strong></dt>
+
+<dt><strong><a name="bg_bulgarian" class="item">bg	- Bulgarian</a></strong></dt>
+
+<dt><strong><a name="bs_bosnian" class="item">bs	- Bosnian</a></strong></dt>
+
+<dt><strong><a name="ca_catalan" class="item">ca	- Catalan</a></strong></dt>
+
+<dt><strong><a name="cs_czech" class="item">cs	- Czech</a></strong></dt>
+
+<dt><strong><a name="cy_welsh" class="item">cy	- Welsh</a></strong></dt>
+
+<dt><strong><a name="da_danish" class="item">da	- Danish</a></strong></dt>
+
+<dt><strong><a name="de_german" class="item">de	- German</a></strong></dt>
+
+<dt><strong><a name="el_greek" class="item">el	- Greek</a></strong></dt>
+
+<dt><strong><a name="en_english" class="item">en	- English</a></strong></dt>
+
+<dt><strong><a name="eo_esperanto" class="item">eo	- Esperanto</a></strong></dt>
+
+<dt><strong><a name="es_spanish" class="item">es	- Spanish</a></strong></dt>
+
+<dt><strong><a name="et_estonian" class="item">et	- Estonian</a></strong></dt>
+
+<dt><strong><a name="eu_basque" class="item">eu	- Basque</a></strong></dt>
+
+<dt><strong><a name="fa_persian" class="item">fa	- Persian</a></strong></dt>
+
+<dt><strong><a name="fi_finnish" class="item">fi	- Finnish</a></strong></dt>
+
+<dt><strong><a name="fr_french" class="item">fr	- French</a></strong></dt>
+
+<dt><strong><a name="fy_frisian" class="item">fy	- Frisian</a></strong></dt>
+
+<dt><strong><a name="ga_irish_gaelic" class="item">ga	- Irish Gaelic</a></strong></dt>
+
+<dt><strong><a name="gd_scottish_gaelic" class="item">gd	- Scottish Gaelic</a></strong></dt>
+
+<dt><strong><a name="he_hebrew" class="item">he	- Hebrew</a></strong></dt>
+
+<dt><strong><a name="hi_hindi" class="item">hi	- Hindi</a></strong></dt>
+
+<dt><strong><a name="hr_croatian" class="item">hr	- Croatian</a></strong></dt>
+
+<dt><strong><a name="hu_hungarian" class="item">hu	- Hungarian</a></strong></dt>
+
+<dt><strong><a name="hy_armenian" class="item">hy	- Armenian</a></strong></dt>
+
+<dt><strong><a name="id_indonesian" class="item">id	- Indonesian</a></strong></dt>
+
+<dt><strong><a name="is_icelandic" class="item">is	- Icelandic</a></strong></dt>
+
+<dt><strong><a name="it_italian" class="item">it	- Italian</a></strong></dt>
+
+<dt><strong><a name="ja_japanese" class="item">ja	- Japanese</a></strong></dt>
+
+<dt><strong><a name="ka_georgian" class="item">ka	- Georgian</a></strong></dt>
+
+<dt><strong><a name="ko_korean" class="item">ko	- Korean</a></strong></dt>
+
+<dt><strong><a name="la_latin" class="item">la	- Latin</a></strong></dt>
+
+<dt><strong><a name="lt_lithuanian" class="item">lt	- Lithuanian</a></strong></dt>
+
+<dt><strong><a name="lv_latvian" class="item">lv	- Latvian</a></strong></dt>
+
+<dt><strong><a name="mr_marathi" class="item">mr	- Marathi</a></strong></dt>
+
+<dt><strong><a name="ms_malay" class="item">ms	- Malay</a></strong></dt>
+
+<dt><strong><a name="ne_nepali" class="item">ne	- Nepali</a></strong></dt>
+
+<dt><strong><a name="nl_dutch" class="item">nl	- Dutch</a></strong></dt>
+
+<dt><strong><a name="no_norwegian" class="item">no	- Norwegian</a></strong></dt>
+
+<dt><strong><a name="pl_polish" class="item">pl	- Polish</a></strong></dt>
+
+<dt><strong><a name="pt_portuguese" class="item">pt	- Portuguese</a></strong></dt>
+
+<dt><strong><a name="qu_quechua" class="item">qu	- Quechua</a></strong></dt>
+
+<dt><strong><a name="rm_rhaeto_romance" class="item">rm	- Rhaeto-Romance</a></strong></dt>
+
+<dt><strong><a name="ro_romanian" class="item">ro	- Romanian</a></strong></dt>
+
+<dt><strong><a name="ru_russian" class="item">ru	- Russian</a></strong></dt>
+
+<dt><strong><a name="sa_sanskrit" class="item">sa	- Sanskrit</a></strong></dt>
+
+<dt><strong><a name="sco_scots" class="item">sco	- Scots</a></strong></dt>
+
+<dt><strong><a name="sk_slovak" class="item">sk	- Slovak</a></strong></dt>
+
+<dt><strong><a name="sl_slovenian" class="item">sl	- Slovenian</a></strong></dt>
+
+<dt><strong><a name="sq_albanian" class="item">sq	- Albanian</a></strong></dt>
+
+<dt><strong><a name="sr_serbian" class="item">sr	- Serbian</a></strong></dt>
+
+<dt><strong><a name="sv_swedish" class="item">sv	- Swedish</a></strong></dt>
+
+<dt><strong><a name="sw_swahili" class="item">sw	- Swahili</a></strong></dt>
+
+<dt><strong><a name="ta_tamil" class="item">ta	- Tamil</a></strong></dt>
+
+<dt><strong><a name="th_thai" class="item">th	- Thai</a></strong></dt>
+
+<dt><strong><a name="tl_tagalog" class="item">tl	- Tagalog</a></strong></dt>
+
+<dt><strong><a name="tr_turkish" class="item">tr	- Turkish</a></strong></dt>
+
+<dt><strong><a name="uk_ukrainian" class="item">uk	- Ukrainian</a></strong></dt>
+
+<dt><strong><a name="vi_vietnamese" class="item">vi	- Vietnamese</a></strong></dt>
+
+<dt><strong><a name="yi_yiddish" class="item">yi	- Yiddish</a></strong></dt>
+
+<dt><strong><a name="chinese" class="item">zh	- Chinese (both Traditional and Simplified)</a></strong></dt>
+
+<dt><strong>zh.big5	- Chinese (Traditional only)</strong></dt>
+
+<dt><strong>zh.gb2312	- Chinese (Simplified only)</strong></dt>
+
+</dl>
+<p></p>
+</dd>
+<dt><strong><a name="inactive_languages_xx_yy_zz_default_see_below" class="item">inactive_languages xx [ yy zz ... ]		(default: see below)</a></strong></dt>
+
+<dd>
+<p>This option is used to specify which languages will not be considered
+when trying to guess the language.  For performance reasons, supported
+languages that have fewer than about 5 million speakers are disabled by
+default.  Note that listing a language in <code>ok_languages</code> automatically
+enables it for that user.</p>
+<p>The default setting is:</p>
+<dl>
+<dt><strong><a name="bs_cy_eo_et_eu_fy_ga_gd_is_la_lt_lv_rm_sa_sco_sl_yi" class="item">bs cy eo et eu fy ga gd is la lt lv rm sa sco sl yi</a></strong></dt>
+
+</dl>
+<p>That list is Bosnian, Welsh, Esperanto, Estonian, Basque, Frisian, Irish
+Gaelic, Scottish Gaelic, Icelandic, Latin, Lithuanian, Latvian,
+Rhaeto-Romance, Sanskrit, Scots, Slovenian, and Yiddish.</p>
+</dd>
+<dt><strong><a name="n" class="item">textcat_max_languages N (default: 3)</a></strong></dt>
+
+<dd>
+<p>The maximum number of languages any one message can simultaneously match
+before its classification is considered unknown.</p>
+</dd>
+<dt><strong>textcat_optimal_ngrams N (default: 0)</strong></dt>
+
+<dd>
+<p>If the number of ngrams is lower than this number then they will be removed.  This
+can be used to speed up the program for longer inputs.  For shorter inputs, this
+should be set to 0.</p>
+</dd>
+<dt><strong>textcat_max_ngrams N (default: 400)</strong></dt>
+
+<dd>
+<p>The maximum number of ngrams that should be compared with each of the languages
+models (note that each of those models is used completely).</p>
+</dd>
+<dt><strong>textcat_acceptable_score N (default: 1.02)</strong></dt>
+
+<dd>
+<p>Include any language that scores at least <code>textcat_acceptable_score</code> in the
+returned list of languages.</p>
+</dd>
+</dl>
+
+</body>
+
+</html>