Skip greylisting when we can't talk to greylist DB
This commit is contained in:
parent
4c9bcc0ee4
commit
51ca3fcda4
@ -213,7 +213,8 @@ sub register {
|
|||||||
$self->{_args} = $config;
|
$self->{_args} = $config;
|
||||||
$self->init_db();
|
$self->init_db();
|
||||||
$self->register_hooks();
|
$self->register_hooks();
|
||||||
$self->prune_db();
|
eval { $self->prune_db(); };
|
||||||
|
$self->log(LOGERROR, "Unable to prune greylist DB: $@") if $@;
|
||||||
if ($self->{_args}{upgrade}) {
|
if ($self->{_args}{upgrade}) {
|
||||||
$self->convert_db();
|
$self->convert_db();
|
||||||
}
|
}
|
||||||
@ -383,16 +384,25 @@ sub greylist {
|
|||||||
|
|
||||||
|
|
||||||
my $key = $self->get_greylist_key($sender, $rcpt) or return DECLINED;
|
my $key = $self->get_greylist_key($sender, $rcpt) or return DECLINED;
|
||||||
|
my @result;
|
||||||
|
eval {
|
||||||
|
$self->db->lock;
|
||||||
|
@result = $self->greylist_result($key, $config);
|
||||||
|
$self->db->unlock;
|
||||||
|
};
|
||||||
|
return $self->errcode($@) if $@;
|
||||||
|
return @result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub greylist_result {
|
||||||
|
my ($self, $key, $config) = @_;
|
||||||
my $fmt = "%s:%d:%d:%d";
|
my $fmt = "%s:%d:%d:%d";
|
||||||
|
|
||||||
$self->db->lock or return DECLINED;
|
|
||||||
my $value = $self->db->get($key);
|
my $value = $self->db->get($key);
|
||||||
if ( ! $value ) {
|
if ( ! $value ) {
|
||||||
# new IP or entry timed out - record new
|
# new IP or entry timed out - record new
|
||||||
$self->db->set( $key, sprintf $fmt, $self->now, 1, 0, 0 );
|
$self->db->set( $key, sprintf $fmt, $self->now, 1, 0, 0 );
|
||||||
$self->log(LOGWARN, "fail: initial DENYSOFT, unknown");
|
$self->log(LOGWARN, "fail: initial DENYSOFT, unknown");
|
||||||
return $self->cleanup_and_return();
|
return $self->failcode();
|
||||||
}
|
}
|
||||||
|
|
||||||
my ( $ts, $new, $black, $white ) = split /:/, $value;
|
my ( $ts, $new, $black, $white ) = split /:/, $value;
|
||||||
@ -404,7 +414,7 @@ sub greylist {
|
|||||||
if ( $self->now - $ts < $config->{white_timeout} ) {
|
if ( $self->now - $ts < $config->{white_timeout} ) {
|
||||||
$self->db->set( $key, sprintf $fmt, $self->now, $new, $black, ++$white );
|
$self->db->set( $key, sprintf $fmt, $self->now, $new, $black, ++$white );
|
||||||
$self->log(LOGINFO, "pass: white, $white deliveries");
|
$self->log(LOGINFO, "pass: white, $white deliveries");
|
||||||
return $self->cleanup_and_return(DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->log(LOGINFO, "key $key has timed out (white)");
|
$self->log(LOGINFO, "key $key has timed out (white)");
|
||||||
@ -416,26 +426,29 @@ sub greylist {
|
|||||||
$self->db->set( $key, sprintf $fmt, $ts, $new, ++$black, 0 );
|
$self->db->set( $key, sprintf $fmt, $ts, $new, ++$black, 0 );
|
||||||
$self->log(LOGWARN,
|
$self->log(LOGWARN,
|
||||||
"fail: black DENYSOFT - $black deferred connections");
|
"fail: black DENYSOFT - $black deferred connections");
|
||||||
return $self->cleanup_and_return();
|
return $self->failcode();
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGWARN, "pass: timed out (grey)");
|
$self->log(LOGWARN, "pass: timed out (grey)");
|
||||||
return $self->cleanup_and_return(DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# This exists purely to be overridden for testing
|
# This exists purely to be overridden for testing
|
||||||
sub now { time() }
|
sub now { time() }
|
||||||
|
|
||||||
sub cleanup_and_return {
|
sub failcode {
|
||||||
my ($self, $return_val) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
$self->db->unlock;
|
|
||||||
return $return_val if defined $return_val; # explicit override
|
|
||||||
return DECLINED
|
return DECLINED
|
||||||
if defined $self->{_args}{reject} && !$self->{_args}{reject};
|
if defined $self->{_args}{reject} && !$self->{_args}{reject};
|
||||||
return DENYSOFT, $DENYMSG;
|
return DENYSOFT, $DENYMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub errcode {
|
||||||
|
my ($self, $err) = @_;
|
||||||
|
$self->log(LOGERROR, "UNABLE TO OBTAIN GREYLIST RESULT:$err");
|
||||||
|
return DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
sub get_greylist_key {
|
sub get_greylist_key {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $sender = shift || $self->qp->transaction->sender;
|
my $sender = shift || $self->qp->transaction->sender;
|
||||||
|
@ -26,6 +26,8 @@ sub register_tests {
|
|||||||
$self->register_test('test_init_redis');
|
$self->register_test('test_init_redis');
|
||||||
$self->register_test('test_init_dbm');
|
$self->register_test('test_init_dbm');
|
||||||
$self->register_test('test_parse_redis_server');
|
$self->register_test('test_parse_redis_server');
|
||||||
|
$self->register_test('test_failcode');
|
||||||
|
$self->register_test('test_errcode');
|
||||||
}
|
}
|
||||||
|
|
||||||
sub test_load_exclude_files {
|
sub test_load_exclude_files {
|
||||||
@ -365,3 +367,24 @@ sub test_parse_redis_server {
|
|||||||
'parse_redis_server(): add default port' );
|
'parse_redis_server(): add default port' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub test_failcode {
|
||||||
|
my ($self) = @_;
|
||||||
|
$self->{_args}{reject} = 0;
|
||||||
|
is( $self->rc( $self->failcode() ), 'DECLINED',
|
||||||
|
'failcode(): reject disabled' );
|
||||||
|
delete $self->{_args}{reject};
|
||||||
|
is( $self->rc( $self->failcode() ), 'DENYSOFT: This mail is temporarily denied',
|
||||||
|
'failcode(): reject enabled' );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub test_errcode {
|
||||||
|
my ($self) = @_;
|
||||||
|
delete $self->qp->{_logged};
|
||||||
|
is( $self->rc( $self->errcode('test error') ),
|
||||||
|
'DECLINED',
|
||||||
|
'errcode(): proper return code' );
|
||||||
|
is( join("\n", @{ $self->qp->{_logged} || [] }),
|
||||||
|
'LOGERROR:greylistingUNABLE TO OBTAIN GREYLIST RESULT:test error',
|
||||||
|
'errocode(): logged error' );
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user