From Wikipedia, the free encyclopedia:

Greylisting is a simple method of defending electronic mail users against e-mail spam. In short, a mail transfer agent which uses greylisting will "temporarily reject" any email from a sender it does not recognize. If the mail is legitimate, the originating server will try again to send it later, at which time the destination will accept it. If the mail is from a spammer, it will probably not be retried, however, even spam sources which re-transmit later will be more likely to be listed in DNSBLs and distributed signature systems such as Vipul's Razor.

Greylisting requires little configuration and modest resources. It is designed as a complement to existing defenses against spam, and not as a replacement.


For compiling the source code, you need to have the following packages available (in addition to the standard development environment):

  • SQLite 3

Implementation Characteristics

implemented as a stand-alone daemon with a simple Unix domain socket interface (suitable for integration with Exim4) uses a SQLite 3 database backend (with a helper module to efficiently handle CIDR IP/netmask matching) per user and per domain configuration and whitelists.


Greylisting configuration is stored in an SQLite 3 database (by default /var/lib/greylstd/greylstd.db) in the tables greyconf and whitelist.

Greylisting timeouts (specified in seconds) can be configured either per user (recipient='user@domain.tld') or per domain (recipient='@domain.tld') in the greyconf table. Global defaults are configured by setting recipient=''.

  • minwait .. minimum time a sender has to wait before a retried attempt will be allowed
  • maxwait .. maximum time a sender is allowed to wait for a retry
  • maxvalid .. time span during which emails with the same (sender IP, sender address, recipient address) tuple will be allowed without further greylisting

Whitelists can be configured for a sender IP address, an e-mail address or a domain in the whitelist table.

greyconf example

 recipient   minwait   maxwait   maxvalid 
 ''   300   3600   86400 
 '@domain.tld'   60   NULL   43200 
 'user@domain.tld'   120   7200   NULL 

A recipient address of 'otheruser@domain.tld' would pick up the options minwait=60, maxwait=3600 and maxvalid=43200, whereas the recipient 'user@domain.tld' would use minwait=120, maxwait=7200 and maxvalid=43200.

whitelist example

 recipient   sender   remoteip   remoteprefixlen 
 'white@domain.tld'   ''   NULL   NULL 
 '@sub.domain.tld'   ''   NULL   NULL 
       ''   32 
       ''   16 
       'fe80::'   64 
 ''   'allow@domain.tld'   NULL   NULL 

Using this whitelisting configuration would exempt SMTP connections from, and fe80::/64 from being greylisted at all, but would also exclude the recipient 'white@domain.tld' and any user under '@sub.domain.tld' from greylisting. Furthermore, mails being sent from 'allow@domain.tld' will also be whitelisted.

IP address storage

To be able to efficiently match IP addresses against CIDR netmasks in the database, IP addresses are physically stored as BLOBs in the database. To facilitate command-line database manipulation, a helper module is available (which can be loaded by using .load /usr/lib/greylstd/ in the sqlite3 shell) and provides function inet_ntop and inet_pton to convert IP addresses from their internal format to a string representation and vice versa.

Following are a few examples to clarify the usage:

sqlite> INSERT INTO whitelist (remoteip, remoteprefixlen) VALUES (inet_pton('~fe80::'), 64);
sqlite> SELECT recipient, sender, inet_ntop(remoteip), remoteprefixlen FROM whitelist;

Exim4 Integration

To have Exim4 use the greylisting daemon you will most likely want to add a "defer" rule to your SMTP RCPT command ACL just before your "accept" rule for local domains, e.g.

  defer   message       = Greylisting in effect, please try again later.
          log_message   = greylisted.
          domains       = +local_domains : +relay_to_domains
          !senders      = : postmaster@*
          !hosts        = +relay_from_hosts
          !authenticated = *
          condition     = ${if eq {${readsocket{/var/run/greylstd/greylstd.sock}{check $sender_host_address $sender_address $local_part@$domain\n}{5s}{}{}}}{defer}{true}{false}}

Copyright Information

Copyright (C) 2006-2008, Christof Meerwald

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA