Blocking Spam in Exim with URI Block Lists

Current Version: 2.3
Released: 06 Mar 12

Written and maintained by Erik Mugele.

Introduction | Exim Configuration | Script Installation
License | Download | Change Log


This document describes using SURBL (Spam URI Realtime Blocklists), URIBL, and the Spamhaus DBL in conjunction with the Exim MTA to block spam containing "spamvertizing" URLs. To achieve this, one can use the Perl script that is found below. This utilizes Exim's MIME and/or DATA ACLs and Exim's embedded Perl engine.

The Perl routine from this page should be relatively easy to modify to use in any other MTA that can call an external script to scan a message.

The SURBL, URIBL and Spamhaus DBL systems functions just like a normal DNSBL system but instead of containing a list of IPs of servers that send spam, they maintain a list of the domains that are found in the bodies of messages. These are the domains that are part of the URL the spammers want you to click on to buy their wares. It's quite an effective way of filtering for spam and can be used in conjunction with traditional DNSBLs for maximum effectiveness.

Exim Configuration

Exim MUST be compiled with the option to enable the embedded Perl engine. See Chapter 12 of the Exim Specification for details. By default, it is commented out in the official source distribution and thus will not be enabled when compiled. Exim's perl_startup runtime option is used to call the embedded Perl engine and define what file contains any Perl routines you want Exim to use. For example:

perl_startup=do '/etc/exim/'

In addition to scanning the body of a plain text mail message, the Perl subroutine can scan any MIME attachment if Exim is using the exiscan additions (included in Exim 4.60 and higher).

The following two ACLs are working examples of Exim MIME and DATA ACLs that call the Perl subroutine to scan the message for blacklisted domain names in URLs. See Chapter 40 of the Exim Specification for details on Exim ACLs.

MIME ACL - This ACL should go in the MIME ACL section of the Exim configuration.

   deny condition = ${if <{$message_size}{100000}{yes}{no}}
        set acl_m0 = ${perl{surblspamcheck}}
	condition = ${if eq{$acl_m0}{false}{no}{yes}}
        message = $acl_m0

DATA ACL - This ACL should go in the DATA ACL section of the Exim configuration.

   deny condition = ${if <{$message_size}{100000}{yes}{no}}
        condition = ${if eq{$acl_m0}{}{yes}{no}}
	set acl_m1 = ${perl{surblspamcheck}}
	condition = ${if eq{$acl_m1}{false}{no}{yes}}
        message = $acl_m1

The second condition statement in the DATA ACL above ensures that the DATA ACL is only called if no MIME ACL was called (i.e. there were no MIME parts). This keeps the message from being scanned inefficiently twice by both the MIME and DATA ACLs.

The following two Exim options should be set in the main configuration area:

message_body_visible = 5000
message_body_newlines = true

The message_body_visible option will determine how much of of the body is scanned during the DATA ACL and the default value won't catch much. A value of 5000 is recommended.

The message_body_newlines option should be set to "true". This ensures the message body will be parsed correctly.

Script Installation and Configuration

Download and extract the contents of the gzipped tar file (see below). The archive contains four files:

If this is the only Perl subroutine in the Exim installation, copy to the location specified in the perl_startup Exim configuration setting (mentioned above). If other subroutines are in use, append the contents of to the existing file defined in perl_startup.

The two-level-tlds, three-level-tlds, and surbl_whitelist.txt files should be copied to the same location as the Perl subroutine script. It is recommended that these files be updated regularly (e.g. monthly) via a cron job from their original sources.

Two-level-tlds and Three-level-tlds Files

The Perl subroutine script follows the SURBL Implementation Guidelines found at the SURBL website. As such, the script makes use of files that contain two-level and three-level TLDs.

These files define domains generally have sub domains and need to have those sub-domains checked. For example, generally has sub-domains such as that need to be checked.

Near the top of the script are the following variable definitions:

my $twotld_file = "/etc/exim/two-level-tlds";
my $threetld_file = "/etc/exim/three-level-tlds";

These variables MUST be set to the full path of the file containing the these lists.

If a domain has two or more elements, all levels from two through four are checked against the URIBL and Spamhaus DBL lists.

Surbl_whitelist File

As part of the SURBL Implementation Guidelines, the Perl subroutine script makes use of a whitelist file which contains certain known good domains such as which will never be blacklisted. The use of this whitelist file will prevent unnecessary queries.

Near the top of the script is the following variable definition:

my $whitelist_file = "/etc/exim/surbl_whitelist.txt";

This variable MUST be set to the full path of the file containing the whitelisted domains.

The file of whitelisted domains can contain additional domains that need to be whitelisted locally. The domains should be entered exactly one domain per line. Blank lines and those beginning with # (comments) are ignored. Entries that are IP addresses should be in IN-ADDR format (reversed). Here is an example of some simple whitelist entries:

# This is a sample SURBL whitelist file
# The following is an example of an IP address entry for

If a domain is listed in the whitelist file, not only will that domain be exempt from checking but all sub-domains to that domain will be exempt as well. For example, if is whitelisted, and will be also be exempt.

Enabling/Disabling Individual URI Checks

Since the Perl subroutine script now has the ability to check multiple databases, the ability has been added to disable individual checks. All are enabled by default. Near the top of the script are the following variables:

my $surbl_enable = 1;
my $uribl_enable = 1;
my $dbl_enable = 1;

Set any of these variables to 0 to disable the desired list check. While it will not produce an error, it should go without saying that disabling all of these checks would be a waste of resources.

Limiting MIME Attachment Scanning Based on Attachment Size

Scanning large MIME attachment can cause excessive load on the mail system. This situation can be exacerbated by the way Exim decodes the MIME attachments prior to scanning.

Near the top of the script is the following variable definition:

my $max_file_size = 50000;

Set this variable to be the maximum size of an attachment that will be scanned. If the attachment is larger than this size, scanning of that attachment will be skipped. By default, this size is 50KB. The variable is specified in bytes.


This script is under a BSD style license. See the script for details.



Version 2.3 - 06 Mar 12 Version 2.2 - 26 Dec 10 Version 2.1 - 10 Jun 10
Version 2.0 - 06 Jan 07 Version 1.9 - 12 Oct 06 Version 1.8 - 26 Sep 06 Version 1.7 - 4 Sep 06 Version 1.6 - 1 May 06 Version 1.5 - 29 Mar 06 Version 1.4 - 20 Feb 06 Version 1.3 - 17 Jun 05 Version 1.2 - 1 May 05 Version 1.1 - 29 Apr 05 Version 1.0

Last modified: Thursday, 15-Mar-2012 15:27:55 MDT :: Erik Mugele :: Main Page :: Contact Page :: Powered by Teuton