Skip to content

farisc0de/email_validation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

EmailValidator

A small, dependency-free PHP class for validating email addresses with sensible defaults: RFC syntax, length limits, allow-list of trusted providers, disposable-domain block-list, and DNS lookups.

Single file, single class, PHP 8.0+.


Features

  • Strict syntax check via filter_var(..., FILTER_VALIDATE_EMAIL).
  • RFC 5321 length limits — 64 chars local part, 255 chars domain, 254 chars total.
  • Allow-list of providers — defaults to common consumer mail hosts (Gmail, Outlook, iCloud, Proton, etc.). Pass [] to allow any domain.
  • Disposable-domain block-list — rejects throw-away addresses (Mailinator, Guerrilla Mail, 10MinuteMail, etc.).
  • DNS verification — checks MX, falls back to A / AAAA per RFC 5321 §5. Toggleable for offline / unit tests.
  • Structured result — returns valid, normalized, and machine-readable errors[] codes.
  • Backward-compatible boolean helper (isValid()).
  • No dependencies — pure PHP standard library.

Requirements

  • PHP 8.0 or newer (uses mixed, constructor property promotion, str_contains).
  • ext-filter (bundled with PHP).
  • Network access if checkDns is enabled (default).

Installation

Drop EmailValidator.php anywhere in your project and require it, or autoload it via Composer.

Manual

require_once __DIR__ . '/EmailValidator.php';

Composer (PSR-4)

Move the file to e.g. src/Support/EmailValidator.php, add a namespace at the top:

namespace App\Support;

Then in composer.json:

{
  "autoload": {
    "psr-4": { "App\\": "src/" }
  }
}

Run composer dump-autoload and use App\Support\EmailValidator;.


Quick start

require_once __DIR__ . '/EmailValidator.php';

$validator = new EmailValidator();

if ($validator->isValid('user@gmail.com')) {
    echo 'Looks good!';
}

Structured result

$result = $validator->validate('foo@mailinator.com');

// $result =
// [
//     'valid'      => false,
//     'normalized' => null,
//     'errors'     => ['domain_disposable', 'domain_not_allowed'],
// ];

When valid, normalized contains the trimmed, lower-cased-domain version of the address — the safe form to store in your database.


Configuration

new EmailValidator(
    ?array $allowedProviders   = null,                       // null = defaults, [] = allow any
    array  $disposableProviders = EmailValidator::DISPOSABLE_PROVIDERS,
    bool   $checkDns            = true
);

Allow any provider (still validates syntax + DNS + disposable)

$validator = new EmailValidator(allowedProviders: []);

Custom allow-list (e.g. corporate domains only)

$validator = new EmailValidator(
    allowedProviders: ['acme.com', 'acme.co.uk']
);

Add to the disposable block-list

$validator = new EmailValidator(
    disposableProviders: array_merge(
        EmailValidator::DISPOSABLE_PROVIDERS,
        ['my-extra-bad-domain.tld']
    )
);

Disable DNS lookups (offline / unit tests)

$validator = new EmailValidator(checkDns: false);

Error codes

validate() returns one or more of the following in errors[]:

Code Meaning
email_not_string Input was not a string.
email_empty Input was empty / whitespace only.
email_contains_invalid_chars Characters were stripped by FILTER_SANITIZE_EMAIL.
email_syntax_invalid Failed FILTER_VALIDATE_EMAIL.
email_missing_at No @ found (defensive check).
email_too_long Total length > 254 chars.
local_part_length_invalid Local part empty or > 64 chars.
domain_length_invalid Domain empty or > 255 chars.
domain_missing_tld Domain has no dot.
domain_disposable Domain matched the disposable block-list.
domain_not_allowed Domain not in the allow-list (when one is configured).
domain_no_dns_records No MX, A, or AAAA records for the domain.

These are stable string codes — safe to use for translation keys or API responses.


Usage examples

Form handler

require_once __DIR__ . '/EmailValidator.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $result = (new EmailValidator())->validate($_POST['email'] ?? '');

    if (!$result['valid']) {
        http_response_code(422);
        exit('Invalid email: ' . implode(', ', $result['errors']));
    }

    register_user($result['normalized']);
}

JSON API

header('Content-Type: application/json');
$payload = json_decode(file_get_contents('php://input'), true);

echo json_encode(
    (new EmailValidator())->validate($payload['email'] ?? null)
);

CLI

The bottom of EmailValidator.php ships with a small CLI demo guarded by PHP_SAPI === 'cli', so it never runs when included from a web app.

php EmailValidator.php
php EmailValidator.php you@hotmail.com
php EmailValidator.php bad@@example

Exit code is 0 for valid, 1 for invalid — handy for shell scripts and CI.


Notes & caveats

  • checkdnsrr() requires outbound DNS. If your host blocks it, set checkDns: false or stub it in tests.
  • DNS existence does not guarantee the mailbox exists — only the domain is reachable. For deliverability checks, use a dedicated service (SMTP probe, Mailgun, Postmark, etc.).
  • FILTER_VALIDATE_EMAIL is intentionally stricter than RFC 5322; some technically valid but exotic addresses (quoted local parts, IP-literal domains) may be rejected. This is usually what you want.
  • The default allow-list is opinionated. If you accept signups from any domain, pass allowedProviders: [].

License

MIT — do whatever you want, no warranty.

About

Simple PHP snippet to validate emails server side

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages