Не дубликат : В этом ответе собраны известные решения для проверки адреса электронной почты.Он также содержит информацию об известных ограничениях при проверке международных писем.В конце я предоставляю возможное решение о том, как встретить международные письма.
filter_var
Автор этой публикации предложил следующую функциюподтвердите адрес электронной почты:
function isValidEmail($email){
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
Если вам требуется, чтобы TLD был частью адреса, автор также предложил:
function isValidEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL)
&& preg_match('/@.+\./', $email);
}
Проблема: нет поддержки международных адресов электронной почты
filter_var
не распространяется на международные адреса электронной почты, которые содержат символы UTF-8, такие как греческий или русский.
preg_match
Используйте пользовательское регулярное выражение для проверки структуры.Хороший пост с подробным описанием: здесь .
Автор предложил регулярное выражение из http://emailregex.com/,, которое позволяет проверять последние версии RDF 5322. Следующий код является нефиксированнымверсия:
$regex = '/^(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){255,})(?!(?:(?:\x22?\x5C[\x00-\x7E]\x22?)|(?:\x22?[^\x5C\x22]\x22?)){65,}@)(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22))(?:\.(?:(?:[\x21\x23-\x27\x2A\x2B\x2D\x2F-\x39\x3D\x3F\x5E-\x7E]+)|(?:\x22(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x23-\x5B\x5D-\x7F]|(?:\x5C[\x00-\x7F]))*\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-[a-z0-9]+)*)|(?:\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\]))$/iD';
if (1 == \preg_match($regex, $email)) {
// email OK
}
Он также упомянул:
[...] RFC 5322 приводит к регулярному выражению, которое можно понять, если изучить его в течение нескольких минут, и достаточно эффективно дляфактическое использование.[...]
Проблема: нет поддержки международных адресов электронной почты
Это решение также не распространяется на международные адреса, которые не совпадают.
Необязательно: поиск DNS
Поиск DNS не является проверкой , но может дополнить проверку.Он работает со всеми символами UTF-8, если они образуют действительное интернационализированное доменное имя (Ссылка: https://en.wikipedia.org/wiki/Internationalized_domain_name).
[...] - это доменное имя в Интернете, которое содержит хотя бы одну метку, которая являетсяотображаются в программных приложениях, [...] в текстовом алфавите или алфавите, например, на арабском, китайском, кириллице, тамильском, иврите или латинском алфавите с диакритическими знаками или лигатурами, например на французском.
С помощью checkdnsrr
вы проверяете, есть ли в указанном домене действительная запись DNS.
// $domain was extracted from the given email before
// $domain must end with a . (see comment below)
if (checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA')) {
// domain is VALID
}
Пользователь Мартин упомянул на php.net, что домен должен заканчиваться на .
добудет считаться действительным. Без точки вы получите ложные срабатывания.
Источник : http://php.net/manual/en/function.checkdnsrr.php#119969
Обработка международных писем
ВозможноРешение 1: структурная проверка + поиск DNS
Что я видел до сих пор, вам нужна комбинация структурных проверок + поиск DNS, чтобы получить лучшее покрытие. Первая часть следующего кода основана накласс EmailAddress
из Genkgo Mail ( source ).
function mail_is_valid(string $address): bool {
$hits = \preg_match('/^([^@]+)@([^@]+)$/', $address, $matches);
if ($hits === 0) {
// email NOT valid
return false;
}
[$address, $localPart, $domain] = $matches;
$variant = INTL_IDNA_VARIANT_2003;
if (\defined('INTL_IDNA_VARIANT_UTS46') ) {
$variant = INTL_IDNA_VARIANT_UTS46;
}
$domain = \rtrim(\idn_to_ascii($domain, IDNA_DEFAULT, $variant), '.') . '.';
if (!\checkdnsrr($domain, 'MX')) {
return \checkdnsrr($domain, 'A') || \checkdnsrr($domain, 'AAAA');
} else {
return true;
}
}
Я считаю это лучшим на данный момент решением, поскольку алгоритм в основном не зависит от символов, что допускает использование символов UTF-8 в электронном письме.Это верно, если у вас есть пользовательская часть + @
+ domain-part.Поиск DNS гарантирует, что домен существует.
Это не оптимально.Если вы знаете лучший способ, пожалуйста, оставьте его как комментарий или решение.