SMTP Email Address Validation

How do you validate an email address? You may validate it with a javascript on the client-side, or run a server-side validation via a regular expression or a newly available filter_var function of the PHP 5.2.x. Perhaps, you may want to go one step further and verify the email address from the remote SMTP server.

Generally, a server-side email address validation would suffice for most applications. If you do have to run an SMTP-based email address verification, the following script will help you do that. This is a modified version of the PHP SMTP Email Validation from Google Project.

class SmtpValidator {
	
	private $options = array(
			"port" => 25,
			"timeout" => 1,  // Connection timeout to remote mail server.
			"sender" => "[email protected]",
			"short_response" => false,
	);
	
	/**
	 *  Override the options for those specified.
	 */
	function __construct($options = null) {
		if (!empty($options)) {
			if (is_array($options)) {
				foreach ($options as $key => $value) {
					$this->options[$key] = $value;
				}
			}
		}
	}
	
	/**
	 *  Validate the email address via SMTP.
	 *  If 'shore_response' is true, the method will return true or false;
	 *  Otherwise, the entire array of useful information will be provided.
	 */
	public function validate($email, $options = null) {
		
		$result = array("valid" => false);
		$errors = array();
		
		// Email address (format) validation
		if (empty($email)) {
			$errors = array("Email address is required.\n");
		} else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
			$errors = array("Invalid email address.\n");
		} else {
			list($username, $hostname) = split('@', $email);
			if (function_exists('getmxrr')) {
				if (getmxrr($hostname, $mxhosts, $mxweights)) {
					$result['mx_records'] = array_combine($mxhosts, $mxweights);
					asort($result['mx_records']);
				} else {
					$errors = "No MX record found.";
				}
			}
	
			foreach ($mxhosts as $host) {
				$fp = @fsockopen($host, $this->options['port'], $errno, $errstr, 
                                       $this->options['timeout']);
				if ($fp) {
					$data = fgets($fp);
					$code = substr($data, 0, 3);
					if($code == '220') {
						$sender_domain = split('@', $this->options['sender']);
						fwrite($fp, "HELO {$sender_domain}\r\n");
						fread($fp, 4096);
						fwrite($fp, "MAIL FROM: <{$this->options['sender']}>\r\n");
						fgets($fp);
						fwrite($fp, "RCPT TO:<{$email}>\r\n");
						$data = fgets($fp);
						$code = substr($data, 0, 3);
						$result['response'] = array("code" => $code, "data" => $data);
						fwrite($fp, "quit\r\n");
						fclose($fp);
						switch ($code) {
							case "250":  // We're good, so exit out of foreach loop
							case "421":  // Too many SMTP connections
							case "450":
							case "451":  // Graylisted
							case "452":
								$result['valid'] = true;
								break 2;  // Assume 4xx return code is valid.
							default:
								$errors[] = "({$host}) RCPT TO: {$code}: {$data}\n";
						}
					} else {
						$errors[] = "MTA Error: (Stream: {$data})\n";
					}
				} else {
					$errors[] = "{$errno}: $errstr\n";
				}
			}
		}
		if (!empty($errors)) {
			$result['errors'] = $errors;
		}
		return ($this->options['short_response']) ? $result['valid'] : $result;
	}
}

Although the script has been disclosed in the article, using the SMTP to verify the email address is somewhat dangerous for three reasons: (1) Not all MTAs will have the VRFY command turned on to enable this functionality, (2) Some MTAs may return incorrect status code due to server busy or graylist reasons, and (3) Sending multiple "RCPT TO" request to a same MTA may result in enrollment into a blacklist.

Conclusion

The article provides a script for validating email addresses using the SMTP (Simple Mail Transfer Protocol) server. The script is a modified version of the PHP SMTP Email Validation from Google Project. It also discusses the potential dangers of using SMTP for email address verification.

Our sister site has an online tool that validates an email address.

References

  • http://www.devshed.com/c/a/PHP/Email-Address-Verification-with-PHP/
  • http://www.linuxjournal.com/article/9585
  • http://www.webdigi.co.uk/blog/2009/how-to-check-if-an-email-address-exists-without-sending-an-email/
  • http://code.google.com/p/php-smtp-email-validation/
  • http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html

Share this post

Comments (0)

    No comment

Leave a comment

All comments are moderated. Spammy and bot submitted comments are deleted. Please submit the comments that are helpful to others, and we'll approve your comments. A comment that includes outbound link will only be approved if the content is relevant to the topic, and has some value to our readers.


Login To Post Comment