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

Reply via email to