Validating email addresses in PHP with Preg filters, DNS, MX Servers and other checks

April 12, 2010

UPDATE: It is now easier to send a confirmation email to the provided address to validate it, or to use a framework than a custom script.

There are many tutorials online that show users how to validate an email address, but most do it wrong. This means many websites will reject valid addresses such as customer/[email protected] or abc!def!xyz%[email protected] (yes, they are valid) with the following expression:

"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$"

If you're here through search then you've probably already seen a load of these!

The code I'm going to provide:

  1. Allows international domains, and special characters in the email address
  2. Checks for domain existance
  3. Checks for mx records

So...to the code. This was put together from a number of sources, then simply based off an article over at LinuxJournal.

<?php
$email = $_POST['email'];
if ($email) {

function ValidateEmail($email) {
	
	// Set test to pass
	$valid = true;
	// Find the last @ in the email
	$findats = strrpos($email, "@");
		// Check to see if any @'s were found
		if (is_bool($findats) && !$findats) {
		$valid = false;
		}
		else {
		// Phew, it's still ok, continue...
		// Let's split that domain up.
		$domain = substr($email, $findats+1);
		$local = substr($email, 0, $findats);
		// Find the local and domain lengths
		$locallength = strlen($local);
		$domainlength = strlen($domain);
			// Check local (first part)
			if ($locallength < 1 || $locallength > 64) {
			$valid = false;
			}
			// Better check the domain too
			elseif ($domainlength < 1 || $domainlength > 256) {
			$valid = false;
			}
			// Can't be having dots at the start or end
			elseif ($local[0] == '.' || $local[$locallength-1] == '.') {
			$valid = false;
			}
			// Don't want 2 (or more) dots in the email
			elseif ((preg_match('/\\.\\./', $local)) || (preg_match('/\\.\\./', $domain))) {
			$valid = false;
			}
			// Make sure the domain has valid chars
			elseif (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
			$valid = false;
			}
			// Make sure the local has valid chars, make sure it's quoted right
			elseif (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) {
				if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
				$valid = false;
				}
			}
			// Whoa, made it this far? Check for domain existance!
			elseif (!(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
			$valid = false;
			}
		}
	if ($valid) {
	echo $email.' is valid!';
	}
	else {
	echo $email.' is not valid!<br />';
	}
}

ValidateEmail($email);

}
?>
<form id="form1" name="form1" method="post" action="validateemail.php">
  <p>Email:
    <input type="text" name="email" id="email" />
</p>
  <p>
    <input type="submit" name="submit" id="submit" value="Is it valid?" />
  </p>
</form>

You'd call this with:

ValidateEmail("[email protected]");

Profile picture

From Dave, who writes to learn things. Thoughts and views are his own.

© 2024, withdave.