How to Validate Emails in PHP: regex, filter_var(), and API Explained
Tags: emailvalidation, php
Published: 2024-05-14 11:14:33

Be it marketing or transactional emails, email address validation is a necessity, or you could risk the reputation of your email domain. 

This tutorial covers the ins and outs of PHP email validation and is primarily designed for beginners. However, I assume you already got the basics of PHP programming skills. 

Also, I’d like to stress the difference between email [validation](https://mailtrap.io/blog/email-validation/) and [verification](https://mailtrap.io/blog/email-verification/). Validation is about the correct formatting of an email address, and it’s a part of verification. It can be done on the server and the client side and I’ll focus on the server side here (no JavaScript, HTML, etc). 

So, let’s get to coding.  

**Note**: The exemplary scripts are based on PHP 8.3.6, and may not work on PHP 7.x.y versions. 

## PHP email validation function: filter_var()

The `filter_var()` function is part of PHP’s filter extension, which provides a convenient way to perform validation and sanitization of various data types using a single function call. 

For email validation, `filter_var()` offers a straightforward, reliable method to quickly assess whether an email address is valid according to PHP standards. For instance, you could integrate it with email form validation on your website. 

Here, I won’t cover the frontend stuff, input fields, and all. I already created an extensive [PHP form validation guide](https://mailtrap.io/blog/php-form-validation/), so feel free to check it out. 

Anyway, the `FILTER_SANITIZE_EMAIL` (as part of ‘filter_var’ function) is engineered to remove characters not permitted in email addresses. This includes, but is not limited to: 

- Spaces, 
- Commas 
- Certain special characters (/, |, #, etc.)

The primary purpose of sanitizing email inputs is to ensure that the data is clean and safe to be processed or stored. This is important when the data gets displayed on a web page, or is included in database queries. The reason is that it helps prevent XSS (Cross-Site Scripting) and SQL injection attacks.

Here’s a practical example of how to sanitize an email input using `filter_var()`: 

```
<?php
// Example email input
$userInputEmail = "john.doe@example.com<script>alert('XSS');</script>";

// Sanitize the email input
$sanitizedEmail = filter_var($userInputEmail, FILTER_SANITIZE_EMAIL);

echo "Original: " . $userInputEmail . "<br>";
echo "Sanitized: " . $sanitizedEmail;
?>
```
In this example, the script tag would be removed from the email input, displaying the sanitized version as john.doe@example.com. It shows how `FILTER_SANITIZE_EMAIL` strips unwanted and potentially harmful characters from email inputs. 

Following this, you would typically validate the sanitized email to ensure it meets the format standards for a valid email address, which I’ll discuss next using `FILTER_VALIDATE_EMAIL`.

### Validating emails with `FILTER_VALIDATE_EMAIL`

The `FILTER_VALIDATE_EMAIL` checks whether the given string conforms to the format of a valid email address. It ensures the email address includes a valid username, an @ symbol, and a valid domain name with a domain extension.

Simply, `FILTER_VALIDATE_EMAIL` enforces proper email format standards. And here’s what the standards typically include:

- A username – can contain letters, numbers, dots, hyphens, and underscores.
- An @ symbol as a separator.
- A domain name that includes letters and may contain dots or hyphens.
- A domain extension, which must be at least two characters long and primarily contain letters.

While very effective for basic validation, the filter has some limitations:

- **Unicode characters**: It does not support email addresses with international characters outside of the basic Latin alphabet.
- **Advanced formats**: Certain valid email formats as per the Internet standards ([RFC standards](https://datatracker.ietf.org/doc/html/rfc2822)) may not be recognized by this filter, such as emails with quoted strings or certain special characters.

The limitations indicate that `FILTER_VALIDATE_EMAIL` may not suffice for applications requiring robust internationalization or adherence to the latest email address standards.

But no worries, I’ll tell you how to overcome that under the [Email validation in PHP using API section](https://mailtrap.io/blog/php-email-validation/#using-api). Here’s a practical example of how to use the filter for basic validation. 

```
<?php
// Example email input
$userInputEmail = "john.doe@example.com";

// Validate the email input
if (filter_var($userInputEmail, FILTER_VALIDATE_EMAIL)) {
    echo "The email address '$userInputEmail' is considered valid.";
} else {
    echo "The email address '$userInputEmail' is considered invalid.";
}
?>
```
To wrap up, I’d like to give you some tips on how to handle verification failures without annoying your users. 

- **User feedback**: Just an “Invalid email address” message won’t suffice. Provide clear and constructive feedback to users, helping them understand why their email was invalid and what they can do to correct it.
- **Logging**: Keep logs of failed validation attempts for debugging purposes or to identify potential misuse of the system. 
- **Alternative validation**: Consider alternative methods of validation for special cases, such as allowing list-specific addresses or domain-specific addresses

## Regular expression for email validation in PHP

Regular expressions (regex) offer a flexible method for validating email addresses in a PHP function. 

For instance, this approach works nicely in scenarios where you might need to validate emails based on specific criteria that are not covered by `FILTER_VALIDATE_EMAIL`, such as:

- Restricting email addresses to certain domains.
- Enforcing specific prefixes or suffixes in the email username.
- Allowing newer top-level domains (TLDs) or internationalized domain names.

Also, regex can be used to implement complex pattern-matching rules necessary for applications requiring precise control over the user input.

Now, I’ll show you how to create and integrate a regex. But before that, I’d have to touch upon the components of an email address as defined by the RFC 5322 standard. It helps wrap your mind around pattern-matching syntax for email validation use cases.

- **Local part**: The local part of the email (before the @ symbol) may include a variety of characters (a-z, A-Z, 0-9) including special characters such as . (dot), – (hyphen), and _ (underscore). It can also contain quoted strings allowing almost any character within the quotes.
- **Domain part**: The domain part (after the @ symbol) typically includes alphanumeric characters and may include hyphens and dots. The domain must not start or end with a hyphen.

Here’s an example of a pattern that matches the given standards.  

```
<?php
$email = "test@example.com";
$pattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';

if (preg_match($pattern, $email)) {
    echo "The email address '$email' is considered valid.";
} else {
    echo "The email address '$email' is considered invalid.";
}
?>
```
The regex matches the following:

- One or more characters in the local part, including alphanumeric characters and special characters (._%+-).
- An @ symbol, separating the local and domain parts.
- A domain part consisting of one or more alphanumeric characters, potentially including dots and hyphens.
- A top-level domain (TLD) that must be at least two characters long.

So far so good, but if you need a more custom thing, here are a couple of suggestions on how to tweak the function filters. 

1. **Tighten the criteria**: Restrict the email to specific domains or subdomains by replacing the domain part of the pattern with a literal string (e.g., example.com).

```
// Example for tightened criteria: Only allowing emails from specific domains
$pattern = '/^[a-zA-Z0-9._%+-]+@(example\.com|example\.net)$/';
```
2. **Relax the criteria**: Allow additional characters in the local part or more variations in the TLD.

```
// Example for a relaxed criteria: Allowing international characters in the local part
$pattern = '/^[a-zA-Z0-9._%+-\p{L}]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/u';
```
Even though regexes provide significant control over input validation, it’s vital to test thoroughly (I’ll cover that in a second) to ensure that the pattern meets all functional requirements. The goal is to avoid excluding valid emails or including invalid ones inadvertently.

This is how you might approach testing a regex pattern for email validation:

```
<?php
$emails = [
    "test@example.com", // Valid
    "test.example@com", // Invalid: no top-level domain
    "test_example.com", // Invalid: missing '@'
    "test@example.com.", // Invalid: dot at the end of the domain
    "ñandu@dominio.com" // Valid if Unicode is considered
];

$pattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';

foreach ($emails as $email) {
    if (preg_match($pattern, $email)) {
        echo "The email address '$email' is valid.\n";
    } else {
        echo "The email address '$email' is invalid.\n";
    }
}
?>
```
Also, you should consider debugging, check the tips to follow:

- **Use online regex testers**: Tools like [Regex101](https://regex101.com/) or [RegExr](https://regexr.com/) can help visualize how your regex matches against test strings, providing explanations and highlighting potential issues.
- **Log troublesome inputs**: When a user input fails validation, log the input for review. This can help identify what the regex may be failing to catch.
- **Unit testing**: Implement unit tests to automatically check the regex against known valid and invalid emails.

As regexes can be a blessing and a curse, I’ll finish this section with some best practices and common mishaps. 

**Best Practices:**

- **Keep it readable**: While regex can be compact, overly complex patterns can become unreadable and difficult to maintain. Use comments and break complex patterns into smaller parts if necessary.
- **Use non-capturing groups**: Unless you need to capture parts of the email for later use in the code, use non-capturing groups`(?: ...)` to avoid unnecessary performance overhead.
- **Specify character ranges explicitly**: Avoid using broad classes like ‘`.\*`’ when validating emails. Instead, encode exactly which characters are allowed in each part of the email.
- **Use anchors**: Always use `^` (start of string) and `$` (end of string) anchors to ensure that the entire string matches the pattern, preventing partial matches.

** Common Mishaps:**

- **Escaping characters**: Failing to escape special regex characters like `.`, `?`, and `+` can lead to unintended matches.
- **Performance issues**: Regex that uses excessive backtracking (e.g., nested quantifiers like `(a+)+)` can cause performance issues.
- **Unicode ignorance**: If international characters are a requirement, forgetting to handle Unicode properly can exclude valid emails with international characters.

## Email validation in PHP using API

APIs offer advanced capabilities beyond what local methods can provide, and here’s what they are. 

1. **Enhanced accuracy**: APIs often use sophisticated algorithms with a real-time data lookup that goes beyond simple format validation. They can check if an email address is correctly formatted and verify it (confirm the address exists and can receive emails).
2. **Reduce local resource usage**: Offloading the validation process to an external service can reduce the load on your local systems, which is beneficial for applications with high volumes of email processing.
3. **Access to additional data**: Some APIs also offer information like whether the email is a disposable address, its risk score for being spam, or its general reputation.

For this tutorial, I’ll discuss a generic approach to integrating an email validation API. While specific details can vary between providers, the general principles of making a request and handling a response are similar across most services.

I assume that you already chose an email validation API provider and obtained their API credentials. So, here’s how to implement the request. 

```
<?php
$email = "test@example.com";
$apiKey = "YOUR_API_KEY";
$apiUrl = "https://api.emailvalidator.com/validate?apiKey={$apiKey}&email={$email}";

$response = file_get_contents($apiUrl);
if ($response !== false) {
    $data = json_decode($response, true);
    print_r($data);
} else {
    echo "API request failed.";
}
?>
```
In this scenario, it’s also important to handle API responses properly and manage errors. The responses usually come in JSON format containing various fields indicating the validation results. You need to parse these responses and react accordingly in your application logic.

As for managing errors, you should cover network issues, invalid API keys, or exceeded rate limits. Use try-catch blocks or check for errors in the response to ensure robustness. Here’s an example. 

```
<?php
try {
    $response = file_get_contents($apiUrl);
    if ($response === false) {
        throw new Exception("API request failed.");
    }
    $data = json_decode($response, true);
    if (isset($data['error'])) {
        throw new Exception("Error from API: " . $data['error']);
    }
    print_r($data);
} catch (Exception $e) {
    echo "An error occurred: " . $e->getMessage();
}
?>
```

## Email validation as part of email testing

I won’t beat around the bush, here are four main reasons to validate addresses when testing emails. 

1. **Deliverability, deliverability, and always deliverability**

By verifying that an email address is formatted correctly and is valid, you reduce the risk of sending emails to non-existent addresses, which can hurt your sender’s reputation and impact deliverability.

2. **Spam compliance** 

Sending emails to invalid addresses frequently leads to higher bounce rates, which are monitored by Internet Service Providers (ISPs). Consequently, it can lead to blacklisting of your sending IP address. By ensuring that email addresses are valid, you avoid penalties associated with violating spam laws (CAN-SPAM and GDPR).

3. **Improved quality of user data**

Regular email validation as part of email testing helps maintain high-quality user data. Clean, validated email lists improve the effectiveness of email marketing campaigns and reduce the cost associated with managing undeliverable emails.

4. **Automation**

Automating email validation processes can significantly enhance the efficiency and reliability of your email testing strategies. Automation ensures that email validation checks are performed consistently, without manual intervention, making the processes scalable and error-resistant.

Of course, there are specific tools and techniques to automate email tests. First, I’ll cover [Mailtrap Email Testing](https://mailtrap.io/email-sandbox/), part of [Mailtrap Email Delivery Platform](https://mailtrap.io/). Then, I’ll talk about dedicated validation services, custom scripts, and cron jobs.  
{% embed https://youtu.be/AveaJc6c3fI %}

Mailtrap Email Testing is an email sandbox to inspect and debug emails in staging, dev, and QA environments before sending them to recipients. 

I need to stress that the sandbox doesn’t include email validation. However, you can run a custom validation script and a cron job in parallel with Mailtrap Email Testing. Or you could check the addresses just before sending the emails on production. 

This is particularly useful if you use [Mailtrap Testing API](https://api-docs.mailtrap.io/docs/mailtrap-api-docs/a2041e813d169-email-testing-api), which allows you to easily test templates and automate QA processes. Then, you can switch from sandbox to production environment and keep sending to valid addresses. 

Aside from a reliable REST API, and a fake SMTP server, you also get the following:

- HTML/CSS check
- Spam score check
- API for QA automation
- Ready-to-use integrations in 20+ languages (Ruby, Python, PHP, Node.js, .Net, etc.)
- Emails preview
- Multiple inboxes for different projects and stages
- User management, SSO

Lastly, the whole setup is straightforward, you just need to do the following: 

1. [Sign up for Mailtrap](https://mailtrap.io/register/signup?ref=header)
2. Go to **Email Testing > Inboxes > My Inbox**  
3. Choose your preferred integration or copy-paste SMTP credentials to your project
4. Run the code and get the test email in an instant

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nej5y52wyvjq521kxl5u.png)

Now, here’s a custom PHP email validation script that can be run as a cron job to validate email addresses with a third-party API:

```
<?php
function validateEmail($email) {
    $apiKey = 'YOUR_API_KEY';
    $apiUrl = "https://api.emailvalidator.com/validate?apiKey={$apiKey}&email={$email}";

    $response = file_get_contents($apiUrl);
    if ($response !== false) {
        $data = json_decode($response, true);
        return $data['isValid'];
    }
    return false;
}

// Example email to validate
$email = 'test@example.com';
if (validateEmail($email)) {
    echo "Email is valid.\n";
} else {
    echo "Email is invalid.\n";
}
?>
```
Also, here’s how to automate the whole thing with a cron job on a Linux server. 

```
0 1 * * * /usr/bin/php /path/to/your/script.php
```

The job runs the script once a day at 1:00 AM. 

Now, your task is to set up all the automation, sit back and relax knowing your domain and IP reputations are safe. 

We appreciate the you chose this article to know more about PHP email validation. If you want to find more interesting content on related topics, follow [Mailtrap blog](https://mailtrap.io/blog/php-email-validation/)!