2012-04-29 10:35:59 +02:00
|
|
|
#!perl -w
|
2010-05-05 00:37:52 +02:00
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
check_bogus_bounce - Check that a bounce message isn't bogus
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
This plugin is designed to reject bogus bounce messages.
|
|
|
|
|
|
|
|
In our case a bogus bounce message is defined as a bounce message
|
|
|
|
which has more than a single recipient.
|
|
|
|
|
|
|
|
=head1 CONFIGURATION
|
|
|
|
|
|
|
|
Only a single argument is recognized and is assumed to be the default
|
|
|
|
action. Valid settings are:
|
|
|
|
|
|
|
|
=over 8
|
|
|
|
|
|
|
|
=item log
|
|
|
|
|
|
|
|
Merely log the receipt of the bogus bounce (the default behaviour).
|
|
|
|
|
|
|
|
=item deny
|
|
|
|
|
|
|
|
Deny with a hard error code.
|
|
|
|
|
|
|
|
=item denysoft
|
|
|
|
|
|
|
|
Deny with a soft error code.
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
2012-06-23 06:32:40 +02:00
|
|
|
2010 - Steve Kemp - http://steve.org.uk/Software/qpsmtpd/
|
2010-05-05 00:37:52 +02:00
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
|
|
|
|
Look for our single expected argument and configure "action" appropriately.
|
|
|
|
|
|
|
|
=end doc
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
sub register {
|
2012-06-23 06:32:40 +02:00
|
|
|
my ($self, $qp) = (shift, shift);
|
2010-05-05 00:37:52 +02:00
|
|
|
|
2012-06-23 06:32:40 +02:00
|
|
|
if ( @_ % 2 ) {
|
|
|
|
$self->{_args}{action} = shift;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->{_args} = { @_ };
|
|
|
|
};
|
2010-05-05 00:37:52 +02:00
|
|
|
|
2012-06-23 06:32:40 +02:00
|
|
|
if ( ! defined $self->{_args}{reject} ) {
|
|
|
|
$self->{_args}{reject} = 0; # legacy default
|
|
|
|
};
|
|
|
|
|
|
|
|
# we only need to check for deferral, default is DENY
|
|
|
|
if ( $self->{_args}{action} =~ /soft/i ) {
|
|
|
|
$self->{_args}{reject_type} = 'temp';
|
2010-05-05 00:37:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
|
|
|
|
Handle the detection of bounces here.
|
|
|
|
|
|
|
|
If we find a match then we'll react with our expected action.
|
|
|
|
|
|
|
|
=end doc
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
sub hook_data_post {
|
|
|
|
my ($self, $transaction) = (@_);
|
|
|
|
|
|
|
|
#
|
|
|
|
# Find the sender, and return unless it wasn't a bounce.
|
|
|
|
#
|
|
|
|
my $sender = $transaction->sender->address || undef;
|
2012-06-23 06:32:40 +02:00
|
|
|
if ( $sender && $sender ne '<>') {
|
|
|
|
$self->log(LOGINFO, "pass, not a null sender");
|
|
|
|
return DECLINED;
|
|
|
|
};
|
2010-05-05 00:37:52 +02:00
|
|
|
|
|
|
|
#
|
|
|
|
# Get the recipients.
|
|
|
|
#
|
|
|
|
my @to = $transaction->recipients || ();
|
2012-06-23 06:32:40 +02:00
|
|
|
if (scalar @to == 1) {
|
|
|
|
$self->log(LOGINFO, "pass, only 1 recipient");
|
|
|
|
return DECLINED;
|
|
|
|
};
|
2010-05-05 00:37:52 +02:00
|
|
|
|
|
|
|
#
|
2012-06-23 06:32:40 +02:00
|
|
|
# at this point we know:
|
2010-05-05 00:37:52 +02:00
|
|
|
#
|
|
|
|
# 1. It is a bounce, via the null-envelope.
|
|
|
|
# 2. It is a bogus bounce, because there are more than one recipients.
|
|
|
|
#
|
2012-06-23 06:32:40 +02:00
|
|
|
$self->log(LOGINFO, "fail, bogus bounce for :" . join(',', @to));
|
2010-05-05 00:37:52 +02:00
|
|
|
|
2012-06-23 06:32:40 +02:00
|
|
|
$self->get_reject( "fail, this is a bogus bounce" );
|
2010-05-05 00:37:52 +02:00
|
|
|
}
|