全部博文(1144)
分类: LINUX
2009-12-09 11:40:20
#!/usr/local/bin/perl
# vrfy.pl v.92b
# copyright 2004 Jeremy Kister.
# released under Perl's Artistic License 20040812
#
# verify envelope sender can take mail
# (similar to rather decommissioned VRFY SMTP verb)
#
# I dont recommend using this; it's just concept code to show
# what Verizon and friends are doing.
#
# If you do use this, it's *very* important to cache your results
# as you dont want to DoS some poor little server. The implemented
# sql commands are natively compatible with MySQL and MSSQL w/FreeTDS.
#
#CREATE TABLE `email_cache` (
# `email` varchar(255) NOT NULL,
# `time` int(4) unsigned NOT NULL,
# `code` tinyint(1) unsigned NOT NULL,
# PRIMARY KEY (`email`)
#) TYPE=MyISAM;
use strict;
use IO::Socket::INET;
use Net::DNS;
use DBI;
my $VERBOSE=0;
my $email = shift;
die "invalid looking email: $email\n"
unless($email =~ /^([a-z0-9_\.\+\-\=\?\^\#])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,4})+$/i);
my $dsn = 'DBI:mysql:host=mysql.example.net;database=isp';
my $dbun = 'dbun';
my $dbpw = 'dbpw';
my $dbh = DBI->connect($dsn, $dbun, $dbpw, {RaiseError => 1});
my $sql = 'SELECT code FROM email_cache WHERE email = ' . $dbh->quote($email);
$sql .= ' AND time > ' . $dbh->quote($^T-43200); # 12 hours ago
my $sth = $dbh->prepare($sql);
$sth->execute;
my $row = $sth->fetchrow_hashref;
my $code = $row->{code};
if($code eq '1' || $code eq '0'){
print $code;
exit;
}
my $me;
if(open(F, "/var/qmail/control/helohost") || open(F, "/var/qmail/control/me") || open(F, "/etc/hostname")){
chop($me = );
close F;
}else{
die "cannot determine helohost\n";
}
my ($user,$domain) = split /\@/, $email;
my $res = Net::DNS::Resolver->new;
my @mx = mx($res, $domain);
my $code = 0;
foreach my $rr (@mx){ # sorted by pref
my $exchanger = $rr->exchange;
if(($exchanger =~ /^(127|0|10|255|224)\./) ||
($exchanger =~ /^192\.168\./) ||
($exchanger =~ /^172\.(1(6|7|8|9)|2\d|3(0|1))\./) ||
($exchanger =~ /^192\.0\.2\./)){
sqllog($dbh,$email,0);
last;
}else{
my $sock = IO::Socket::INET->new(PeerAddr => $exchanger,
PeerPort => 25,
Proto => 'tcp',
Timeout => 12);
if($sock){
my @banner = getlines($sock);
print "banner: @banner\n" if($VERBOSE);
unless($banner[-1] =~ /^220\s/){
print $sock "QUIT\r\n"; # be nice
next;
}
print $sock "HELO $me\r\n";
my @helo = getlines($sock);
print "helo: @helo\n" if($VERBOSE);
unless($helo[-1] =~ /^250\s/){
print $sock "QUIT\r\n"; # be nice
next;
}
print $sock "MAIL FROM:<>\r\n";
my @mf = getlines($sock);
print "mf: @mf\n" if($VERBOSE);
unless($mf[-1] =~ /^250\s/){
print $sock "QUIT\r\n"; # be nice
next;
}
print $sock "RCPT TO:<${email}>\r\n";
my @rt = getlines($sock);
print "rt: @rt\n" if($VERBOSE);
if($rt[-1] =~ /^250\s/){
# host accepted
$code = 1;
print $sock "QUIT\r\n"; # be nice
last;
}elsif($rt[-1] =~ /^5\d{2}/){
# host rejected
$code = 0;
print $sock "QUIT\r\n"; # be nice
last;
} # else tmp fail or dunno wtf, try next exchanger
} # else try next exchanger.
}
}
sqllog($dbh,$email,$code);
$dbh->disconnect;
print $code;
#exit $code;
sub getlines {
my $sock = shift;
my @lines;
while(<$sock>){
if(/^\d+\s/){
chomp;
push @lines, $_;
last;
}else{
push @lines, $_;
}
}
return(@lines);
}
sub sqllog {
my ($dbh,$email,$code) = @_;
my $sql = 'SELECT COUNT(*) FROM email_cache WHERE email = ' . $dbh->quote($email);
my $sth = $dbh->prepare($sql);
$sth->execute;
my $row = $sth->fetchrow_hashref;
my ($count) = values %$row;
my $sql;
if($count > 0){
$sql = 'UPDATE email_cache SET time = ' . $dbh->quote($^T);
$sql .= ', code = ' . $dbh->quote($code) . ' WHERE email = ' . $dbh->quote($email);
}else{
$sql = 'INSERT INTO email_cache VALUES (' . $dbh->quote($email);
$sql .= ',' . $dbh->quote($^T) . ',' . $dbh->quote($code) . ')';
}
my $sth = $dbh->prepare($sql);
$sth->execute;
}