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
# 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");
}

Reply via email to