[Mimedefang] greylisting

Lucas Albers admin at cs.montana.edu
Mon Nov 24 21:22:31 EST 2003

I implemented greylisting on the 23rd.
(read the archives if your wondering what greylisting is.)
And I am just completelly amazed at how effective it is at bouncing spam,
and also dropping the load on my mail server.
I did make some changes, I set the rejection to relay-server instead of
sender-recipient pair.
I wanted to reduce the mail delay to to the minimum number of mail messages.
It will only tempfail the first mail message from a new server.
I also set it to not tempfail from my local domain.
I get a lot of mailing lists and I didn't want't to delay their delivery.

I was planning to set a minimal delivery time, so it rejects the first
message and won't accept for at least five minutes from the first
attempted delivery. Haven't done that yet, have that code 90% finished.

But it appears spammers just speed through deliveries and don't hit with a
second attempt. They will, but not yet...

They will switch relays, I saw a few spammers try and deliver the same
message through 17 relays in a 30 second interval. Tempfailed them all.

I'll post my complete code (which I got originally almost in it's entirety
except for my additions from Big Daddy-O Dave Skoll.

To reiterate this code has been tested and works on my server, unchanged
from what posted below, except for putting the actual ip's in

need to enable filter_recipient tests in /etc/sysconfig/mimedefang or
wherever you do it for your os.

add next to other global var's
my $DBFilename = "/var/spool/MIMEDefang/greylist.db";

add to /usr/bin/mimedefang.pl after function recipient_ok, doesn't matter
If you comment out the lines near 'ip_of_test_machine' you can enable it
so it will only tempfail mail coming from a single machine.

(I enabled it only for 1 remote mail server to make sure it worked before
I enabled it as it currently is for all remote servers.)


#graylist stuff.
sub lock_db () {
    open(LOCKFILE, ">>$DBFilename.lock") or return 0;
    flock(LOCKFILE, \&LOCK_EX);
    return 1;

sub unlock_db () {
    flock(LOCKFILE, \&LOCK_UN);
    return 1;

sub canonicalize_email ($) {
    my($email) = @_;
    # Remove angle-brackets; convert to lower-case
    $email =~ s/^<//;
    $email =~ s/>$//;
    $email = lc($email);

sub should_greylist ($$$) {
    my($sender, $recip,$ip) = @_;
    my %hash;

    $sender = canonicalize_email($sender);
    $recip  = canonicalize_email($recip);
    #my $key = "<$sender><$recip>";
    my $key = "<$ip><$ip.blah>";

    tie %hash, 'DB_File', $DBFilename;
    my $ret = ++$hash{$key};
    untie %hash;
    return ($ret == 1);

sub exclude_server ($){
        my ($ip) = @_;
        if ($ip =~ /127\.0\.0\.1/
                || $ip =~ /xxx\.xx\./
                || $ip =~ /xxx\.xx\.xxx\.xx/
                || $ip =~ /xxx\.xx\.xxx\./
                || $ip =~ /xxx\.xx\.xxx\./
                || $ip =~ /xxx\.xx\.xxx\./
                || $ip =~ /xxx\.xx\.xxx\./
                || exists($SendmailMacros{'auth_authen'})) {
                #md_syslog('err',"skipping $RelayAddr because local");
                return 1;
        } else {
                #md_syslog('err',"not skipping $RelayAddr because not
                return 0;

sub filter_recipient ($$$$$$$$$) {
    my($recip, $sender,$ip, $rest_of_the_junk) = @_;
    #md_syslog('warning', "Filter Recipient:$sender:$recip");
    if (exclude_server($ip)) {
    return ("CONTINUE", "");
        #if ($ip eq 'ip_of_test_machine') {
    md_syslog('warning', "Filter Recipient:$sender:$recip:$ip");

        if (should_greylist($sender,$recip,$ip)) {
                return("TEMPFAIL", "Tempfailed as anti-spam measure. 
Please try again.");
    return ("CONTINUE", "");
        #return ("CONTINUE", "");

More information about the MIMEDefang mailing list