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/department=shipping@example.com
or abc!def!xyz%yyy@example.com
(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:
- Allows international domains, and special characters in the email address
- Checks for domain existance
- 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("test@domain.com");