Spam Haters and Spam Friends:
Per User (or Per Domain) Spam Control with access_db (Sort of)

Weldon Whipple <weldon@whipple.org>


Sendmail's access_db and DNS-based blacklist features help control spam by blocking incoming e-mail during the SMTP conversation. Blocking during the SMTP conversation has the desirable effect of reducing the generation of bounce messages (and the resulting double-bounces when bounce message can't be delivered to a spammer's bogus address).

In the past, many administrators have avoided sendmail's access_db and dnsbl features because they haven't allowed the flexibility of procmail (for example), where rules can match regular expressions and allow exceptions based on the recipient(s) of the mail.

While not quite as flexible as procmail, sendmail does support the ability to exempt specified recipients from access_db and dnsbl blacklisting. It avoids the bounce messages that are inevitable when filtering with procmail (which filters after the e-mail has been accepted). (With procmail, every rejection results in the generation of a bounce e-mail to the envelope sender of the rejected mail.)

Sendmail lets you disable both DNS-based and access_db-based blacklisting for those "spam lovers" that want none of their e-mail filtered by sendmail access.db, while enabling both types of blacklisting for "spam haters" who want their mail filtered.

Here is how it works:

First, determine the relative numbers of local e-mail recipients who are spam lovers and who are spam haters.

If most local users are spam haters (probably the "usual" case)

You will need to tell sendmail the local e-mail addresses of spam lovers ("friends" of spam--those that want to receive all mail unfiltered):

  1. Before noting the spam lovers in access.db, you need to modify your sendmail mc file (used to generate the sendmail.cf file) by add the following line (after "FEATURE(`access_db')"):
       FEATURE(`access_db')dnl
       FEATURE(`delay_checks',`friend')dnl
    
    Then rebuild and replace your sendmail.cf file, and restart sendmail.
  2. Now you can add entries for the spam lovers/friends (who want no filtering of their incoming mail) to the access.db:
       Spam:tom@whipple.org         FRIEND
       Spam:dick@whipple.org        FRIEND
       Spam:harry@whipple.org       FRIEND
    
    The above syntax is for sendmail 8.12 and later. In sendmail 8.10 and 8.11, "To:" was used instead of "Spam:", and "SPAMFRIEND" was used instead of "FRIEND", like so:
       To:tom@whipple.org           SPAMFRIEND
    
  3. Now regenerate the access.db (using makemap or other available tool).
    Typical sendmail installations can generate the access.db with the following commands (as root):
    
    # cd /etc/mail
    # makemap hash access < access
    
    (If your sendmail doesn't use "hash" databases, you will likely need to substitute "btree" for "hash" in the makemap command.)

Now Tom, Dick and Harry (in the example above) will receive all mail--even if sent from IP addresses that are listed in DNS blacklists you have configured for sendmail, and even if listed in tagged From: or Connect: entries in the acceses.db. (This also applies to the--now deprecated--access entries that have no tags.)

Why it works. When conducting an incoming SMTP conversation, sendmail normally calls the check_relay rule set when the incoming connection is made. At that time access entries tagged with Connect: are checked; this is also when DNS-based blacklists are consulted. Later, when the incoming server issues the MAIL FROM: command, sendmail checks tagged From: entries in the access.db. Then, for each RCPT TO: command issued by the incoming mail server, sendmail checks tagged To: (or, in this case Spam:) entries in the access.db
When you specify the delay_checks FEATURE in the sendmail mc file, sendmail delays the checks that it normally performs at the "connection initiation" and MAIL FROM: phases of the SMTP conversation. Instead, the first check it performs is (at the RCPT TO: step) to look up the recipient in access.db to see if she wants to unconditionally receive all mail; then sendmail performs the MAIL FROM: and connection checks. This is how mail addressed to "spam friends" is allowed unconditional delivery by sendmail.

Else if most users are spam lovers

You will need to tell sendmail the e-mail address of the few spam haters (the users whose e-mail will be filtered by other entries in access.db).

  1. In your sendmail mc file (used to generate the sendmail.cf file), add the following line (after "FEATURE(`access_db')"):
       FEATURE(`access_db')dnl
       FEATURE(`delay_checks',`hater')dnl
    
    Then rebuild and replace your sendmail.cf file, and restart sendmail.
  2. Add entries for the spam haters to the access.db:
       Spam:curlym@whipple.org         HATER
       Spam:moe@whipple.org            HATER
    
    The above syntax is for sendmail 8.12 and later. In sendmail 8.10 and 8.11, "To:" was used instead of "Spam:", and "SPAMHATER" was used instead of "HATER".
    Then regenerate the access database as described earlier.

Spam Hating and Friendly Domains (in a Virtual Hosting Environment)

Sendmail installations that host multiple domains might have a mix of domains that hate spam and those that love spam. They might want to indicate friends and haters on a per domain (rather than per user) basis. If most of your domains are spam haters, you can list the spam friendly domains in your access.db:

   Spam:whipple.org         FRIEND
   Spam:bmw.com             FRIEND
Important: Note the omission of the "at" sign (@).

If, on the other hand, most of your domain owners are uneasy about hating spam, but a handful are haters, you can add the minority of haters to the access.db:

   Spam:whipple.org         HATER
   Spam:bmw.com             HATER

(Of course, you can also mix per domain spam control--for some domains--and per user spam control for others--if you are willing to accept the administrative overhead ... :-)

Appendix: Configuration Details for SuSE Linux 9.3 (i586) and Sendmail Version 8.13.3-5

(Submitted by Hans-Ulrich Jetter, 26 Jan 2007)

  1. Put the following line at the end of the file /usr/share/sendmail/ostype/suse-linux.m4 (without touching sendmail.cf):
    FEATURE(`delay_checks', `friend')dnl
    
  2. Put the following at the end of the file /etc/sysconfig/sendmail:
    SENDMAIL_DNSRBL="dnsbl.njabl.org sbl-xbl.spamhaus.org"
    
  3. Add the following to /etc/mail/access:
    Spam:domain.tld     FRIEND
    
  4. Then type:
    SuSeconfig --modules sendmail
    rcsendmail restart
    
  5. Finally, view the end of /var/log/mail for errors/results:
    tail -f /var/log/mail
    

(A special thanks to readers who point out omissions to this document--and suggest ways to make it better!!)