Checking in last version before deleting it :-)
git-svn-id: https://svn.perl.org/qpsmtpd/trunk@323 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
4b8b4793b6
commit
1b977fbb5e
@ -96,6 +96,19 @@ help, unsubscribe, and other sub-list requests.
|
|||||||
Note: These addresses are easily forgeable. Patches welcome to add checking of rDNS
|
Note: These addresses are easily forgeable. Patches welcome to add checking of rDNS
|
||||||
into the mix to eliminate the forgery problem (though rDNS isn't available to everyone).
|
into the mix to eliminate the forgery problem (though rDNS isn't available to everyone).
|
||||||
|
|
||||||
|
=head2 bounce_verp.bounce_heuristics
|
||||||
|
|
||||||
|
Put a 1 in this file to tell the plugin to use more aggressive heuristics
|
||||||
|
in determining whether this email is a bounce or not. The default rules
|
||||||
|
for detecting a bounce are:
|
||||||
|
|
||||||
|
MailFrom = <>
|
||||||
|
or MailFrom = <postmaster@domain>
|
||||||
|
or MailFrom = <mailer-daemon@domain>
|
||||||
|
|
||||||
|
Setting C<bounce_verp.bounce_heuristics> makes bounce_verp look in the mail
|
||||||
|
headers for various clues too.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
use Mail::SRS;
|
use Mail::SRS;
|
||||||
@ -104,8 +117,13 @@ sub register {
|
|||||||
my ($plugin) = @_;
|
my ($plugin) = @_;
|
||||||
|
|
||||||
$plugin->register_hook('data' => 'do_verp');
|
$plugin->register_hook('data' => 'do_verp');
|
||||||
|
if ($plugin->qp->config('bounce_verp.bounce_heuristics')) {
|
||||||
$plugin->register_hook('data_post' => 'check_verp');
|
$plugin->register_hook('data_post' => 'check_verp');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$plugin->register_hook('data' => 'check_verp');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub do_verp {
|
sub do_verp {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
@ -150,6 +168,8 @@ sub get_srs {
|
|||||||
sub do_outbound_verp {
|
sub do_outbound_verp {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
|
foreach my $recip ($transaction->recipients) {
|
||||||
|
if ($self->skip_verp($recip->address))
|
||||||
my $sender = $transaction->sender->address;
|
my $sender = $transaction->sender->address;
|
||||||
|
|
||||||
return DECLINED if $self->skip_verp($sender);
|
return DECLINED if $self->skip_verp($sender);
|
||||||
@ -160,7 +180,9 @@ sub do_outbound_verp {
|
|||||||
|
|
||||||
my $hash = $srs->hash_create($timestamp, $sender);
|
my $hash = $srs->hash_create($timestamp, $sender);
|
||||||
|
|
||||||
my $new_address = join('=', $hash, $timestamp, $sender);
|
my ($local, $domain) = ($sender =~ /^(.*)\@(.*?)$/);
|
||||||
|
my $new_address = join('-', $local, $hash, $timestamp);
|
||||||
|
$new_address = "$new_address\@$domain";
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "setting sender to $new_address");
|
$self->log(LOGDEBUG, "setting sender to $new_address");
|
||||||
$transaction->sender(Qpsmtpd::Address->new($new_address));
|
$transaction->sender(Qpsmtpd::Address->new($new_address));
|
||||||
@ -175,19 +197,27 @@ sub do_inbound_verp {
|
|||||||
|
|
||||||
$recip = $recip->address;
|
$recip = $recip->address;
|
||||||
|
|
||||||
return DECLINED if $self->skip_verp($recip);
|
if ($self->skip_verp($recip)) {
|
||||||
|
$self->log(LOGINFO, "skipping inbound check");
|
||||||
|
return DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
return DECLINED unless $self->is_bounce($transaction);
|
unless ($self->is_bounce($transaction)) {
|
||||||
|
$self->log(LOGINFO, "this mail is not a bounce - no need to check verp");
|
||||||
|
return DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "validating bounce recipient: $recip");
|
$self->log(LOGDEBUG, "validating bounce recipient: $recip");
|
||||||
#return DENY, "Multiple recipients of bounces not allowed" if $not_allowed;
|
#return DENY, "Multiple recipients of bounces not allowed" if $not_allowed;
|
||||||
|
|
||||||
my $srs = $self->get_srs();
|
my $srs = $self->get_srs();
|
||||||
|
|
||||||
my ($hash, $timestamp, $address) = split('=', $recip, 3);
|
my ($local, $domain) = ($recip =~ /^(.*)\@(.*?)$/);
|
||||||
|
my ($user, $hash, $timestamp) = split('-', $local, 3);
|
||||||
|
|
||||||
|
my $address = "$user\@$domain";
|
||||||
if (!$srs->hash_verify($hash, $timestamp, $address)) {
|
if (!$srs->hash_verify($hash, $timestamp, $address)) {
|
||||||
return DENY, "This mail did not originate here.";
|
return DENY, "Mail from $recip probably did not originate here.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$srs->timestamp_check($timestamp)) {
|
if (!$srs->timestamp_check($timestamp)) {
|
||||||
@ -213,6 +243,8 @@ sub is_bounce {
|
|||||||
|
|
||||||
return 1 if ($sender =~ /^mailer[_-]daemon\@/i);
|
return 1 if ($sender =~ /^mailer[_-]daemon\@/i);
|
||||||
|
|
||||||
|
return 0 unless $self->qp->config('bounce_verp.bounce_heuristics');
|
||||||
|
|
||||||
my $headers = $transaction->header();
|
my $headers = $transaction->header();
|
||||||
my $from = $headers->get('From');
|
my $from = $headers->get('From');
|
||||||
my $subject = $headers->get('Subject');
|
my $subject = $headers->get('Subject');
|
||||||
@ -220,8 +252,8 @@ sub is_bounce {
|
|||||||
return 1 if ($from =~ /\bpostmaster\@/i);
|
return 1 if ($from =~ /\bpostmaster\@/i);
|
||||||
return 1 if ($from =~ /\bmailer-daemon\@/i);
|
return 1 if ($from =~ /\bmailer-daemon\@/i);
|
||||||
|
|
||||||
return 1 if ($subject =~ /failure notice/i);
|
return 1 if ($subject =~ /^failure notice/i);
|
||||||
return 1 if ($subject =~ /Rejected mail/i);
|
return 1 if ($subject =~ /^Rejected mail/i);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -235,15 +267,22 @@ sub skip_verp {
|
|||||||
foreach my $skip (@skips) {
|
foreach my $skip (@skips) {
|
||||||
if (index($skip, '@') < 0) {
|
if (index($skip, '@') < 0) {
|
||||||
# skip a domain, and any subdomains
|
# skip a domain, and any subdomains
|
||||||
return 1 if $address =~ /[@\.]\Q$skip\E$/i;
|
if ($address =~ /[@\.]\Q$skip\E$/i) {
|
||||||
|
$self->log(LOGDEBUG, "skip domain: $skip");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# skip an address.
|
# skip an address.
|
||||||
return 1 if $address eq $skip;
|
if ($address eq $skip) {
|
||||||
|
$self->log(LOGDEBUG, "skip address: $skip");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
# OK, it's not that address, but is it a mailing list verp
|
# OK, it's not that address, but is it a mailing list verp
|
||||||
my ($local, $domain) = ($skip =~ /^(.*)\@(.*?)$/);
|
my ($local, $domain) = ($skip =~ /^(.*)\@(.*?)$/);
|
||||||
if ($address =~ /^\Q$local\E\b/i and $address =~ /\@\Q$domain\E$/i) {
|
if ($address =~ /^\Q$local\E\b/i and $address =~ /\@\Q$domain\E$/i) {
|
||||||
|
$self->log(LOGDEBUG, "skip partial address: $skip");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user