Ensuring Proper Email Validation in PHP: Avoiding False Positives
When working with email validation in PHP, you might assume that using FILTER_VALIDATE_EMAIL
is enough. However, this built-in filter can sometimes allow invalid email formats, leading to unexpected issues in your application. A common example is a string like +44112233
, which is clearly not an email, yet PHP may not flag it as invalid.
Why FILTER_VALIDATE_EMAIL
Alone Is Not Enough
PHP's filter_var($email, FILTER_VALIDATE_EMAIL)
function only checks for a valid email syntax based on the RFC 822 standard. However, this standard is quite broad, allowing many unusual formats that are technically valid but not suitable for real-world applications.
For example:
$email = "+44112233";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "Valid email";
} else {
echo "Invalid email";
}
The above incorrectly considers +44112233
to be valid because, under RFC rules, it can be interpreted as a valid email with an implicit domain. This is a problem!
A More Robust Email Validation Approach
To avoid such issues, you should combine FILTER_VALIDATE_EMAIL
with a regular expression to enforce a stricter format. A better approach is:
$email = "+44112233";
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !preg_match('/^[^@]+@[^@]+\.[a-zA-Z]{2,}$/', $email)) {
echo "Invalid email format";
} else {
echo "Valid email";
}
Breaking Down the Improved Validation
FILTER_VALIDATE_EMAIL
– Ensures basic email structure is present.- Regular expression (
preg_match
) – Checks if the email contains an@
symbol and a valid domain (example.com
).[^@]+@[^@]+\.[a-zA-Z]{2,}$
ensures that:- There is at least one character before the
@
. - A domain name exists after
@
. - The domain contains a dot (
.
) followed by at least two letters (TLD).
- There is at least one character before the
Additional Considerations for Email Validation
- Disposable Emails: Some users use temporary/disposable emails. You can integrate an API or maintain a blacklist to prevent such emails.
- Length Limits: RFC 5321 states that an email address should be no more than 320 characters long.
- Allowing Internationalized Domains: If your application supports internationalized domain names (IDN) (e.g.,
jörg@exämple.de
), consider usingidn_to_ascii()
to normalize the domain before validation.
DNS Verification: Checking only the format is not enough; you should verify that the domain exists using checkdnsrr()
.
function isValidEmail($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$domain = substr(strrchr($email, "@"), 1);
return checkdnsrr($domain, "MX");
}
This ensures that the domain has a valid Mail Exchange (MX) record, meaning emails can be received.
Finally
While PHP provides a built-in function for email validation, it is not always strict enough for real-world applications. Combining it with regular expressions, DNS validation, and other checks ensures better accuracy and prevents invalid emails from passing through. By implementing a more robust validation strategy, you can improve data integrity and reduce errors in user input.
Comments ()