[Mimedefang] Re: md_check_against_smtp_server

Scott Silva ssilva at sgvwater.com
Fri May 25 13:04:58 EDT 2007


Daniel Aquino spake the following on 5/25/2007 6:51 AM:
> This seems like an easy way to remove the need for me to dip into a
> ldap server...
> Has anyone thought/created some type of cache for making this function
> more practical?
I found the following from the archives.

--------------------snip--------------------------


	In case it might be of interest, here's the code we're using
for caching the results of md_check_against_smtp_sender.


[...in filter_initialize...]
# location of cache files for md_check_against_smtp_server results lookups
$cachedir="/var/spool/MIMEDefang/smtpcheck";

    if (! -d "$cachedir") {
	mkdir "$cachedir", 0775;
    }
[...]



# strip an email address down to the bare minimum, no optional text
# parts and no <>
sub address_strip ($) {
        my ($a) = @_;
        $a = "" if (!defined($a));
        $a =~ s/^[<\[]//;
        $a =~ s/[>\]]$//;
        return ($a);
}

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# %PROCEDURE: writedb
# %ARGUMENTS: (database filename), (keystring), (value)
# %RETURNS: 0 if database write failed, 1 if success
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sub writedb($$$) {
    my ($dbfile, $key, $val) = @_;
    my ($db);
    if (tie (%db, "DB_File", $dbfile, O_RDWR|O_CREAT, 0775, $DB_HASH)) {
	# insert new val
	$db{$key} = "$val";
	untie %db;
	return 1;
    } else {
	md_syslog('warning', "Couldn't tie/write DB \'$dbfile\': $!");
	return 0;
    }
}

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# %PROCEDURE: cache_write
# %ARGUMENTS: username, server, code
# %RETURNS: 0 if database write failed, 1 if success
# %DESCRIPTION: Basically a wrapper for writedb. (We use writedb
#  elsewhere, that's why.  :-)
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sub cache_write ($$$) {
    my ($luser, $server, $code)=@_;
    my $dbfile="$cachedir/$server.cache.db";
    my $tstamp=rfc2822_date;
    md_syslog('debug', "cache_write: adding $luser:$code to cache for $server
with stamp $tstamp");
    return writedb($dbfile, $luser, "$code|$tstamp");
}

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# %PROCEDURE: cache_check
# %ARGUMENTS: username, servername (fqdn)
# %RETURNS: CONTINUE if username at server is cached known good
#           REJECT if username at server is cached known bad
#           TEMPFAIL if username at server is not cached
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sub cache_check ($$) {
    my ($luser, $server)=@_;
    my $dbfile="$cachedir/$server.cache.db";
    return 'TEMPFAIL' unless (my $h = &opendb_read($dbfile));
    my $rval = $h->{$luser};
    closedb($dbfile);
    return 'TEMPFAIL' unless $rval;
    my ($test, $tstamp) = split (/\|/, $rval, 2);
    if ($test =~ /REJECT/) {
	# previous lookup returned negative result
	md_syslog('debug', "cache_check: lookup succeeded: REJECT $luser on $server,
record dated $tstamp");
	return 'REJECT';
    } else {
	# valid users we've already seen and added to the local cache
	md_syslog('debug', "cache_check: lookup succeeded: ACCEPT $luser on $server,
record dated $tstamp");
	return 'CONTINUE';
    }
}

[ and then, in filter_recipient...]
    my $relay="";
    my ($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('CONTINUE', 'ok',
'250', '2.1.5', '0');
    my $lusername="";
    my $testsender="smtpcheck\@bifrost.cs.umass.edu";
    my ($recipient, $sender, $ip, $hostname, $first, $helo, $rcpt_mailer,
$rcpt_host, $rcpt_addr) = @_;
    my $cacheadd=0;

    # normalize $recipient into local username part and hostname part
    my $rcpt = address_strip($recipient);
    if ($rcpt =~ /^(.+)\@([\w_.]+)$/) {
	$lusername = $1;
	$relay = $2;
	# is this a host we know to accept mail for?
	if ($relay =~ /$Cw_hosts/i ) {
	    # find actual relay
	    my $end_server = relayget($relay);
	    # if relay is not localhost, then check deliverability on the end-server
	    if ($end_server) {
		# first check local cache
		if (($code = cache_check($lusername, $end_server)) =~ /TEMPFAIL/) {
		    # means recipient is not in local cache
		    ($code, $msg) = md_check_against_smtp_server($testsender, $recipient,
$helo, $end_server);
		    $cacheadd=1;
		}
		if ($code =~ /TEMPFAIL/) {
		    md_syslog('warning', "rcpt check on $lusername against $end_server
FAILED: \'$code\', \'$msg\'");
		    ($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('TEMPFAIL', "Unable to
verify LUser", "451", "4.3.0", $delay);
		} else {
		    $cacheadd && cache_write($lusername, $end_server, $code);
		    if ($code =~/CONTINUE/) { # we got verification from the end-server
			md_syslog('debug', "rcpt check on $lusername against $end_server
succeeded:\'$code\', \'$msg\'");
			($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('CONTINUE', "ok", "251",
"2.1.5", $delay);
		    } else { # must be a bad user
			md_syslog('info', "rcpt check on $lusername against $end_server rejected
with \'$code\', \'$msg\'");
			($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('REJECT', "$recipient...
LUser unknown", "550", "5.1.1", $delay);
		    }
		}
	    } else {
		# must be a valid alias for this host
		md_syslog('debug', "filter_recipient: no relay information found for $relay");
	    }
	} else {
	    md_syslog('debug', "\$relay \'$relay\' not in \$Cw_hosts");
	    ($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('REJECT', "$relay: cannot
relay", "550", "5.1.1", $delay);
	}
    } else {
	md_syslog('warning', "bad RCPT value \'$rcpt\' from \'$recipient\'");
	($code, $msg, $smtp_code, $smtp_dsn, $delay) = ('REJECT', "$rcpt: invalid",
"550", "5.1.1", $delay);
    }
    return ("$code", "$msg", "$smtp_code", "$smtp_dsn", $delay);
}



	Cheers,
		Ole
-- Ole Craig * UNIX, linux, SMTP-fu; news, web; SGI martyr * CS Computing
Facility, UMass * <www.cs.umass.edu/~olc/pgppubkey.txt> for public key Need a
seasoned *NIX admin in the Denver/Boulder area? Hire me!

----------------------------snip--------------------------------------

-- 

MailScanner is like deodorant...
You hope everybody uses it, and
you notice quickly if they don't!!!!



More information about the MIMEDefang mailing list