PHP 邮箱真实性检测

标题邮箱真实性检测

邮箱地址真实性检测接口,检查校验判断邮箱有效性,邮箱是否开通,邮箱是否真实邮箱,能否收到邮件,避免无效邮箱的发送与验证。

使用到的类
VerifyEmailService

class VerifyEmailService {

    protected $stream = false;

    /**
     * SMTP port number
     * @var int
     */
    protected $port = 25;

    /**
     * Email address for request
     * @var string
     */
    protected $from = 'root@localhost';

    /**
     * The connection timeout, in seconds.
     * @var int
     */
    protected $max_connection_timeout = 30;

    /**
     * Timeout value on stream, in seconds.
     * @var int
     */
    protected $stream_timeout = 5;

    /**
     * Wait timeout on stream, in seconds.
     * * 0 - not wait
     * @var int
     */
    protected $stream_timeout_wait = 0;

    /**
     * Whether to throw exceptions for errors.
     * @type boolean
     * @access protected
     */
    protected $exceptions = false;

    /**
     * The number of errors encountered.
     * @type integer
     * @access protected
     */
    protected $error_count = 0;

    /**
     * class debug output mode.
     * @type boolean
     */
    public $Debug = false;

    /**
     * How to handle debug output.
     * Options:
     * * `echo` Output plain-text as-is, appropriate for CLI
     * * `html` Output escaped, line breaks converted to `
`, appropriate for browser output * * `log` Output to error log as configured in php.ini * @type string */
public $Debugoutput = 'echo'; /** * SMTP RFC standard line ending. */ const CRLF = "rn"; /** * Holds the most recent error message. * @type string */ public $ErrorInfo = ''; /** * Constructor. * @param boolean $exceptions Should we throw external exceptions? */ public function __construct($exceptions = false) { $this->exceptions = (boolean) $exceptions; } /** * Set email address for SMTP request * @param string $email Email address */ public function setEmailFrom($email) { if (!self::validate($email)) { $this->set_error('Invalid address : ' . $email); $this->edebug($this->ErrorInfo); if ($this->exceptions) { throw new verifyEmailException($this->ErrorInfo); } } $this->from = $email; } /** * Set connection timeout, in seconds. * @param int $seconds */ public function setConnectionTimeout($seconds) { if ($seconds > 0) { $this->max_connection_timeout = (int) $seconds; } } /** * Sets the timeout value on stream, expressed in the seconds * @param int $seconds */ public function setStreamTimeout($seconds) { if ($seconds > 0) { $this->stream_timeout = (int) $seconds; } } public function setStreamTimeoutWait($seconds) { if ($seconds >= 0) { $this->stream_timeout_wait = (int) $seconds; } } /** * Validate email address. * @param string $email * @return boolean True if valid. */ public static function validate($email) { return (boolean) 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) === FALSE) { $this->set_error('MX records not found or an error occurred'); $this->edebug($this->ErrorInfo); } else { array_multisort($mxweights, $mxhosts); } /** * Add A-record as last chance (e.g. if no MX record is there). * Thanks Nicht Lieb. * @link http://www.faqs.org/rfcs/rfc2821.html RFC 2821 - Simple Mail Transfer Protocol */ if (empty($mxhosts)) { $mxhosts[] = $hostname; } return $mxhosts; } /** * Parses input string to array(0=>user, 1=>domain) * @param string $email * @param boolean $only_domain * @return string|array * @access private */ public static function parse_email($email, $only_domain = TRUE) { sscanf($email, "%[^@]@%s", $user, $domain); return ($only_domain) ? $domain : array($user, $domain); } /** * Add an error message to the error container. * @access protected * @param string $msg * @return void */ protected function set_error($msg) { $this->error_count++; $this->ErrorInfo = $msg; } /** * Check if an error occurred. * @access public * @return boolean True if an error did occur. */ public function isError() { return ($this->error_count > 0); } /** * Output debugging info * Only generates output if debug output is enabled * @see verifyEmail::$Debugoutput * @see verifyEmail::$Debug * @param string $str */ protected function edebug($str) { if (!$this->Debug) { return; } switch ($this->Debugoutput) { case 'log': //Don't output, just log error_log($str); break; case 'html': //Cleans up output a bit for a better looking, HTML-safe output echo htmlentities( preg_replace('/[rn]+/', '', $str), ENT_QUOTES, 'UTF-8' ) . "
n"
; break; case 'echo': default: //Normalize line breaks $str = preg_replace('/(rn|r|n)/ms', "n", $str); echo gmdate('Y-m-d H:i:s') . "t" . str_replace( "n", "n t ", trim($str) ) . "n"; } } /** * Validate email * @param string $email Email address * @return boolean True if the valid email also exist */ public function check($email) { $result = FALSE; if (!self::validate($email)) { $this->set_error("{$email} incorrect e-mail"); $this->edebug($this->ErrorInfo); if ($this->exceptions) { throw new verifyEmailException($this->ErrorInfo); } return FALSE; } $this->error_count = 0; // Reset errors $this->stream = FALSE; $mxs = $this->getMXrecords(self::parse_email($email)); $timeout = ceil($this->max_connection_timeout / count($mxs)); foreach ($mxs as $host) { /** * suppress error output from stream socket client... * Thanks Michael. */ $this->stream = @stream_socket_client("tcp://" . $host . ":" . $this->port, $errno, $errstr, $timeout); if ($this->stream === FALSE) { if ($errno == 0) { $this->set_error("Problem initializing the socket"); $this->edebug($this->ErrorInfo); if ($this->exceptions) { throw new verifyEmailException($this->ErrorInfo); } return FALSE; } else { $this->edebug($host . ":" . $errstr); } } else { stream_set_timeout($this->stream, $this->stream_timeout); stream_set_blocking($this->stream, 1); if ($this->_streamCode($this->_streamResponse()) == '220') { $this->edebug("Connection success {$host}"); break; } else { fclose($this->stream); $this->stream = FALSE; } } } if ($this->stream === FALSE) { $this->set_error("All connection fails"); $this->edebug($this->ErrorInfo); if ($this->exceptions) { throw new verifyEmailException($this->ErrorInfo); } return FALSE; } $this->_streamQuery("HELO " . self::parse_email($this->from)); $this->_streamResponse(); $this->_streamQuery("MAIL FROM: {$this->from}>"); $this->_streamResponse(); $this->_streamQuery("RCPT TO: {$email}>"); $code = $this->_streamCode($this->_streamResponse()); $this->_streamResponse(); $this->_streamQuery("RSET"); $this->_streamResponse(); $code2 = $this->_streamCode($this->_streamResponse()); $this->_streamQuery("QUIT"); fclose($this->stream); $code = !empty($code2)?$code2:$code; switch ($code) { case '250': /** * http://www.ietf.org/rfc/rfc0821.txt * 250 Requested mail action okay, completed * email address was accepted */ case '450': case '451': case '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 */ return TRUE; case '550': return FALSE; default : return FALSE; } } /** * writes the contents of string to the file stream pointed to by handle * If an error occurs, returns FALSE. * @access protected * @param string $string The string that is to be written * @return string Returns a result code, as an integer. */ protected function _streamQuery($query) { $this->edebug($query); return stream_socket_sendto($this->stream, $query . self::CRLF); } /** * Reads all the line long the answer and analyze it. * If an error occurs, returns FALSE * @access protected * @return string Response */ protected function _streamResponse($timed = 0) { $reply = stream_get_line($this->stream, 1); $status = stream_get_meta_data($this->stream); if (!empty($status['timed_out'])) { $this->edebug("Timed out while waiting for data! (timeout {$this->stream_timeout} seconds)"); } if ($reply === FALSE && $status['timed_out'] && $timed $this->stream_timeout_wait) { return $this->_streamResponse($timed + $this->stream_timeout); } if ($reply !== FALSE && $status['unread_bytes'] > 0) { $reply .= stream_get_line($this->stream, $status['unread_bytes'], self::CRLF); } $this->edebug($reply); return $reply; } /** * Get Response code from Response * @param string $str * @return string */ protected function _streamCode($str) { preg_match('/^(?[0-9]{3})(s|-)(.*)$/ims', $str, $matches); $code = isset($matches['code']) ? $matches['code'] : false; return $code; } }

抛出错误类
verifyEmailException

class verifyEmailException extends Exception {

    /**
     * Prettify error message output
     * @return string
     */
    public function errorMessage() {
        $errorMsg = $this->getMessage();
        return $errorMsg;
    }

}

使用示例

   //验证邮箱连通性
        $mail = new VerifyEmailService();
        //设置流的超时值
        $mail->setStreamTimeoutWait(20);

        // 设置调试输出模式
        $mail->Debug= TRUE;
        $mail->Debugoutput= 'html';

        // 设置SMTP请求的电子邮件地址
        $mail->setEmailFrom('llpa@qq.com');

        // 电子邮件检查
        $email = 'ddd@163.com';

        // 检查电子邮件是否有效且存在
        if($mail->check($email)){
            echo $email.'&gt存在';
        }elseif(VerifyEmailService::validate($email)){
            echo $email.'> 存在但无效';
        }else{
            echo $email.'> 无效且不存在';
        }

版权声明:
作者:linrux
链接:https://www.tot7.cn/technology/php/125.html
来源:阿信博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>