check_badrcptto, to prevent backscatter

[email protected] (Todd Brunhoff)
Newsgroups perl.qpsmtpd
Message-ID <[email protected]>
  I have a small email server that is just for my wife and I. The 
biggest problem I have is backscatter (mail received with invalid local 
address that bounces to an invalid sender address). So the following 
script blocks all of this at the point of receipt, inside qpsmtpd. Could 
not find it anywhere else so I wrote this. Comments welcome.

Todd
check_goodrcptto (text/plain, 2 KB)
# this plugin checks the goodrcptto config (like badmailfrom, but for
# rcpt address rather than sender address). "Good" is based on the
# contents of /etc/passwd and/etc/aliases. This will prevent all backscatter.

use Qpsmtpd::DSN;
use strict;
use warnings;

sub read_alias {
    my $file = shift;

    local *ALIAS;
    local $_;
    if (! open(ALIAS,$file))
        { return undef; }

    my $line = undef;
    my $alias_hash = {};

    while(<ALIAS>) {
        chomp;
        if(defined $line && /^\s/) {      
            $line .= $_;
        } else {
            if (defined $line) {
                if ($line =~ s/^([^:]+)://)
                    { $alias_hash->{$1} = 1; }
                undef $line;
            }
            next if (/^#/ || /^\s*$/);       
            $line = $_;
        }
    }
    close(ALIAS);
    return $alias_hash;
}

sub load_passwd {
    my $logins = {};
    setpwent();
    while (my @list = getpwent())  {
        $logins->{$list[0]} = 1;
    }
    endpwent();
    return $logins;
}

sub hook_rcpt {
    my ($self, $transaction, $recipient, %param) = @_;

    # load aliases and passwd if not yet done
    if (! defined($self->{'aliases'})) {
        $self->{'aliases'} = read_alias("/etc/aliases");
        $self->log(LOGINFO, "goodrcptto: aliases available");
    }
    if (! defined($self->{'logins'})) {
        $self->{'logins'} = load_passwd();
        $self->log(LOGINFO, "goodrcptto: logins available");
    }

    if (! $recipient->host || ! $recipient->user)
        { return (DECLINED); }

    if (defined($self->{'aliases'}) && $self->{'aliases'}->{$recipient->user}) {
        $self->log(LOGINFO, "goodrcptto " . $recipient->user . " is alias");
        return (DECLINED);
    }
    if (defined($self->{'logins'}) && $self->{'logins'}->{$recipient->user}) {
        $self->log(LOGINFO, "goodrcptto " . $recipient->user . " is login");
        return (DECLINED);
    }
    return Qpsmtpd::DSN->no_such_user("mail to $recipient not accepted here");
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.