Validate an Email Address Via SMTP using php

Post Reply
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Validate an Email Address Via SMTP using php

Post by Neo » Fri Jan 29, 2010 3:33 pm

Code: Select all

/**
 * Validate an Email Address Via SMTP
 * This queries the SMTP server to see if the email address is accepted.
 * @copyright http://creativecommons.org/licenses/by/2.0/ - Please keep this comment intact
 * @author [email protected]
 * @version 0.1a
 */
class SMTP_validateEmail {
 
    var $sock;
 
    var $user;
    var $domain;
    var $port = 25;
    var $max_conn_time = 30;
    var $max_read_time = 5;
 
    var $from_user = 'user';
    var $from_domain = 'localhost';
 
    var $debug = false;
 
    function SMTP_validateEmail($email = false, $sender = false) {
        if ($email) {
            $this->setEmail($email);
        }
        if ($sender) {
            $this->setSenderEmail($sender);
        }
    }
 
    function setEmail($email) {
        list($user, $domain) = explode('@', $email);
        $this->user = $user;
        $this->domain = $domain;
    }
 
    function setSenderEmail($email) {
        list($user, $domain) = explode('@', $email);
        $this->from_user = $user;
        $this->from_domain = $domain;
    }
 
    /**
    * Validate an Email Address
    * @param String $email Email to validate (recipient email)
    * @param String $sender Senders Email
    */
    function validate($email = false, $sender = false) {
        if ($email) {
            $this->setEmail($email);
        }
        if ($sender) {
            $this->setSenderEmail($sender);
        }
        // retrieve SMTP Server via MX query on domain
        $result = getmxrr($this->domain, $hosts);
        // last fallback is the original domain
        array_push($hosts, $this->domain);
 
        $this->debug(print_r($hosts,1 ));
 
        $timeout = $this->max_conn_time/count($hosts);
 
        // try each host
        foreach($hosts as $host) {
            // connect to SMTP server
            $this->debug("try $host:$this->port\n");
            if ($this->sock = fsockopen($host, $this->port, $errno, $errstr, (float) $timeout)) {
                socket_set_blocking($this->sock, false);
                break;
            }
        }
 
        // did we get a TCP socket
        if ($this->sock) {
            // say helo
            $this->send("HELO ".$this->from_domain);
            // tell of sender
            $this->send("MAIL FROM: <".$this->from_user.'@'.$this->from_domain.">");
            // ask of recepient
            $reply = $this->send("RCPT TO: <".$this->user.'@'.$this->domain.">");
            // quit
            $this->send("quit");
            // close socket
            fclose($this->sock);
            // get code and msg from response
            list($code, $msg) = explode(' ', $reply);
 
            if ($code == '250') {
                // you received 250 so the email address was accepted
                return true;
            }
 
        }
 
        return false;
    }
 
 
    function send($msg) {
        fwrite($this->sock, $msg."\n");
        $resp = '';
        $start = $this->microtime_float();
        while(1) {
            $reply = fread($this->sock, 2082);
            $resp .= $reply;
            if (($resp != '' && trim($reply) == '') 
            || ($this->microtime_float() - $start > $this->max_read_time )) {
                break;
            }
        }
 
        $this->debug(">>>\n$msg\n");
        $this->debug("<<<\n$resp");
 
        return $resp;
    }
 
    /**
     * Simple function to replicate PHP 5 behaviour. http://php.net/microtime
     */
    function microtime_float() {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }
 
    function debug($str) {
        if ($this->debug) {
            echo $str;
        }
    }
}
 
Example Usage:

Code: Select all

// the email to validate
$email = '[email protected]';
// an optional sender
$sender = '[email protected]';
// instantiate the class
$SMTP_Valid = new SMTP_validateEmail();
// turn debugging on to view the SMTP session
$SMTP_Valid->debug = true;
// do the validation
$result = $SMTP_Valid->validate($email, $sender);
// view results
var_dump($result);
echo $email.' is '.($result ? 'valid' : 'invalid')."\n";
 
// send email? 
if ($result) {
  //mail(...);
}
 
User avatar
BenjaminJ
Posts: 2
Joined: Mon Aug 30, 2010 1:19 am

Re: Validate an Email Address Via SMTP using php

Post by BenjaminJ » Mon Aug 30, 2010 1:49 am

Thanks for providing this code. I did some succesful tests, but run into a problem when I try to verify an address at hotmail:

Code: Select all

HELO hotmail.com
<<<
220 snt0-mc4-f34.Snt0.hotmail.com Sending unsolicited commercial or bulk e-mail to Microsoft's computer network is prohibited. Other restrictions are found at http://privacy.msn.com/Anti-spam/. Violations will result in use of equipment located in California and other states. Sun, 29 Aug 2010 07:32:11 -0700 
I have a suspicion this may be due to the way you built the send function.

I've got a simpler script (that does work for hotmail) which uses this line for the HELO command:

Code: Select all

fputs ($Connect, "HELO {$HTTP_HOST}\r\n"); 
Any idea what part of your code might be causing the problem? I see that you use fwrite instead of fputs; I'm not an expert at this so I don't know the difference off the top of my head (I'll look them up at php.net).

Thanks,
Benjamin
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: Validate an Email Address Via SMTP using php

Post by Neo » Mon Aug 30, 2010 11:08 am

It seems a confusion of the use of /r/n with email. Is your web server running Windows? If that is the case, you will have to do some experiments by adding /r/n at the end of lines. I found quite a lot of problems like this when I was running Windows Server 2003 as my web server. After I replace it with Linux (RedHat) all problem gone.

Also, it is a known fact that some mail transfer agents replace \n by \r\n automatically (leads to doubling \r if \r\n is used).
User avatar
BenjaminJ
Posts: 2
Joined: Mon Aug 30, 2010 1:19 am

Re: Validate an Email Address Via SMTP using php

Post by BenjaminJ » Mon Aug 30, 2010 11:41 am

Thanks for that -- I didn't even know what OS and PHP version the server I tried is using. :D (I didn't really plan on using this server.) Turns out to be FreeBSD + PHP 4.4.x.

Using \r\n did the trick; I can connect to hotmail now. Thanks for the quick help, much appreciated!
Post Reply

Return to “PHP & MySQL”