On 1/2/2015 6:29 AM, joris dedieu wrote:
2014-12-30 23:53 GMT+01:00 Jon Rowlan <jon.row...@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);
}
}
_______________________________________________
NOTE: If there is a disclaimer or other legal boilerplate in the above
message, it is NULL AND VOID. You may ignore it.
Visit http://www.mimedefang.org and http://www.roaringpenguin.com
MIMEDefang mailing list MIMEDefang@lists.roaringpenguin.com
http://lists.roaringpenguin.com/mailman/listinfo/mimedefang