[Mimedefang] md_check_against_smtp_server
Kevin A. McGrail
KMcGrail at PCCC.com
Mon Jan 12 18:19:37 EST 2015
On 1/2/2015 6:29 AM, joris dedieu wrote:
> 2014-12-30 23:53 GMT+01:00 Jon Rowlan <jon.rowlan at sads.com>:
>> I'd like to thank everyone who replied to my recent query regarding
>> md_check_against_smtp_server.
>>
>> The end result is now working beautfifully and inspired by the replies I
>> am looking into caching the lookup results.
> I use a Redis database for that. It's quite efficient.
>
> Joris
Thanks Joris,
We refined your caching and added more debugging and error checking so
we thought we would post back to the list in like and kind.
Best,
KAM
#Thanks to Joris Dedieu for inspiration and example code for this function
sub cached_md_smtp_check {
my ($sender, $recipient, $helo, $server, $port) = @_;
my ($redis, $key, $status, $message, $redis_server, $redis_password,
$start_time, $end_time, $status_message);
md_syslog("warning", "DEBUG: Edge Test - Checking Recipient
$recipient with cached_md_smtp_check");
# IN ORDER TO MAKE SURE WE DON'T GET STUCK, RUN IN AN EVAL SO WE CAN
TIME OUT THAN md_check_against_smtp_server
($status, $message) = eval {
# SET TIMEOUT FUNCTION
$SIG{ALRM} = sub { md_syslog("warning", "DEBUG: Edge Test - Timing
Out"); die "timeout" }; # NB: \n required
# SET TIMEOUT TO 15 SECONDS
alarm 15;
$redis_server = "XXX:6379";
$redis_password = "YYY";
$recipient =~ s/[<>]//g;
# ATTEMPT CONNECTION TO REDIS SERVER
eval { $redis = Redis->new(server => $redis_server, password =>
$redis_password); };
# IF THERE IS AN ERROR WHEN TRYING TO CONNECT TO REDIS, JUST USE A
REGULAR CALL
if ($@) {
# WARN THAT REDIS ISN'T WORKING
md_syslog("warning", "WARNING: Edge Test - Redis Failed, calling
md_check_against_smtp_server. Error: $@");
# RESET ALARM BEFORE RETURNING
alarm 0;
return md_check_against_smtp_server($sender, $recipient, $helo,
$server, $port);
} else {
md_syslog("warning", "DEBUG: Edge Test - Redis connection
success, checking for cached value for $recipient");
$key = $redis->get("$recipient");
# PARSE RESPONSE FROM REDIS IF IT IS SET
if ($key ne '' and $key =~ /(.*):(.*)/) {
$status = $1;
$message = $2;
if (uc($status) eq "CONTINUE" or uc($status) eq "REJECT") {
md_syslog("warning", "DEBUG: Edge Test - Returning cached
value from Redis Status: '$status' Message: '$message' Recipient:
$recipient");
$redis->quit;
# RESET ALARM BEFORE RETURNING
alarm 0;
return ($status, $message);
} else {
$redis->quit;
md_syslog("warning", "WARNING: Edge Test - Cached value in
Redis returned an incorrect value for $recipient. Calling
md_check_against_smtp_server");
# RESET ALARM BEFORE RETURNING
alarm 0;
return md_check_against_smtp_server($sender, $recipient,
$helo, $server, $port);
}
} else {
md_syslog("warning", "DEBUG: Edge Test - Response for
$recipient Not Cached, calling md_check_against_smtp_server");
($status, $message) = md_check_against_smtp_server($sender,
$recipient, $helo, $server, $port);
# IF NOT TEMPFAIL, SAVE RESPONSE IN REDIS WITH APPROPRIATE
EXPIRATION
if(uc($status) eq "CONTINUE") {
$redis->set($recipient,"$status:$message");
# GOOD RESPONSE, CACHE FOR 5 DAYS
$redis->expire("$recipient", 432000);
} elsif(uc($status) eq "REJECT") {
$redis->set($recipient,"$status:$message");
# BAD RESPONSE, CACHE FOR 1 DAY
$redis->expire("$recipient", 86400);
} elsif (uc($status) eq "TEMPFAIL") {
# IF THE RESPONSE IS TEMPORARY FAIL, DON'T CACHE THE RESULT
alarm 0;
return ($status, $message);
}
$redis->quit;
# RESET ALARM BEFORE RETURNING
alarm 0;
return ($status, $message);
}
}
};
if ($@) {
# FUNCTION TIMED OUT, FOR NOW, JUST SEND CONTINUE, LATER WE WILL
NEED TO CALL THE md_check_against_smtp_server FUNCTION
if ($@ =~ /timeout/) {
md_syslog("warning", "DEBUG: Edge Test - Redis Eval timed out,
sending CONTINUE, OK");
return ("CONTINUE", "OK");
} else {
# FAILURE DID NOT COME FROM TIMEOUT, WARN AND DIE
md_syslog("warning", "DEBUG: Edge Test - Redis Eval failed for
reasons other than timeout $@, calling die");
die;
}
} else {
# NO TIMEOUT, RETURN VALUES SET
return ($status, $message);
}
}
More information about the MIMEDefang
mailing list