Sign Up Free

Email Verification with Regex — JavaScript & PHP

Regular expressions are the first line of defense in email validation. They catch malformed addresses instantly on the client side before any server request is made. This guide covers practical regex patterns for JavaScript and PHP, explains their limitations, and shows when you need API-based verification instead.

Why Regex Is the Starting Point for Email Validation

Every email address follows a standard format defined by RFC 5322: a local part, an @ symbol, and a domain part. Regex (regular expressions) lets you enforce this structure in code before the address ever reaches your server or database. A well-crafted regex pattern catches typos, missing characters, and obviously invalid addresses in milliseconds.

However, regex alone cannot tell you whether an email address actually exists. It validates format, not deliverability. A perfectly formatted address like user@nonexistent-domain-xyz.com passes every regex check but will bounce when you try to send to it. Understanding where regex fits in the validation pipeline — and where its limits begin — is essential for building robust email handling.

This guide provides production-ready regex patterns for JavaScript and PHP, explains the tradeoffs between strict and permissive patterns, and shows how to combine regex with API-based verification for comprehensive email validation.

Email Address Structure: What Regex Needs to Match

Before writing regex patterns, you need to understand the anatomy of an email address. According to RFC 5322, an email address consists of two parts separated by the @ symbol:

The Local Part (Before @)

The local part identifies the specific mailbox on the server. It can contain uppercase and lowercase Latin letters (A-Z, a-z), digits (0-9), and certain special characters including dots, hyphens, underscores, and plus signs. Dots cannot appear at the start or end and cannot appear consecutively. The maximum length is 64 characters.

Technically, RFC 5322 allows quoted strings with nearly any character, including spaces and special symbols, but in practice almost no modern email provider supports this. Your regex should handle real-world addresses, not theoretical edge cases.

The Domain Part (After @)

The domain part identifies the mail server. It consists of labels separated by dots, where each label can contain letters, digits, and hyphens. Labels cannot start or end with a hyphen. The top-level domain (TLD) must be at least two characters. The maximum total domain length is 253 characters.

Internationalized Email Addresses

Modern standards (RFC 6531) allow non-ASCII characters in both the local and domain parts. Addresses like user@example.com with Unicode characters are valid but require special handling. Most regex patterns do not account for internationalized addresses, and you should decide whether your application needs to support them based on your audience.

Email Regex Patterns for JavaScript

JavaScript is the most common language for client-side email validation. Here are three patterns ranging from simple to comprehensive, each with different tradeoffs between strictness and usability.

Basic Pattern — Quick Validation

This pattern catches the most common formatting errors with minimal complexity:

// Basic email regex — catches obvious errors
const basicEmailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function validateEmail(email) {
  return basicEmailRegex.test(email);
}

// Examples
validateEmail('user@example.com');     // true
validateEmail('user@.com');            // false
validateEmail('user@example');         // false
validateEmail('user example.com');     // false
validateEmail('@example.com');         // false

This pattern checks for at least one character before @, at least one character after @, a dot in the domain, and no whitespace anywhere. It is intentionally permissive — it accepts some technically invalid addresses but never rejects a valid one. For most signup forms, this is sufficient as a first pass.

Standard Pattern — Balanced Validation

This pattern adds character class restrictions and length checks for better accuracy:

// Standard email regex — good balance of accuracy and simplicity
const standardEmailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

function validateEmail(email) {
  if (email.length > 320) return false;  // RFC max total length
  return standardEmailRegex.test(email);
}

// Examples
validateEmail('john.doe@example.com');       // true
validateEmail('user+tag@company.co.uk');     // true
validateEmail('name@sub.domain.com');        // true
validateEmail('user@com');                   // false (TLD only)
validateEmail('user@-example.com');          // true (limitation)
validateEmail('user@example..com');          // false

This is the most widely used pattern in production applications. It handles plus addressing, subdomains, multi-part TLDs, and most real-world email formats. It does not catch every edge case (like hyphens at the start of domain labels), but it correctly validates over 99% of real addresses.

Comprehensive Pattern — Strict Validation

This pattern enforces stricter RFC compliance including local part rules and domain label constraints:

// Comprehensive email regex — strict RFC-aligned validation
const strictEmailRegex = /^(?!.*\.\.)(?!^\.)[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(? 320) return false;
  const [local, domain] = email.split('@');
  if (!local || !domain) return false;
  if (local.length > 64) return false;
  if (domain.length > 253) return false;
  return strictEmailRegex.test(email);
}

// Examples
validateEmailStrict('user@example.com');        // true
validateEmailStrict('.user@example.com');        // false (leading dot)
validateEmailStrict('user.@example.com');        // false (trailing dot)
validateEmailStrict('user..name@example.com');   // false (consecutive dots)
validateEmailStrict('user@-example.com');        // false (leading hyphen)
validateEmailStrict('user@example-.com');        // false (trailing hyphen)

This pattern uses negative lookaheads and lookbehinds to enforce dot and hyphen placement rules. It is more complex but catches edge cases that simpler patterns miss. Use this when you need strict validation, such as in email service providers or security-critical applications.

Real-Time Validation with Event Listeners

Here is how to implement regex validation in a form with user feedback:

// Real-time email validation in a form
const emailInput = document.getElementById('email');
const feedback = document.getElementById('email-feedback');
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

emailInput.addEventListener('input', function () {
  const value = this.value.trim();

  if (value === '') {
    feedback.textContent = '';
    feedback.className = '';
    return;
  }

  if (emailRegex.test(value)) {
    feedback.textContent = 'Valid email format';
    feedback.className = 'feedback-valid';
  } else {
    feedback.textContent = 'Please enter a valid email address';
    feedback.className = 'feedback-invalid';
  }
});

// On form submit — additional checks before sending
document.getElementById('signup-form').addEventListener('submit', function (e) {
  const email = emailInput.value.trim();
  if (!emailRegex.test(email)) {
    e.preventDefault();
    feedback.textContent = 'A valid email address is required';
    feedback.className = 'feedback-invalid';
  }
});

Email Regex Patterns for PHP

PHP offers both regex-based validation and a built-in filter function. Here are the options and when to use each.

PHP filter_var — The Recommended Approach

PHP's built-in filter_var function with FILTER_VALIDATE_EMAIL is the recommended first choice for PHP applications:

// PHP built-in email validation — recommended first choice
function validateEmail(string $email): bool {
    return filter_var(trim($email), FILTER_VALIDATE_EMAIL) !== false;
}

// Examples
var_dump(validateEmail('user@example.com'));     // true
var_dump(validateEmail('user@example'));          // false
var_dump(validateEmail('user@.com'));             // false
var_dump(validateEmail(''));                      // false

The filter_var function follows RFC 5322 closely and handles edge cases that most custom regex patterns miss. It is maintained by the PHP core team and updated with each PHP release. Unless you have specific requirements that filter_var does not meet, use it instead of writing your own regex.

Custom PHP Regex — When You Need More Control

If you need custom validation rules beyond what filter_var provides, here is a comprehensive regex approach:

// Custom PHP email validation with regex
function validateEmailRegex(string $email): array {
    $email = trim($email);
    $errors = [];

    // Length checks
    if (strlen($email) > 320) {
        $errors[] = 'Email address exceeds maximum length';
        return ['valid' => false, 'errors' => $errors];
    }

    $parts = explode('@', $email);
    if (count($parts) !== 2) {
        $errors[] = 'Email must contain exactly one @ symbol';
        return ['valid' => false, 'errors' => $errors];
    }

    [$local, $domain] = $parts;

    // Local part validation
    if (strlen($local) > 64) {
        $errors[] = 'Local part exceeds 64 characters';
    }
    if (strlen($local) === 0) {
        $errors[] = 'Local part cannot be empty';
    }
    if (!preg_match('/^[a-zA-Z0-9._%+\-]+$/', $local)) {
        $errors[] = 'Local part contains invalid characters';
    }
    if (str_starts_with($local, '.') || str_ends_with($local, '.')) {
        $errors[] = 'Local part cannot start or end with a dot';
    }
    if (str_contains($local, '..')) {
        $errors[] = 'Local part cannot contain consecutive dots';
    }

    // Domain validation
    if (strlen($domain) > 253) {
        $errors[] = 'Domain exceeds 253 characters';
    }
    if (!preg_match('/^(?!-)([a-zA-Z0-9-]{1,63}\.)+[a-zA-Z]{2,63}$/', $domain)) {
        $errors[] = 'Domain format is invalid';
    }

    return [
        'valid' => empty($errors),
        'errors' => $errors,
    ];
}

// Usage
$result = validateEmailRegex('user@example.com');
if ($result['valid']) {
    echo "Email format is valid\n";
} else {
    foreach ($result['errors'] as $error) {
        echo "Error: $error\n";
    }
}

This approach returns detailed error messages explaining exactly what is wrong with the address. This is useful for APIs, admin tools, and any context where you want to give the user specific guidance on fixing their input.

Combining filter_var with DNS Checks in PHP

You can go a step beyond regex by combining format validation with DNS verification:

// PHP validation with DNS check
function validateEmailWithDns(string $email): array {
    $email = trim(strtolower($email));

    // Step 1: Format validation
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return ['valid' => false, 'reason' => 'Invalid email format'];
    }

    // Step 2: Extract domain
    $domain = substr($email, strrpos($email, '@') + 1);

    // Step 3: Check MX records
    if (!checkdnsrr($domain, 'MX')) {
        // Fallback to A record (some domains use A records for mail)
        if (!checkdnsrr($domain, 'A')) {
            return ['valid' => false, 'reason' => 'Domain has no mail server'];
        }
    }

    return ['valid' => true, 'reason' => 'Format valid, mail server found'];
}

$result = validateEmailWithDns('user@example.com');
echo $result['reason'];

This adds a DNS lookup to confirm the domain has mail servers configured. It catches cases where the format is valid but the domain cannot receive email. Note that DNS checks add latency (typically 50-200ms) and require network access, so they are not suitable for real-time client-side validation.

Common Email Regex Mistakes

Developers frequently make the same mistakes when writing email regex. Here are the most common ones and how to avoid them.

Being Too Strict with the TLD

Some patterns hardcode TLD length limits like [a-zA-Z]{2,4}, which rejects valid TLDs like .travel, .museum, and the hundreds of new gTLDs like .photography and .technology. Use [a-zA-Z]{2,} or [a-zA-Z]{2,63} instead.

Rejecting Plus Addressing

Patterns that exclude the + character from the local part reject addresses like user+newsletter@gmail.com. Plus addressing is a standard feature supported by Gmail, Outlook, and most providers. Users rely on it for email filtering, and rejecting it frustrates power users and causes lost signups.

Ignoring Case Sensitivity

The domain part of an email address is case-insensitive per RFC. The local part is technically case-sensitive, but virtually all providers treat it as case-insensitive. Always normalize emails to lowercase before storage and comparison, but do not reject mixed-case input.

Not Trimming Whitespace

Users frequently copy-paste email addresses with leading or trailing spaces. Always trim() the input before validation. A valid email with a trailing space should not fail your regex.

Using Overly Complex RFC-Compliant Patterns

The fully RFC 5322-compliant regex is over 6,000 characters long. It handles obscure syntax like quoted strings, IP address literals, and nested comments that no real email provider uses. In practice, a simpler pattern that covers 99.9% of real addresses is better than a theoretically complete pattern that is impossible to maintain and debug.

Regex vs API-Based Email Verification

Regex and API verification serve different purposes and are not interchangeable. Understanding their differences helps you build a proper validation pipeline.

What Regex Can Do

  • Validate email format and structure instantly (under 1ms)
  • Run client-side with no server or network required
  • Catch typos, missing @, double dots, and malformed addresses
  • Provide instant feedback to users as they type
  • Cost nothing — no API calls, no rate limits

What Regex Cannot Do

  • Verify the domain exists and has mail servers
  • Confirm the mailbox exists on the mail server
  • Detect disposable or temporary email addresses
  • Identify role-based addresses (info@, admin@, support@)
  • Check if the address is on a spam trap list
  • Determine if the address has historically bounced
  • Detect catch-all domains where any address appears valid

The Proper Validation Pipeline

Best practice is to use both in sequence:

  • Step 1 — Client-side regex: Catch obvious format errors instantly as the user types. This prevents unnecessary API calls and gives immediate feedback.
  • Step 2 — Server-side regex: Re-validate on the server because client-side validation can be bypassed. Never trust client-only validation.
  • Step 3 — API verification: For addresses that pass regex, make an API call to verify the mailbox exists, the domain is configured for email, and the address is not disposable or risky. Use a service like EmailVerifier.com for this step.

This layered approach gives you instant user feedback, server-side security, and verified deliverability. Regex handles the fast, free first pass. The API handles the thorough verification that regex cannot do.

Email Regex in Popular Frameworks

Node.js with Express

// Express middleware for email validation
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

function validateEmailMiddleware(req, res, next) {
  const { email } = req.body;

  if (!email || typeof email !== 'string') {
    return res.status(400).json({ error: 'Email is required' });
  }

  const trimmed = email.trim().toLowerCase();

  if (trimmed.length > 320) {
    return res.status(400).json({ error: 'Email address is too long' });
  }

  if (!emailRegex.test(trimmed)) {
    return res.status(400).json({ error: 'Invalid email format' });
  }

  req.body.email = trimmed;
  next();
}

// Usage in route
app.post('/signup', validateEmailMiddleware, async (req, res) => {
  // req.body.email is now validated and normalized
  const { email } = req.body;
  // Proceed with signup logic...
});

Laravel (PHP)

// Laravel validation — uses filter_var internally
$request->validate([
    'email' => 'required|email:rfc,dns|max:320',
]);

// Custom rule for stricter validation
use Illuminate\Contracts\Validation\Rule;

class StrictEmail implements Rule {
    public function passes($attribute, $value): bool {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            return false;
        }
        $domain = substr($value, strrpos($value, '@') + 1);
        return checkdnsrr($domain, 'MX');
    }

    public function message(): string {
        return 'The email address must be valid with an active mail server.';
    }
}

React Form Validation

// React component with email validation
import { useState } from 'react';

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

function SignupForm() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const handleChange = (e) => {
    const value = e.target.value;
    setEmail(value);

    if (value && !emailRegex.test(value.trim())) {
      setError('Please enter a valid email address');
    } else {
      setError('');
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const trimmed = email.trim().toLowerCase();

    if (!emailRegex.test(trimmed)) {
      setError('A valid email address is required');
      return;
    }

    // Submit to server for API verification...
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={handleChange} />
      {error && <span className="error">{error}</span>}
      <button type="submit">Sign Up</button>
    </form>
  );
}

Testing Your Email Regex Thoroughly

Every email regex should be tested against a comprehensive set of valid and invalid addresses. Here is a test suite you can adapt:

// Test suite for email regex validation
const testCases = [
  // Valid addresses
  { email: 'simple@example.com', expected: true },
  { email: 'user.name@example.com', expected: true },
  { email: 'user+tag@example.com', expected: true },
  { email: 'user@sub.domain.com', expected: true },
  { email: 'user@example.co.uk', expected: true },
  { email: 'firstname.lastname@company.com', expected: true },
  { email: 'user@123.123.123.com', expected: true },
  { email: 'user_name@example.com', expected: true },
  { email: '1234567890@example.com', expected: true },
  { email: 'user@example.photography', expected: true },

  // Invalid addresses
  { email: '', expected: false },
  { email: 'plaintext', expected: false },
  { email: '@example.com', expected: false },
  { email: 'user@', expected: false },
  { email: 'user@.com', expected: false },
  { email: 'user@com', expected: false },
  { email: 'user @example.com', expected: false },
  { email: 'user@example..com', expected: false },
  { email: '.user@example.com', expected: false },
  { email: 'user.@example.com', expected: false },
];

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

testCases.forEach(({ email, expected }) => {
  const result = regex.test(email);
  const status = result === expected ? 'PASS' : 'FAIL';
  console.log(`${status}: "${email}" — expected ${expected}, got ${result}`);
});

When You Need API Verification Instead of Regex

Regex is appropriate for instant format validation, but certain use cases require API-based verification. Use an email verification API when:

  • You are sending transactional emails: Bounced password resets and order confirmations create a poor user experience. API verification confirms the address exists before you rely on it.
  • You are building an email list: List quality directly impacts deliverability. Bulk verification catches invalid addresses that regex cannot detect.
  • You need to block disposable emails: Regex cannot identify disposable email domains. API verification checks against databases of 150,000+ known disposable domains.
  • Bounce rates are hurting your reputation: If you are experiencing bounce rates above 2%, regex is not catching the invalid addresses. API verification typically reduces bounce rates to under 0.5%.
  • You are importing email data: Purchased or scraped lists contain high percentages of invalid addresses. Always verify imported data with an API before sending.

Try our free email verifier to see API-based verification in action. It performs syntax checking, domain validation, MX record lookup, SMTP mailbox verification, and disposable email detection — everything regex cannot do.

Frequently Asked Questions

For most applications, the pattern /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ provides the best balance of accuracy and simplicity. It correctly validates over 99% of real-world email addresses including plus addressing, subdomains, and modern TLDs. Avoid overly complex RFC-compliant patterns that are impossible to maintain.

No. Regex can only validate the format (syntax) of an email address. It cannot verify that the domain exists, that the mail server is configured, or that the specific mailbox is real. A perfectly formatted address like user@nonexistent-domain.com passes every regex check but will bounce. Use regex for instant format checking and an API for deliverability verification.

Common causes include rejecting plus addressing (user+tag@domain.com), using a TLD length limit that is too restrictive (like {2,4} which rejects .travel and .photography), not allowing hyphens or underscores in the local part, and not trimming whitespace before validation. Test your regex against a comprehensive set of valid addresses.

Use both. The HTML5 email input type (type="email") provides basic browser-native validation but its rules vary across browsers and are generally very permissive. Add your own regex validation on top for consistent behavior, and always re-validate on the server since client-side validation can be bypassed.

Yes. PHP filter_var with FILTER_VALIDATE_EMAIL is the recommended approach for PHP email validation. It follows RFC 5322 closely, handles edge cases that custom regex patterns miss, and is maintained by the PHP core team. Use it instead of writing your own regex unless you have specific requirements it does not meet.

In React, validate client-side using a regex pattern in your onChange or onSubmit handler for instant feedback. In Node.js, re-validate server-side using the same regex pattern in Express middleware. Always validate on both client and server — client-side validation improves UX, server-side validation ensures security since client-side checks can be bypassed.

Go Beyond Regex — Verify Emails for Real

Regex validates format. Our API verifies deliverability. Check any email address for free — syntax, domain, MX records, and mailbox existence in under 3 seconds.