NAME

Mail::SpamAssassin::Plugin::LDAPfilter - an LDAP-based blacklist engine for SpamAssassin


DESCRIPTION

This plugin checks an LDAP directory for entries and attributes that are associated with specific message resource, and assigns SpamAssassin scores to the message according to the values that are returned.


SYNOPSIS

  loadplugin Mail::SpamAssassin::Plugin::LDAPfilter ldapfilter.pm
  header LDAP_IP_FROM_BLACK       eval:ldap_ip_from_blacklisted()
  describe LDAP_IP_FROM_BLACK     Checks SMTP client IP for blacklist
  tflags LDAP_IP_FROM_BLACK       net
  score LDAP_IP_FROM_BLACK        50.0


INTRODUCTION

This plugin was developed for the purpose of being able to store blacklist and whitelist data in an LDAP server. It was originally intended to provide a way to reuse the Postfix LDAP filters inside SpamAssassin, but has subsequently detoured into becoming a generalized front-end for LDAP filtering mechanisms in SpamAssassin.

Using this plugin, the author is able to:

Essentially, any domain name, email address, IP subnet (CIDR masking) or IP octet grouping can be assigned a blacklist, darklist, lightlist or whitelist attribute value, with the cumulative set of values determining the score that is returned to SpamAssassin.

For the author's network, most of this functionality was originally provided with various Postfix filters, or was provided with static blacklist and whitelist entries inside SpamAssassin. Both of those mechanisms are certainly capable of providing important features, but neither of them worked well enough for the author's purposes. In particular, Postfix has a very powerful filtering model, but those filters are not available to SpamAssassin (EG, they have diferent ``whitelist'' filtering tools). Meanwhile, the filtering mechanisms in SpamAssassin are not reusable across machine and account boundaries easily (without using something like NFS anyway), and don't provide much granularity. Thus, LDAPfilter was originally designed to makea Postfix LDAP filters available to SpamAssassin so that they could be shared, but has since been developed as its own LDAP-based blacklisting tool.

A visual representation of a typical LDAP entry and its associated attributes is shown below:

     mailFilterName = ietf.org
      |
      +-spamAssassinFilterClient = LIGHTLISTED
      |
      +-spamAssassinFilter822To = LIGHTLISTED

In the example shown above, an email message that was determined to have been sent by a computer in the ``ietf.org'' domain (as determined from the SMTP client reverse-DNS domain name) would match for the ``LIGHTLISTED'' score, as would messages with an RFC-822 To: or Cc: header field value containing ``ietf.org''. Messages that matched both of those resource- specific filters would get two LIGHTLISTED scores, which would combine.

Another example is shown below:

    cn=Spammers
      |
      +-mailFilterName = cnchost.com
      |
      +-mailFilterName = mypcclub.net
      |
      +-spamAssassinFilterClient = BLACKLISTED
      |
      +-spamAssassinFilterEnvFrom = BLACKLISTED

In the example shown above, there is a single entry for problematic spam sources (cn=Spammers), which has multiple mailFilterName attributes that each identify a known spammer resource (domain names are shown here, but almost any resource can be used). Hosts that have reverse-DNS domain names are caught and flagged by the spamAssassinFilterClient attribute, while email adddresses from the SMTP envelope ``MAIL FROM'' command are trapped by the spamAssassinFilterEnvFrom attribute.

Using this model, the author is able to define global entries that are accessible to all of the front-line SMTP servers, while users are also able to define additional entries in their personal LDAP views.


FUNCTIONAL OVERVIEW

When an email message is examined by a version of SpamAssassin that incorporates this plugin, the data values associated with some of the message resources will be read (EG, the contents of a From: header), and LDAP queries for those resources will be generated. If any entries are found for the resource or one of its delegation parents (such as the mail-domain from a discovered email address), those entries are examined to see if they contain any of the user-specified LDAP attributes. If those attributes exist, the attribute values are also examined to see if they match with the user-specified matching values. If that match also succeeds, one or more user-specified SpamAssassin scores are assigned to the message, with the final score depending on the number of matches and their user-assigned scores.

There are several important components to this model:

Message resources
By default, LDAPfilter parses a message for information that is commonly used for blacklisting purposes. In particular, it looks for the IPv4 address and reverse DNS domain name of the SMTP client, the HELO identifier used in the SMTP session, the email addresses that were provided in the SMTP envelope (``MAIL FROM'' and ``RCPT TO''), and the email addresses that were provided in the RFC-822 message header (specifically including the From:, Reply-To:, To: and Cc: headers).

The data values for each resource are used to build LDAP searches for those resources and their delegation parents. These searches are then submitted to the LDAP server for processing.

Each of the supported resource types can have their type-specific searches disabled as the operator sees fit, and operators also have control over the depth of resource recursion that takes place.

Note that LDAPfilter does not currently support IPv6 addresses, but this is on the author's to-do list. Theoretically, this same model can also be applied to additional header fields and even body data, but this potential capability has not been developed upon.

LDAP schema
LDAPfilter makes use of several different LDAP attributes, which can each be manually defined if needed.

In order to ensure efficient searching, LDAPfilter looks for entries that have a specific naming attribute. By default, the naming attribute is ``mailFilterName'', but this can be overridden in the configuration settings on a global basis, or on a type-specific basis if you already have entries and attributes that you want to match against.

When entries are returned for any of the searches, LDAPfilter also looks to see if there is also a resource-specific attribute assigned to each entry (for example, searches for email addresses from the ``From:'' header field will also be filtered by looking for the presence of a ``spamAssassinFilter822From'' attribute by default). Each of the resource-specific filtering attributes can be defined in the configuration options if needed.

If the resource-specific attribute is found, its value is read and compared against the local filtering syntax. The four values that are used by default are ``BLACKLISTED'', ``DARKLISTED'', ``LIGHTLISTED'' and ``WHITELISTED'', but these can also be overridden if needed.

A schema file for LDAPfilter that is suitable for use with OpenLDAP is available at http://www.ntrg.com/software/spamassassin-ldapfilter/

Configuration syntax settings for overriding the default LDAP attributes and values are provided further ahead.

SpamAssassin rules and scoring values
The ldapfilter.cf file contains all of the SpamAssassin rules that define the actual scores which are eventually assigned to each of the specific matches. By default, each of the resource-specific searches have four rules, each of which provide a score based on whether or not the LDAP filter attribute exists with the defined matching value.

The score for each rule and resource can be adjusted as needed by changing the relevant score. The deafult for all rules are as shown above, but it may make sense to change some rules for your specific environment. For example, it may be useful to assign different scores for Reply-To: header fields than MAIL-FROM envelope data which is verified with SPF.

A SpamAssassin rules file for LDAPfilter is available at http://www.ntrg.com/software/spamassassin-ldapfilter/

Plugin configuration options
There are numerous options that can be defined for LDAPfilter. Among these options are the ability to override all of the LDAP attributes and schema, configuration statements that govern the LDAP session and its related parameters, whether or not sessions should be maintained across multiple messages, control over the recursion behavior, and so forth.

LDAPfilter is designed to operate without needing explicit option statements, but some option definitions are usually required for basic LDAP connectivity. By default, LDAPfilter will try to connect to port 389 on localhost, and will try to perform an anonymous bind, and will also try to use the base DN returned by the server as the search base. However, this only works if your instance of SpamAssassin is running on the same host as your LDAP server and if the anonymous user has read acccess rights to the attributes. While feasible, these assumptions are not likely to work in all cases. Furthermore, there are several performance-boosting configuration statements that should also be defined, such as defining the search base for queries to use (thereby preventing the whole tree from being searched on each query).

A sample configuration file for LDAPfilter is available at http://www.ntrg.com/software/spamassassin-ldapfilter/

The specific options are discussed in more detail further ahead in this document.


CONFIGURATION

Configuration options override the default values.

The configuration option statements follow a simple structure of:

    name    value

Option names are case-neutral. Some option values are case-neutral (especially the ``on|off'' toggles), while some option values are not (passwords and such).

Option values can be enclosed in single- or double-quotes if needed, and the quotes will be stripped on read.

A default configuration file is available at http://www.ntrg.com/software/spamassassin-ldapfilter/

Do not place this file into the master SpamAssassin folder tree, as those folders are deleted whenever SpamAssassin is upgraded.

LDAP Session Options

The session defaults should be fine if (1) your LDAP server can be found with DNS lookups for the LDAP SRV resource record, (2) anonymous has search rights, and (3) you are using the bundled LDAP schema. If any of those assumptions are false, you will need to define the relevant setting(s).

You will probably need to define the ldapfilter_ldap_search_base option, since the default behavior is to probe for a namingContext attribute in the rootDSE object. This doesn't always work, and searches from the root of the tree will be much slower than searches that start in the target container.

Note that DNS lookups for LDAP SRV resource records will not overwrite an explicit port number setting. This is usually important with LDAP-over-SSL connections, which tend to use a different port number than the one that is associated with SRV entries.

    ldapfilter_ldap_transport             ldap  # ldap|ldaps|ldapi
    ldapfilter_ldap_server                ""    # use LDAP SRV data
    ldapfilter_ldap_port                  ""    # use LDAP SRV data
    ldapfilter_ldap_version               3
    ldapfilter_ldap_bind_dn               ""    # use anonymous bind
    ldapfilter_ldap_bind_password         ""    # use anonymous bind
    ldapfilter_ldap_search_base           ""    # use the namingContext
    ldapfilter_ldap_search_scope          sub   # base|one|sub
    ldapfilter_ldap_search_deref          never # never|search|find|always

Supported connection methods include ``ldaps'' (for LDAP-over-SSL security) and ``ldapi'' (for LDAP-over-UNIX sockets performance).

LDAPS sessions don't do any certificate validation by default. You shouldn't need to enable certificate validation unless you plan to use a server that is not under your direct control, but if you do enable it you may also need to adjust ldapfilter_ldap_ssl_capath to use your CA certificate store.

    ldapfilter_ldap_ssl_verify            none  # none|optional|require
    ldapfilter_ldap_ssl_capath            /etc/ssl/certs/

If you want to use LDAPI, you will almost certainly need to specify the path to your local server's UNIX domain socket, since the default is practically guaranteed to be wrong (don't forget to double-check ACL permissions for the ldapi socket... mine didn't work).

    ldapfilter_ldap_ldapi_path            /var/run/slapd/ldapi

'ldapfilter_ldap_timeout' says how long to wait (in seconds) for an LDAP operation to succeed before giving up on it. The default values in Net::LDAP are much higher than the values used here, because we have to consider the negative impact that timeouts have on SpamAssassin and related processes. Generally speaking it is better for us to suicide early than to cause other processes to die by making them wait too long.

    ldapfilter_ldap_timeout               5     # timeout value in seconds

'ldapfilter_ldap_persistency' controls whether or not the LDAP session is killed after the searches complete. Enabling this feature avoids the need to connect and login for every lookup process, which significantly reduces the overall task-completion times. However, this is really only meaningful if SpamAssassin itself is running in persistent mode (eg, using spamd).

    ldapfilter_ldap_persistency           off   # on|off

'ldapfilter_ldap_search_mode' determines whether the resource-specific searches are performed one-at-a-time or as a batch. In 'single' mode, the original resource name and all of its delegation parent names are searched individually. In 'batch' mode, the resource name and all of its delegation parent names are combined into a single LDAP search filter, using the LDAP 'OR' operator. Batch searches avoid some latency delays and also require fewer network resources, but the queries are harder for LDAP servers to process than simplistic equality filters.

    ldapfilter_ldap_search_mode           batch # batch|single

LDAP Schema Options

The *_match_attr options are used for name-based matching. By default, all searches first try to find a match with ``(mailFilterName = $resource)'', but you can redefine that global attribute if you want. You can also define the three major resource-type (IP address, hostname, and email address), matching attributes too, and those will be used in the appropriate places. For example, if you define ldapfilter_ldap_email_match_attr to ``mail'' (thus reusing the ``mail'' attribute from the inetOrgPerson objectclass), searches for email addresses will use ``(mail = $resource)'', while the rest of the searches will still use whatever has been assinged to the global matching attribute (assuming they are also undefined, of course). Note that the heuristic matching uses simple regular expression analysis (digits and dots are likely to be IP addresses...), and this can fail in a couple of places (ie, an email address without an @domain qualifier looks just like a domain name), so consider this to be experimental.

    ldapfilter_ldap_match_attr            mailFilterName
    ldapfilter_ldap_ip_match_attr         ""
    ldapfilter_ldap_dns_match_attr        ""
    ldapfilter_ldap_email_match_attr      ""

Once a match has been found, the entries are examined to see if they have an appropriate LDAP attribute for the filter-type in use. The default attribute names for this comparison are from the default schema (and are also shown below), but you can also define your own if you want.

    ldapfilter_ldap_ip_from_attr          spamAssassinFilterClient
    ldapfilter_ldap_rdns_from_attr        spamAssassinFilterClient
    ldapfilter_ldap_helo_from_attr        spamAssassinFilterHelo
    ldapfilter_ldap_env_from_attr         spamAssassinFilterEnvFrom
    ldapfilter_ldap_env_to_attr           spamAssassinFilterEnvTo
    ldapfilter_ldap_msg_from_attr         spamAssassinFilter822From
    ldapfilter_ldap_msg_rplyto_attr       spamAssassinFilter822RplyTo
    ldapfilter_ldap_msg_tocc_attr         spamAssassinFilter822To
    ldapfilter_ldap_msg_uri_attr          spamAssassinFilter822Uri

The attribute values to match against for scoring purposes, which you will probably need to define if you also defined your own attributes.

    ldapfilter_ldap_blacklist_val         BLACKLISTED
    ldapfilter_ldap_darklist_val          DARKLISTED
    ldapfilter_ldap_lightlist_val         LIGHTLISTED
    ldapfilter_ldap_whitelist_val         WHITELISTED

Resource- and Type-Specific Options

The following options determine whether or not the plug-in even bothers to generate queries for certain resource types. Note that disabling a rule will not have this result, since *all* of the queries are built and issued once any rule is called. In order to eliminate a whole class of resource queries, you have to tell the plug-in which ones it should not bother with. As far as SpamAssassin is concerned, the related rules just seem to always return ``no match''. Note that all of these options default to the ``on'' toggle position.

    ldapfilter_search_ip_from             on    # on|off
    ldapfilter_search_rdns_from           on    # on|off
    ldapfilter_search_helo_from           on    # on|off
    ldapfilter_search_env_from            on    # on|off
    ldapfilter_search_env_to              on    # on|off
    ldapfilter_search_msg_from            on    # on|off
    ldapfilter_search_msg_rplyto          on    # on|off
    ldapfilter_search_msg_tocc            on    # on|off
    ldapfilter_search_msg_uri             on    # on|off

The next two options specify the header fields where we should look for envelope sender and recipient data, as provided in the SMTP 'MAIL FROM' and 'RCPT TO' envelope exchange. By default, we'll look for the envelope sender in the 'Return-Path' header field, but you can override that with another header field in the 'ldapfilter_env_from_header' option. There is no standardized header for envelope recipient data, so we don't have a reasonable starting point for that. If you can configure your server to generate something like an X-Envelope-To, specify the name of that header field here. Note that envelope recipient checks won't be done until this option is set, regardless of the 'ldapfilter_search_env_to' option.

    ldapfilter_env_from_header            ""    # not used
    ldapfilter_env_to_header              ""    # not used

'ldapfilter_recipient_limit' sets a cap on the number of recipient addresses that will be searched (``0'' is no limit). Note that this count specifically applies to LDAP searches, and not to addresses that are filtered out before a search takes place (see ldapfilter_recipient_filter), nor does it affect name recursion (see ldapfilter_recursion_limit). Keep in mind that large lists of names that are infinitely recursed will negatively affect the cumulative amount of time required to process a message, and long operations can trigger timeouts in SpamAssassin or related processes. For this reason, the default value for this settings is ``10'' instead of ``0''.

    ldapfilter_recipient_limit            10    # "0" = no limit

'ldapfilter_recipient_filter' provides a domain name mask for recipient addresses, in case you only want to check the blacklist database for a specific domain.

    ldapfilter_recipient_filter           ""    # not used

'ldapfilter_cidr_lookups' determines if parent IPv4 netblocks are located by CIDR matching (``on''), or if they are located by simply chopping the right-most octet from the address (``off''). Using CIDR lookups provides fine-granularity filters, but imposes significant resource requirements on the search operation, since there are 22 possible CIDR prefixes for each address (these are the initial /32, and the subsequent lookups for /29 through /8). Disabling CIDR lookups is much faster and lighter, and it uses the same logic as found in postfix filters (meaning you can share filter entries), but it is a very rough-grained filtering mechanism. One other consideration to keep in mind here is the potential for negative interaction with 'ldapfilter_recursion_limit', which can cause the CIDR matching to stop short of the full /8 lookups.

    ldapfilter_cidr_lookups               on    # on|off

'ldapfilter_recursion_limit' determines how many levels of a resource name will be searched for a match (``0'' is no limit, meaning that every element in the name can be searched). One level of recursion is often enough to match against a parent domain or net-block if the email address or host IP address didn't match an explicit entry, but this doesn't work when the resource name is deeply nested. Also remember that recursion stops when all of the elements in the name have been exhausted, so infinite recursion never really is infinite.

    ldapfilter_recursion_limit            0     # "0" = no limit

'ldapfilter_verify_resources' determines if malformed resources should be processed or discarded. If this option is enabled (the default setting), malformed IP addresses, domain names and email addresses will be ignored instead of being searched. Although some spammers are known to purposely generate malformed data in an effort to escape repurcussions for their prior acts, there are some potential security risks in allowing random strings of characters to be passed in LDAP queries, so we default to the safe position.

    ldapfilter_verify_resources           on    # on|off


RULES AND SCORES

LDAPfilter ``works'' by defining SpamAssassin rules that are called as a message is processed. Each rule that matches returns a score for that rule.

Note that disabling a rule does not prevent a search from being executed. LDAPfilter uses a single instance of a message and an LDAP session, so if any rule is called all of them will get processed. If you want to actually stop a rule from being executed (as opposed to not being scored), use the appropriate option(s) described in the preceeding section.

Note that SpamAssassin requires that rules and score values be defined in a .cf file that can be found by SpamAssassin on startup.

A default ruleset and scoring file is available at http://www.ntrg.com/software/spamassassin-ldapfilter/

Do not place this file into the master SpamAssassin folder tree, as those folders are deleted whenever SpamAssassin is upgraded.

SMTP Client IP Address

Blacklist/whitelist mail from IP networks. Note that there's no way to corollate remote IP addresses to their real CIDR netblocks, so all matching has to occur on octet boundaries.

    header LDAP_IP_FROM_BLACK       eval:ldap_ip_from_blacklisted()
    describe LDAP_IP_FROM_BLACK     Checks SMTP client IP for blacklist
    tflags LDAP_IP_FROM_BLACK       net
    score LDAP_IP_FROM_BLACK        50.0
    header LDAP_IP_FROM_DARK        eval:ldap_ip_from_darklisted()
    describe LDAP_IP_FROM_DARK      Checks SMTP client IP for darklist
    tflags LDAP_IP_FROM_DARK        net
    score LDAP_IP_FROM_DARK         10.0
    header LDAP_IP_FROM_LIGHT       eval:ldap_ip_from_lightlisted()
    describe LDAP_IP_FROM_LIGHT     Checks SMTP client IP for lightlist
    tflags LDAP_IP_FROM_LIGHT       net
    score LDAP_IP_FROM_LIGHT        -20.0
    header LDAP_IP_FROM_WHITE       eval:ldap_ip_from_whitelisted()
    describe LDAP_IP_FROM_WHITE     Checks SMTP client IP for whitelist
    tflags LDAP_IP_FROM_WHITE       net
    score LDAP_IP_FROM_WHITE        -100.0

SMTP Client Reverse-DNS Domain Name

Blacklist/whitelist mail associated with a domain name, as determined by reverse DNS lookups. This is useful if you're trying to list an organization with multiple or frequently-changing network assingments.

    header LDAP_RDNS_FROM_BLACK     eval:ldap_rdns_from_blacklisted()
    describe LDAP_RDNS_FROM_BLACK   Checks SMTP client rDNS for blacklist
    tflags LDAP_RDNS_FROM_BLACK     net
    score LDAP_RDNS_FROM_BLACK      50.0
    header LDAP_RDNS_FROM_DARK      eval:ldap_rdns_from_darklisted()
    describe LDAP_RDNS_FROM_DARK    Checks SMTP client rDNS for darklist
    tflags LDAP_RDNS_FROM_DARK      net
    score LDAP_RDNS_FROM_DARK       10.0
    header LDAP_RDNS_FROM_LIGHT     eval:ldap_rdns_from_lightlisted()
    describe LDAP_RDNS_FROM_LIGHT   Checks SMTP client rDNS for lightlist
    tflags LDAP_RDNS_FROM_LIGHT     net
    score LDAP_RDNS_FROM_LIGHT      -20.0
    header LDAP_RDNS_FROM_WHITE     eval:ldap_rdns_from_whitelisted()
    describe LDAP_RDNS_FROM_WHITE   Checks SMTP client rDNS for whitelist
    tflags LDAP_RDNS_FROM_WHITE     net
    score LDAP_RDNS_FROM_WHITE      -100.0

SMTP Client HELO Identifier

HELO domains are often forged. One feature of this is that you can add a blacklist entry for your own mail server netblock or reverse domain name, and catch spammers that are trying to pass themselves off as you. You might also need to whitelist important mail servers that use malformed or illegal HELO identifiers (such as a small business behind a NAT). Keep in mind that these can all be forged, so it's best to just lightlist them.

    header LDAP_HELO_FROM_BLACK     eval:ldap_helo_from_blacklisted()
    describe LDAP_HELO_FROM_BLACK   Checks SMTP client HELO for blacklist
    tflags LDAP_HELO_FROM_BLACK     net
    score LDAP_HELO_FROM_BLACK      50.0
    header LDAP_HELO_FROM_DARK      eval:ldap_helo_from_darklisted()
    describe LDAP_HELO_FROM_DARK    Checks SMTP client HELO for darklist
    tflags LDAP_HELO_FROM_DARK      net
    score LDAP_HELO_FROM_DARK       10.0
    header LDAP_HELO_FROM_LIGHT     eval:ldap_helo_from_lightlisted()
    describe LDAP_HELO_FROM_LIGHT   Checks SMTP client HELO for lightlist
    tflags LDAP_HELO_FROM_LIGHT     net
    score LDAP_HELO_FROM_LIGHT      -20.0
    header LDAP_HELO_FROM_WHITE     eval:ldap_helo_from_whitelisted()
    describe LDAP_HELO_FROM_WHITE   Checks SMTP client HELO for whitelist
    tflags LDAP_HELO_FROM_WHITE     net
    score LDAP_HELO_FROM_WHITE      -100.0

SMTP Envelope MAIL-FROM Command

Not really trustworthy except for bulk marketers that use a ``real'' email address that can be blacklisted. These can also be ``validated'' with SPF.

    header LDAP_ENV_FROM_BLACK      eval:ldap_env_from_blacklisted()
    describe LDAP_ENV_FROM_BLACK    Checks SMTP MAIL-FROM address for blacklist
    tflags LDAP_ENV_FROM_BLACK      net
    score LDAP_ENV_FROM_BLACK       50.0
    header LDAP_ENV_FROM_DARK       eval:ldap_env_from_darklisted()
    describe LDAP_ENV_FROM_DARK     Checks SMTP MAIL-FROM address for darklist
    tflags LDAP_ENV_FROM_DARK       net
    score LDAP_ENV_FROM_DARK        10.0
    header LDAP_ENV_FROM_LIGHT      eval:ldap_env_from_lightlisted()
    describe LDAP_ENV_FROM_LIGHT    Checks SMTP MAIL-FROM address for lightlist
    tflags LDAP_ENV_FROM_LIGHT      net
    score LDAP_ENV_FROM_LIGHT       -20.0
    header LDAP_ENV_FROM_WHITE      eval:ldap_env_from_whitelisted()
    describe LDAP_ENV_FROM_WHITE    Checks SMTP MAIL-FROM address for whitelist
    tflags LDAP_ENV_FROM_WHITE      net
    score LDAP_ENV_FROM_WHITE       -100.0

SMTP Envelope RCPT-TO Command

Envelope recipients are where the local message recipients are listed, so this is where you should filter on spamtrap addresses and the like. However, SpamAssassin does not currently provide this data itself, so if you want to use this feature, you must create an X-Envelope-To: header field in the message somehow (presumably with a ``create header'' function in your mail server), before the message is read by SpamAssassin.

    header LDAP_ENV_TO_BLACK        eval:ldap_env_to_blacklisted()
    describe LDAP_ENV_TO_BLACK      Checks SMTP RCPT-TO address for blacklist
    tflags LDAP_ENV_TO_BLACK        net
    score LDAP_ENV_TO_BLACK         50.0
    header LDAP_ENV_TO_DARK         eval:ldap_env_to_darklisted()
    describe LDAP_ENV_TO_DARK       Checks SMTP RCPT-TO address for darklist
    tflags LDAP_ENV_TO_DARK         net
    score LDAP_ENV_TO_DARK          10.0
    header LDAP_ENV_TO_LIGHT        eval:ldap_env_to_lightlisted()
    describe LDAP_ENV_TO_LIGHT      Checks SMTP RCPT-TO address for lightlist
    tflags LDAP_ENV_TO_LIGHT        net
    score LDAP_ENV_TO_LIGHT         -20.0
    header LDAP_ENV_TO_WHITE        eval:ldap_env_to_whitelisted()
    describe LDAP_ENV_TO_WHITE      Checks SMTP RCPT-TO address for whitelist
    tflags LDAP_ENV_TO_WHITE        net
    score LDAP_ENV_TO_WHITE         -100.0

RFC-822 Message From: Header Field

Not really trustworthy except for bulk marketers that use a ``real'' email address that can be blacklisted.

    header LDAP_MSG_FROM_BLACK      eval:ldap_msg_from_blacklisted()
    describe LDAP_MSG_FROM_BLACK    Checks RFC-822 From: address for blacklist
    tflags LDAP_MSG_FROM_BLACK      net
    score LDAP_MSG_FROM_BLACK       50.0
    header LDAP_MSG_FROM_DARK       eval:ldap_msg_from_darklisted()
    describe LDAP_MSG_FROM_DARK     Checks RFC-822 From: address for darklist
    tflags LDAP_MSG_FROM_DARK       net
    score LDAP_MSG_FROM_DARK        10.0
    header LDAP_MSG_FROM_LIGHT      eval:ldap_msg_from_lightlisted()
    describe LDAP_MSG_FROM_LIGHT    Checks RFC-822 From: address for lightlist
    tflags LDAP_MSG_FROM_LIGHT      net
    score LDAP_MSG_FROM_LIGHT       -20.0
    header LDAP_MSG_FROM_WHITE      eval:ldap_msg_from_whitelisted()
    describe LDAP_MSG_FROM_WHITE    Checks RFC-822 From: address for whitelist
    tflags LDAP_MSG_FROM_WHITE      net
    score LDAP_MSG_FROM_WHITE       -100.0

RFC-822 Message Reply-To: Header Field

Some idiots try to hide their ``From:'' identity but will still provide a ``Reply-To:'' header with their real address. I use this to catch Nigerian spam for Yahoo mail accounts and such, while lightlisting From: headers from people I know. Note that some mailing groups are also known to use this header.

    header LDAP_MSG_RPLYTO_BLACK    eval:ldap_msg_rplyto_blacklisted()
    describe LDAP_MSG_RPLYTO_BLACK  Checks RFC-822 Reply-To: address for blacklist
    tflags LDAP_MSG_RPLYTO_BLACK    net
    score LDAP_MSG_RPLYTO_BLACK     50.0
    header LDAP_MSG_RPLYTO_DARK     eval:ldap_msg_rplyto_darklisted()
    describe LDAP_MSG_RPLYTO_DARK   Checks RFC-822 Reply-To: address for darklist
    tflags LDAP_MSG_RPLYTO_DARK     net
    score LDAP_MSG_RPLYTO_DARK      10.0
    header LDAP_MSG_RPLYTO_LIGHT    eval:ldap_msg_rplyto_lightlisted()
    describe LDAP_MSG_RPLYTO_LIGHT  Checks RFC-822 Reply-To: address for lightlist
    tflags LDAP_MSG_RPLYTO_LIGHT    net
    score LDAP_MSG_RPLYTO_LIGHT     -20.0
    header LDAP_MSG_RPLYTO_WHITE    eval:ldap_msg_rplyto_whitelisted()
    describe LDAP_MSG_RPLYTO_WHITE  Checks RFC-822 Reply-To: address for whitelist
    tflags LDAP_MSG_RPLYTO_WHITE    net
    score LDAP_MSG_RPLYTO_WHITE     -100.0

RFC-822 Message To: and Cc: Header Fields

These are useful if you want to blacklist a spamtrap address, or if you want to whitelist all traffic going to a mailing list address (the latter is particularly useful with SpamAssassin's auto-whitelist feature, since any private replies to you and the mailing list will both be flagged, with the message sender inheriting the benefit of the whitelist score). If you plan to make heavy use of this ruleset, make sure that ldapfilter_rcpt_limit is not set to too low a value, or else you might miss some hits.

    header LDAP_MSG_TO_BLACK        eval:ldap_msg_tocc_blacklisted()
    describe LDAP_MSG_TO_BLACK      Checks RFC-822 To:/Cc: addresses for blacklist
    tflags LDAP_MSG_TO_BLACK        net
    score LDAP_MSG_TO_BLACK         50.0
    header LDAP_MSG_TO_DARK         eval:ldap_msg_tocc_darklisted()
    describe LDAP_MSG_TO_DARK       Checks RFC-822 To:/Cc: addresses for darklist
    tflags LDAP_MSG_TO_DARK         net
    score LDAP_MSG_TO_DARK          10.0
    header LDAP_MSG_TO_LIGHT        eval:ldap_msg_tocc_lightlisted()
    describe LDAP_MSG_TO_LIGHT      Checks RFC-822 To:/Cc: addresses for lightlist
    tflags LDAP_MSG_TO_LIGHT        net
    score LDAP_MSG_TO_LIGHT         -20.0
    header LDAP_MSG_TO_WHITE        eval:ldap_msg_tocc_whitelisted()
    describe LDAP_MSG_TO_WHITE      Checks RFC-822 To:/Cc: addresses for whitelist
    tflags LDAP_MSG_TO_WHITE        net
    score LDAP_MSG_TO_WHITE         -100.0

RFC-822 Message Body URI

These are useful if you want to blacklist a particular URI. Currently these tests only look at http: and mailto: URIs. For mailto links, the test first tries the complete URI, then the email address, and then recurses through the mail domain hierarchy. For http links, the test first tries the complete URI then recursively removes each path element, then any embedded authentication information, then the port number element, and finally recurses through the domain hierarchy.

    header LDAP_MSG_URI_BLACK       eval:ldap_msg_uri_blacklisted()
    describe LDAP_MSG_URI_BLACK     Checks RFC-822 message URIs for blacklist
    tflags LDAP_MSG_URI_BLACK       net
    score LDAP_MSG_URI_BLACK        50.0
    header LDAP_MSG_URI_DARK        eval:ldap_msg_uri_darklisted()
    describe LDAP_MSG_URI_DARK      Checks RFC-822 message URIs for darklist
    tflags LDAP_MSG_URI_DARK        net
    score LDAP_MSG_URI_DARK         10.0
    header LDAP_MSG_URI_LIGHT       eval:ldap_msg_uri_lightlisted()
    describe LDAP_MSG_URI_LIGHT     Checks RFC-822 message URIs for lightlist
    tflags LDAP_MSG_URI_LIGHT       net
    score LDAP_MSG_URI_LIGHT        -20.0
    header LDAP_MSG_URI_WHITE       eval:ldap_msg_uri_whitelisted()
    describe LDAP_MSG_URI_WHITE     Checks RFC-822 message URIs for whitelist
    tflags LDAP_MSG_URI_WHITE       net
    score LDAP_MSG_URI_WHITE        -100.0


REQUIREMENT

Requires SpamAssassin 3.0.x and Net::LDAP

Optional features separately require Net::LDAPS and Net::LDAPI, Net::DNS, and Sys::Hostname::Long