Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5376293
  • 博文数量: 1144
  • 博客积分: 11974
  • 博客等级: 上将
  • 技术积分: 12312
  • 用 户 组: 普通用户
  • 注册时间: 2005-04-13 20:06
文章存档

2017年(2)

2016年(14)

2015年(10)

2014年(28)

2013年(23)

2012年(29)

2011年(53)

2010年(86)

2009年(83)

2008年(43)

2007年(153)

2006年(575)

2005年(45)

分类: 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;
}
阅读(758) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~