Email addresses and suggestions
Beyond composing and sending, the package gives you two tools for working with the addresses themselves: Email parses and validates an address, and EmailSuggester spots likely typos and proposes corrections.
The Email value object
Email is an immutable value object split into three parts: a username, a domain and an optional plus tag. You can build one directly from its parts, but most of the time you parse a raw string with Email::fromString.
<?php
declare(strict_types=1);
use Raxos\Mail\Email;
$email = Email::fromString('jane+newsletter@example.com');
$email->username; // 'jane'
$email->domain; // 'example.com'
$email->tag; // 'newsletter'fromString validates the input with FILTER_VALIDATE_EMAIL and requires exactly one @. When the local part contains a +, everything after it becomes the tag. Anything that is not a single valid address throws an InvalidEmailAddressException, which implements EmailAddressExceptionInterface from raxos/contract.
use Raxos\Contract\Mail\EmailAddressExceptionInterface;
try {
$email = Email::fromString('not-an-address');
} catch (EmailAddressExceptionInterface $err) {
// handle the invalid input
}Email implements both Stringable and JsonSerializable. It renders back to username@domain, or username+tag@domain when a tag is present, in both string and JSON contexts.
echo (string)Email::fromString('jane+news@example.com');
// jane+news@example.com
echo json_encode(['email' => Email::fromString('jane@example.com')]);
// {"email":"jane@example.com"}Suggesting corrections
EmailSuggester::for looks at an address and returns a list of likely intended addresses, or null when nothing looks wrong. It accepts either an Email instance or a raw string (which it parses for you, so it can also throw EmailAddressExceptionInterface).
<?php
declare(strict_types=1);
use Raxos\Mail\EmailSuggester;
$suggestions = EmailSuggester::for('jane@gmial.com');
// [Email('jane', 'gmail.com')]
$none = EmailSuggester::for('jane@gmail.com');
// nullThe suggester works on two levels. It compares the provider part of the domain against a fixed list of common providers (gmail, hotmail, outlook, live, icloud and me) using Levenshtein distance, so a one character slip like gmial is caught. It also validates the domain suffix against the public suffix list, and when the suffix itself is unrecognized it proposes corrected suffixes. Each entry in the returned array is a fresh Email that keeps the original username and tag.
Because the result is either an array of Email objects or null, a common pattern is to offer the first suggestion back to the user before sending.
$suggestions = EmailSuggester::for($input);
if ($suggestions !== null) {
$didYouMean = (string)$suggestions[0];
// prompt the user with $didYouMean
}