正文 7987字数 41,525阅读

这个类可以用来检查电子邮件是否有效使用SMTP协议。

它可以连接到由地址的域名来验证的MX记录中定义的SMTP服务器。

并且模拟消息的传递,以查看是否在给定的收件人地址被接受为有效。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Sample</title> </head> <body> <?php include_once 'class.verifyEmail.php'; $email = 'verify@codepearl.com'; $vmail = new verifyEmail(); if ($vmail->check($email)) { echo 'email &lt;' . $email . '&gt; exist!'; } elseif ($vmail->isValid($email)) { echo 'email &lt;' . $email . '&gt; valid, but not exist!'; } else { echo 'email &lt;' . $email . '&gt; not valid and not exist!'; } ?> </body> </html>
Run code
Cut to clipboard

    class.verifyEmail.php
    <?php /** * Class to check up e-mail * @author liuxudong <http://www.codepearl.com> * @copyright Copyright (c) 2010, liuxudong */ class verifyEmail { /** * User name * @var string */ private $_fromName; /** * Domain name * @var string */ private $_fromDomain; /** * SMTP port number * @var int */ private $_port; /** * The connection timeout, in seconds. * @var int */ private $_maxConnectionTimeout; /** * The timeout on socket connection * @var int */ private $_maxStreamTimeout; public function __construct() { $this->_fromName = 'noreply'; $this->_fromDomain = 'localhost'; $this->_port = 25; $this->_maxConnectionTimeout = 30; $this->_maxStreamTimeout = 5; } /** * Set email address for SMTP request * @param string $email Email address */ public function setEmailFrom($email) { list($this->_fromName, $this->_fromDomain) = $this->_parseEmail($email); } /** * Set connection timeout, in seconds. * @param int $seconds */ public function setConnectionTimeout($seconds) { $this->_maxConnectionTimeout = $seconds; } /** * Set the timeout on socket connection * @param int $seconds */ public function setStreamTimeout($seconds) { $this->_maxStreamTimeout = $seconds; } /** * Validate email address. * @param string $email * @return boolean True if valid. */ public function isValid($email) { return (false !== filter_var($email, FILTER_VALIDATE_EMAIL)); } /** * Get array of MX records for host. Sort by weight information. * @param string $hostname The Internet host name. * @return array Array of the MX records found. */ public function getMXrecords($hostname) { $mxhosts = array(); $mxweights = array(); if (getmxrr($hostname, $mxhosts, $mxweights)) { array_multisort($mxweights, $mxhosts); } /** * Add A-record as last chance (e.g. if no MX record is there). * Thanks Nicht Lieb. */ $mxhosts[] = $hostname; return $mxhosts; } /** * check up e-mail * @param string $email Email address * @return boolean True if the valid email also exist */ public function check($email) { $result = false; if ($this->isValid($email)) { list($user, $domain) = $this->_parseEmail($email); $mxs = $this->getMXrecords($domain); $fp = false; $timeout = ceil($this->_maxConnectionTimeout / count($mxs)); foreach ($mxs as $host) { // if ($fp = @fsockopen($host, $this->_port, $errno, $errstr, $timeout)) { if ($fp = @stream_socket_client("tcp://" . $host . ":" . $this->_port, $errno, $errstr, $timeout)) { stream_set_timeout($fp, $this->_maxStreamTimeout); stream_set_blocking($fp, 1); // stream_set_blocking($fp, 0); $code = $this->_fsockGetResponseCode($fp); if ($code == '220') { break; } else { fclose($fp); $fp = false; } } } if ($fp) { $this->_fsockquery($fp, "HELO " . $this->_fromDomain); //$this->_fsockquery($fp, "VRFY " . $email); $this->_fsockquery($fp, "MAIL FROM: <" . $this->_fromName . '@' . $this->_fromDomain . ">"); $code = $this->_fsockquery($fp, "RCPT TO: <" . $user . '@' . $domain . ">"); $this->_fsockquery($fp, "RSET"); $this->_fsockquery($fp, "QUIT"); fclose($fp); if ($code == '250') { /** * http://www.ietf.org/rfc/rfc0821.txt * 250 Requested mail action okay, completed * email address was accepted */ $result = true; } elseif ($code == '450' || $code == '451' || $code == '452') { /** * http://www.ietf.org/rfc/rfc0821.txt * 450 Requested action not taken: the remote mail server * does not want to accept mail from your server for * some reason (IP address, blacklisting, etc..) * Thanks Nicht Lieb. * 451 Requested action aborted: local error in processing * 452 Requested action not taken: insufficient system storage * email address was greylisted (or some temporary error occured on the MTA) * i believe that e-mail exists */ $result = true; } } } return $result; } /** * Parses input string to array(0=>user, 1=>domain) * @param string $email * @return array * @access private */ private function _parseEmail(&$email) { return sscanf($email, "%[^@]@%s"); } /** * writes the contents of string to the file stream pointed to by handle $fp * @access private * @param resource $fp * @param string $string The string that is to be written * @return string Returns a string of up to length - 1 bytes read from the file pointed to by handle. * If an error occurs, returns FALSE. */ private function _fsockquery(&$fp, $query) { stream_socket_sendto($fp, $query . "\r\n"); return $this->_fsockGetResponseCode($fp); } /** * Reads all the line long the answer and analyze it. * @access private * @param resource $fp * @return string Response code * If an error occurs, returns FALSE */ private function _fsockGetResponseCode(&$fp) { $reply = stream_get_line($fp, 1); $status = stream_get_meta_data($fp); if ($status['unread_bytes']>0) { $reply .= stream_get_line($fp, $status['unread_bytes'],"\r\n"); } preg_match('/^(?<code>[0-9]{3})(\s|-)(.*)$/ims', $reply, $matches); $code = isset($matches['code']) ? $matches['code'] : false; return $code; } } ?>
    Run code
    Cut to clipboard