Search by

iliaal / smtp-validate-email

iliaa

Validates an email address by checking for MX records and performing an SMTP triplet connection

Package info

github.com/iliaal/smtp-validate-email

pkg:composer/iliaal/smtp-validate-email

Statistics

Installs: 13

Dependents: 0

Suggesters: 0

Stars: 0

v2.0.0 2026-10-26 13:05 UTC

This package is auto-updated.

Last update: 2026-10-26 13:15:42 UTC


README

Perform email address validation/verification via SMTP.

Retrieves MX records for the email domain and connects to the domain's SMTP server to determine if the address actually exists, without sending a message.

Features

  • Graceful session reset (no message is sent)
  • Command-specific timeouts per RFC 2821
  • Catch-all account detection
  • Batch mode with single connection per domain
  • STARTTLS support
  • Email format validation via filter_var before SMTP probing
  • Duplicate address deduplication
  • Logging and debug output

Requirements

  • PHP 8.1+
  • getmxrr() support (Linux/BSD; not available on Windows, where MX lookups raise a descriptive exception)

Installation

composer require iliaal/smtp-validate-email

Usage

Single email

use SMTPValidateEmail\SMTPValidateEmail;

$from = 'sender@yourdomain.com';
$email = 'address-to-verify@example.com';

$validator = new SMTPValidateEmail($email, $from);
$results = $validator->validate();

print_r($results);

Batch validation

Emails on the same domain share a single SMTP connection.

use SMTPValidateEmail\SMTPValidateEmail;

$from = 'sender@yourdomain.com';
$emails = [
    'alice@example.com',
    'bob@example.com',
    'someone@other-domain.com',
];

$validator = new SMTPValidateEmail($emails, $from);
$results = $validator->validate();

print_r($results);

Configuration

All options are public properties set before calling validate():

$validator = new SMTPValidateEmail();

// Treat catch-all domains as valid (default: true)
$validator->catchall_is_valid = true;

// Enable catch-all detection (default: false)
$validator->catchall_test = false;

// Treat communication failures as valid (default: false)
$validator->no_comm_is_valid = false;

// Treat connection failures as valid (default: false)
$validator->no_conn_is_valid = false;

// Treat greylisted real-recipient responses as valid (default: true)
$validator->greylisted_considered_valid = true;
// Temporary failures of random catch-all probes never prove a catch-all.

// SMTP port (default: 25)
$validator->connect_port = 25;

// Send NOOP between RCPT TO commands (default: false)
$validator->noop = false;

// Enable debug output (default: false)
$validator->debug = false;

// Verify TLS certificates during STARTTLS (default: false; many MXs use mismatched certs)
$validator->ssl_verify_peer = false;

The sender address (constructor / set_sender() / validate(..., $sender)) must be a usable local@domain string. Control characters (CR/LF/NUL) and <> are rejected to prevent SMTP command injection. Recipients are still validated with filter_var().

Results

validate() returns an associative array:

[
    'user@example.com' => true,          // valid
    'bogus@example.com' => false,        // invalid
    'bogus@example.com_error_msg' => 'No such user',
    'domains' => [
        'example.com' => [
            'users' => ['user', 'bogus'],
            'mxs' => ['mx1.example.com' => 10, 'example.com' => 11],
        ]
    ]
]

Pass false as the third argument to validate() to exclude domain info from results.

Note: domains is a reserved key in the result map; an email string cannot use it.

Debug log

$validator->validate($emails, $from);

// Retrieve the log
$log = $validator->get_log();

// Clear it
$validator->clear_log();

Running Tests

The library supports PHP 8.1+, but the locked development dependencies (PHPUnit 12) require PHP 8.3+. CI runs the tests on PHP 8.4. Use that newer PHP CLI for both composer install and vendor/bin/phpunit. Enable the dom, mbstring, xml, and xmlwriter extensions, as in CI; Composer checks the complete extension requirements during installation.

Unit tests

No network required. Uses an in-memory SMTP conversation mock.

composer install
vendor/bin/phpunit

End-to-end tests

Runs against a local aiosmtpd server that accepts/rejects addresses deterministically. Requires Python 3 with aiosmtpd installed.

pip3 install aiosmtpd
vendor/bin/phpunit --group e2e

The test suite starts and stops the SMTP server automatically.

License

GPL-3.0-or-later. See LICENSE.txt.