Как проверить адрес электронной почты в PHP
У меня есть эта функция для проверки адресов электронной почты:
function validateEMAIL($EMAIL) {
$v = "/[a-zA-Z0-9_-.+][email protected][a-zA-Z0-9-]+.[a-zA-Z]+/";
return (bool)preg_match($v, $EMAIL);
}
Это нормально для проверки правильности адреса электронной почты?
Ответы
Ответ 1
Самый простой и безопасный способ проверить, правильно ли сформирован адрес электронной почты, - использовать filter_var()
:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// invalid emailaddress
}
Кроме того, вы можете проверить, определяет ли домен запись MX
:
if (!checkdnsrr($domain, 'MX')) {
// domain is not valid
}
Но это все еще не гарантирует, что почта существует. Единственный способ узнать это - отправить письмо с подтверждением.
Теперь, когда у вас есть свой простой ответ, вы можете свободно читать о проверке адреса электронной почты, если хотите научиться или иным образом просто использовать быстрый ответ и двигаться дальше. Никаких жестких чувств.
Попытка проверить адрес электронной почты с помощью регулярного выражения является "невозможной" задачей. Я хотел бы сказать, что это регулярное выражение, которое вы сделали, бесполезно. Существует три rfc относительно адресов электронной почты и написания регулярных выражений, чтобы поймать неправильные адреса электронной почты и в то же время не имеют ложных срабатываний - это то, что не может сделать смертный. Проверьте этот список для тестов (как неудачных, так и filter_var()
регулярного выражения, используемого filter_var()
PHP filter_var()
.
Даже встроенные функции PHP, почтовые клиенты или серверы не понимают это правильно. В большинстве случаев filter_var
- лучший вариант.
Если вы хотите узнать, какой шаблон регулярного выражения PHP (в настоящее время) используется для проверки адресов электронной почты, обратитесь к источнику PHP.
Если вы хотите узнать больше о адресах электронной почты, я предлагаю вам начать читать спецификации, но я должен предупредить вас, что это нелегко прочитать на любом участке:
Обратите внимание: filter_var()
уже указан только в PHP 5.2. Если вы хотите, чтобы он работал с более ранними версиями PHP, вы могли бы использовать регулярное выражение, используемое в PHP:
<?php
$pattern = '/^(?!(?:(?:\\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';
$emailaddress = '[email protected]';
if (preg_match($pattern, $emailaddress) === 1) {
// emailaddress is valid
}
PS Замечание о шаблоне регулярного выражения, используемом выше (из источника PHP). Похоже, есть некоторые авторские права на него Майкла Раштона. Как указано: "Не стесняйтесь использовать и распространять этот код, но, пожалуйста, сохраните это уведомление об авторских правах".
Ответ 2
Вы можете использовать filter_var для этого.
<?php
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
?>
Ответ 3
По моему опыту, в решениях regex
слишком много ложных срабатываний, а в filter_var()
есть ложные негативы (особенно со всеми новыми TLD).
Вместо этого лучше убедиться, что адрес имеет все необходимые части адреса электронной почты (пользователь, символ "@" и домен), а затем убедитесь, что сам домен существует.
Невозможно определить (серверную сторону), если пользователь электронной почты существует для внешнего домена.
Это метод, который я создал в классе Utility:
public static function validateEmail($email)
{
// SET INITIAL RETURN VARIABLES
$emailIsValid = FALSE;
// MAKE SURE AN EMPTY STRING WASN'T PASSED
if (!empty($email))
{
// GET EMAIL PARTS
$domain = ltrim(stristr($email, '@'), '@') . '.';
$user = stristr($email, '@', TRUE);
// VALIDATE EMAIL ADDRESS
if
(
!empty($user) &&
!empty($domain) &&
checkdnsrr($domain)
)
{$emailIsValid = TRUE;}
}
// RETURN RESULT
return $emailIsValid;
}
Ответ 4
Я думаю, вам может быть лучше использовать PHP inbuilt filters - в данном конкретном случае:
Он может возвращать true или false, если поставляется с параметром FILTER_VALIDATE_EMAIL
.
Ответ 5
Это не только подтвердит вашу электронную почту, но и дезинформирует ее для неожиданных символов:
$email = $_POST['email'];
$emailB = filter_var($email, FILTER_SANITIZE_EMAIL);
if (filter_var($emailB, FILTER_VALIDATE_EMAIL) === false ||
$emailB != $email
) {
echo "This email adress isn't valid!";
exit(0);
}
Ответ 6
Ответил это в "верхнем вопросе" о проверке электронной почты fooobar.com/questions/245/...
Для меня правильный способ проверки электронной почты:
- Убедитесь, что символ @существует, и до и после него есть некоторые символы @@:
/^[^@][email protected][^@]+$/
- Попробуйте отправить электронное письмо на этот адрес с некоторым "кодом активации".
- Когда пользователь "активирует" свой адрес электронной почты, мы увидим, что все правильно.
Конечно, вы можете показать предупреждение или всплывающую подсказку в интерфейсе, когда пользователь набрал "странную" электронную почту, чтобы помочь ему избежать распространенных ошибок, например, нет точка в доменной части или пробелы в названии без цитирования и т.д. Но вы должны принять адрес "hello @world", если пользователь действительно этого хочет.
Кроме того, вы должны помнить, что стандарт адреса электронной почты был и может evolute, поэтому вы не можете просто называть некоторое "стандартное допустимое" регулярное выражение один раз и на все времена. И вы должны помнить, что какой-то конкретный интернет серверы могут выдать некоторые детали общего стандарта и фактически работать с собственный "модифицированный стандарт".
Итак, просто отметьте @, подскажите пользователю об интерфейсе и отправьте письма с подтверждением по указанному адресу.
Ответ 7
Если вы просто ищете фактическое регулярное выражение, которое допускает различные точки, подчеркивания и тире, это выглядит следующим образом: [a-zA-z0-9.-]+\@[a-zA-z0-9.-]+.[a-zA-Z]+
. Это позволит проверять довольно глупый вид электронной почты, например [email protected]_matrix.com
.
Ответ 8
/(?![[:alnum:]]|@|-|_|\.)./
В настоящее время, если вы используете форму HTML5 с type=email
, вы уже на 80% безопасны, так как у браузеров есть свой валидатор. Чтобы дополнить его, добавьте это регулярное выражение к вашему preg_match_all()
и отрицайте его:
if (!preg_match_all("/(?![[:alnum:]]|@|-|_|\.)./",$email)) { .. }
Найти регулярное выражение, используемое форматами HTML5 для проверки
https://regex101.com/r/mPEKmy/1
Ответ 9
При запуске некоторых тестов этим утром я обнаружил, что FILTER_VALIDATE_EMAIL будет проверять [email protected] как действительный адрес электронной почты.
$counter = 0;
foreach($emails as $email){
$email = trim($email);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
unset($emails[$counter]);
}
$counter++;
}
У кого-нибудь есть рекомендация по устранению этого?
Ответ 10
Если вы хотите проверить, действительно ли предоставленный домен с адреса электронной почты действителен, используйте что-то вроде:
/*
* Check for valid MX record for given email domain
*/
if(!function_exists('check_email_domain')){
function check_email_domain($email) {
//Get host name from email and check if it is valid
$email_host = explode("@", $email);
//Add a dot to the end of the host name to make a fully qualified domain name and get last array element because an escaped @ is allowed in the local part (RFC 5322)
$host = end($email_host) . ".";
//Convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
return checkdnsrr(idn_to_ascii($host), "MX"); //(bool)
}
}
Это удобный способ фильтрации большого количества недействительных адресов электронной почты, а также стандартная проверка электронной почты, поскольку действующий формат электронной почты не означает действительный адрес электронной почты.
Обратите внимание: idn_to_ascii()
(или его дочерняя функция idn_to_utf8()
) может быть недоступна в вашей установке PHP, она требует расширений PECL intl> = 1.0.2 и PECL idn> = 0,1.
Также имейте в виду, что IPv4 или IPv6 как часть домена в электронной почте (например, [email protected][IPv6:2001:db8::1]
) не могут быть проверены, но только именами хостов.
Подробнее см. Здесь.
Ответ 11
Прочитав ответы здесь, я получил следующее:
public static function isValidEmail(string $email) : bool
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return false;
}
//Get host name from email and check if it is valid
$email_host = array_slice(explode("@", $email), -1)[0];
// Check if valid IP (v4 or v6). If it is we can't do a DNS lookup
if (!filter_var($email_host,FILTER_VALIDATE_IP, [
'flags' => FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
])) {
//Add a dot to the end of the host name to make a fully qualified domain name
// and get last array element because an escaped @ is allowed in the local part (RFC 5322)
// Then convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
$email_host = idn_to_ascii($email_host.'.');
//Check for MX pointers in DNS (if there are no MX pointers the domain cannot receive emails)
if (!checkdnsrr($email_host, "MX")) {
return false;
}
}
return true;
}
Ответ 12
Кроме того, вы могли бы полагаться на сторонний API, такой как https://email-validation-api.com, для того, чтобы иметь корректор орфографических ошибок и несколько контрольных точек и индикаторов на релевантность соответствующего адреса электронной почты.
Ответ 13
Лучшее решение использует filter_var:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->addError($attribute, 'you inputted wrong email'); // Or another handler
}