[Mimedefang] How can I block spam mail addressed FROM me TO me if not HELO match of my SMTP server?

- kd6lvw at yahoo.com
Wed Feb 24 00:39:23 EST 2010

--- On Tue, 2/23/10, Andre Doles <andre at doles.com> wrote:
> I'm having a large amount of spam mail hitting all my mail
> accounts, with forged addresses FROM myaccount TO myaccount,
> but coming from an SMTP server that isnt mine.

Sounds like SPF is your solution.  Please use the DNS SPF-RRtype, not TXT, if available at your domain server.  http://www.openspf.org/
> Is there a rule that will allow me to block any incoming
> mail FROM a list of legit email addresses, but where the
> HELO does not match the address/name of my SMTP server?

Well, here's my SPF checking routine.  Note that I exempt those delivering mail where SMTP AUTH was pre-arranged (i.e. known forwarders).  I also check for senders that have bogus MX servers (i.e. not replyable mail).  Since Mail::SPF does NOT exempt looped-back mail, I check for that.  If you need to exempt other addresses on your host, compare $ip to $SendmailMacro{'if_addr'}.  Note that I also check the IPv6 value as I'm dual stacked.  Finally, I fail "SPF softfails" but with a different message than hard failures.

I'm aware that in a stock MimeDefang prior to 2.68, action_insert_header() is ignored.  I hacked my copy to permit the action.  Also, I use the standarized results header defined in the later RFC 5451 (not 4408).

The code:

use Mail::SPF;

sub filter_sender {
    my ($sender, $ip, $hostname, $helo) = @_;
    if ($sender =~ /@([^>]+)/) {
        my $domain = $1;
        my @bogushosts = md_get_bogus_mx_hosts($domain);
        my $i = scalar(@bogushosts);
        return('REJECT',"Domain $domain has $i bogus MX record" .
            (($i < 2)? '' : 's') .': '. join(' ', at bogushosts),'550','5.4.4')
            if ($i);
    } else {
        $sender = "<postmaster\@$helo>" unless ($sender =~ /[^<>]+/);
    return('CONTINUE',"OK - Localhost [$ip]",'250','2.4.0')
        if (($ip eq '') || ($ip eq '::1'));
    return('CONTINUE','OK - Authenicated Client','235','2.7.0')
        if ($SendmailMacros{'auth_authen'});
    my $id = ($sender =~ /<(.+)>/) ? $1 : $sender;
    my $spfserver = Mail::SPF::Server->new(max_void_dns_lookups => undef,
        hostname => $SendmailMacros{'if_name'} );
    my $spfrequest = Mail::SPF::Request->new(versions => [1], scope => 'mfrom',
        identity => $id, ip_address => $ip, helo_identity => $helo);
    my $r = $spfserver->process($spfrequest);
    my $spfrec = $spfrequest->record;
    my $result = $r->code;
    my $text   = $r->text;
    my $local  = $r->local_explanation;
    my $auth   = ($result eq 'fail') ? $r->authority_explanation : '';
    my $label  = ($sender eq "<>") ? 'helo' : 'mailfrom';
    md_syslog('info',"$QueueID: SPF=$result From=<$id> ($text)");
    action_insert_header('Authentication-Results', $SendmailMacros{'if_name'} .
         "; SPF=$result smtp.$label=$1 ($local)", 0) if ($id =~ /@([^>]+)/);
    return('REJECT', "SPF Forgery: $local. ($auth)",'550','5.7.7')
        if ($result =~ /^(hard)?fail$/);
    return('REJECT', "SPF Error: $local ($spfrec)",'550','5.7.4')
        if ($result eq 'permerror');
    return('TEMPFAIL',"SPF Temp-Error: $local",'451','4.4.3')
        if ($result eq 'temperror');
    return('REJECT', "SPF Failure: $local",'550','5.7.1')
        if ($result eq 'softfail');
    return('CONTINUE',"OK - SPF=$result ($local)");

More information about the MIMEDefang mailing list