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