#!/usr/bin/perl use Cache::Memcached; use strict; my $memd = _create_memcached(); sub check_greylist { my $key = &_tuple(@_); my $now = time(); my $timeout = ( $_[4] || 5 ) * 60; # Minutes to seconds, default 5 my $expire = ( $_[5] || 7 ) *24*60*60; # Days to seconds, default 7 my $val = $memd->get($key); if ( $val ) { # Update expiration $memd->replace($key, $val, $now + $expire); # Has exceeded the timeout, don't defer it if ( $now > $val + $timeout ) { Exim::log_write("PASS GREYLIST: '$key'"); return(0); } #Exim::log_write("CONTINUE GREYLIST: '$key' still greylisted for " . ($val + $timeout - $now) . " seconds"); return(1); } else { $memd->set($key, $now ,$now + $expire); #Exim::log_write("SET GREYLIST: '$key'"); return(1); } } sub greylist_time { my $key = &_tuple(@_); my $now = time(); my $timeout = ( $_[4] || 5 ) * 60; # Minutes to seconds, default 5 if ( my $val = $memd->get($key) ) { my $left = $val + $timeout - $now; $left = sprintf("%0i:%02i", int($left/60), $left % 60); return( $left); } # Should never get here if because this sub should never # have been called if there is no greylist record, but # handle it by just printing default return( sprintf("%0i:%02i", int($timeout/60), $timeout % 60)); } sub _tuple { my ($ip,$from,$local_part,$domain) = @_; return( $ip . ":" . $from . ":" . $local_part . '@' . $domain ); } sub _create_memcached { my $config = "/etc/exim/memcached.conf"; my $namespace = 'exim:'; # set default namespace my $servers; if ( -f $config ) { open(my $fh, "<", $config); while(<$fh>) { chomp($_); if ( my ($arg,$val) = split(/=/,$_) ) { next if ( $arg =~ /#/ ); $arg =~ s/\s+//; $val =~ s/\s+//; if ( $arg =~ /\bserver\b/ ) { next if ( $val !~ /^[-\w\d\.]+:\d+$/ ); push( @$servers, $val ); } elsif ( $arg =~ /\bnamespace\b/ ) { next if ( $val !~ /^[-\w\d\.]+$/ ); $namespace = $val . ":"; } } } close $fh; } $servers ||= [ 'localhost:11211' ]; # Set a default if nothing specified my $m = Cache::Memcached->new( { 'servers' => $servers, 'namespace' => $namespace, 'debug' => 0, 'compress_threshold' => 10_000 } ); return($m); }