[Mimedefang] My semi-cached version of md_check_against_smtp_server

Yizhar Hurwitz yizhar at mail.com
Fri Dec 8 08:58:41 EST 2006


Here is my cached implementation of md_check_against_smtp_server.

I publish it here for other to look at, and for tips on improving it.

General design goals and thoughts:

* I know about the option of using LDAP or other methods to get the 
valid recipients list,

and I currently use exchange2access.pl on some sites,

but for some other sites I prefer to use md_check_against_smtp_server.

* Make it lite, simple and portable to different sites.

* No use of external DB software (sql server), unless I decide that I 
really need it.

* Cache only positive response for valid recipients (CONTINUE).

This will give me the major benefits of the md_check_function,

the mail relay will accept mail for cached valid recipient even when 
backend mail server is down.

When a new mailbox/address is configured on the mailbox server, it will 
be available immediately.

* Use a combination of disk cache for writing changes, and ram cache for 
reading them.

This will avoid possible locking issues or race conditions, because I 
will very rarely write to the disk cache.

I'm taking advantage of the assumptions that most "filter_recipients" 
calls in MD 2.57 and above would run on the save slave(s)

I think that I can afford storing the whole cache in RAM, because:

It is for use on small sites, with maximum of 200 recipients.

I cache only valid recipients.

I run only 2-6 slaves on each MD machine.

So if I assume that each email address will consume less then 50 bytes 
of RAM, and I have less then 200 recipients,

I get less then 10kb spent RAM per slave, or did I miss anything?

* I'm currently using an SDBM file for the disk cache,

I really don't know much about all those different dbm file formats,

so if you can tell me about a better format I can try it.

* I've used the command: "tie ...... or die ....", so I can see if 
something goes wrong.

Maybe I should change it to be more tolerant, but anyway it seems to 
work fine with no errors so far.

* Take a look at how I get the destination server address to check 
against, from $rcpt_host.

This makes the code portable from site to site, without the need to 
manually specify the server.

What do you think? So far it seems to work for me.

It is designed for servers which are mail relay of incoming mail only.

OK, time for the real thing (relevant parts from 


# On/Off switch...

$CheckRecipientEnable = 1;

### Used for valid recipients cache:
use Fcntl;
use SDBM_File;
### Valid Recipients Cache:
my $vrc_filename = '/home/defang/vrc-sdbm';
my %vrc_disk;
my %vrc_ram;

sub filter_initialize {
if ($CheckRecipientEnable) {
  my $valid_timestamp = time - 86400*30;  ### Currently I'm caching 
valid recipients for 30 days.
  tie (%vrc_disk, 'SDBM_File', $vrc_filename, O_RDONLY|O_CREAT, 0666) or 
die "Cannot tie VRC file, $!";
  while (($key,$val) = each %vrc_disk) {
   $vrc_ram{$key} = 1 if ($val >= $valid_timestamp);
  untie (%vrc_disk);

sub filter_recipient
 my($recip, $sender, $ip, $host, $first, $helo, $rcpt_mailer, 
$rcpt_host, $rcpt_addr) = @_;
 if ($CheckRecipientEnable and ($rcpt_mailer ne 'local')) {
  if ($vrc_ram{$recip}) {
   return ('CONTINUE', 'OK');
  else {
   ### Check if $rcpt_host is in mailertable by looking for square 
brackets []:
   if ($rcpt_host =~ /^\[(.*)\]$/) {
    my ($stat,$msg,$code) = md_check_against_smtp_server($sender, 
$recip, $HostName, $1);
    if ($stat eq 'CONTINUE') {
     $vrc_ram{$recip} = 1;
     tie (%vrc_disk, 'SDBM_File', $vrc_filename, O_RDWR, 0666) or die 
"Cannot tie $vrc_file for write, $!";
     $vrc_disk{$recip} = time;
     untie (%vrc_disk);
    return ($stat, $msg, $code);
 return ('CONTINUE', 'OK');

Comments are welcome.

Yizhar Hurwitz.


More information about the MIMEDefang mailing list