Работает ли PHP filter_var FILTER_VALIDATE_EMAIL на самом деле?
После прочтения различных постов я решил не использовать REGEX для проверки правильности электронной почты и просто использовать встроенную функцию PHP filter_var. Казалось, что все работает нормально, пока не начал сообщать мне, что электронное письмо было недействительным, потому что в нем был номер.
то есть name@domain.com работает, а name2@domain.com - нет.
Я что-то упустил или это filter_var($email, FILTER_VALIDATE_EMAIL)
действительно довольно неэффективно?
4 ответа
Регулярное выражение, используемое в коде фильтра PHP 5.3.3, основано на блоге Майкла Раштона о проверке адреса электронной почты. Похоже, это работает для случая, который вы упоминаете.
Вы также можете проверить некоторые параметры в разделе Сравнение регулярных выражений адреса электронной почты (регулярное выражение, используемое в настоящее время в PHP, является одним из протестированных).
Тогда вы можете выбрать регулярное выражение, которое вам больше нравится, и использовать его в вызове preg_match()
,
Или же вы можете взять регулярное выражение и заменить его в файле PHP / ext / filter / logic_filter.c, функция php_filter_validate_email()
и перестройте PHP.
name2@domain.com, кажется, работает нормально: http://codepad.org/5HDgMW5i
Но я определенно видел людей, жалующихся, что у него есть проблемы, даже на SO. По всей вероятности, у него есть проблемы, но также и решение регулярных выражений. Спецификации адресов электронной почты очень, очень сложные ( RFC XXXX).
Вот почему единственное решение для проверки электронных писем, на которое вы должны полагаться, - это отправка электронного письма на адрес и требование действий (например: если это сценарий регистрации, попросите их нажать на ссылку для подтверждения).
function isValidEmail($email, $checkDNS = false)
{
$valid = (
/* Preference for native version of function */
function_exists('filter_var') and filter_var($email, FILTER_VALIDATE_EMAIL)
) || (
/* The maximum length of an e-mail address is 320 octets, per RFC 2821. */
strlen($email) <= 320
/*
* The regex below is based on a regex by Michael Rushton.
* However, it is not identical. I changed it to only consider routeable
* addresses as valid. Michael's regex considers a@b a valid address
* which conflicts with section 2.3.5 of RFC 5321 which states that:
*
* Only resolvable, fully-qualified domain names (FQDNs) are permitted
* when domain names are used in SMTP. In other words, names that can
* be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed
* in Section 5) are permitted, as are CNAME RRs whose targets can be
* resolved, in turn, to MX or address RRs. Local nicknames or
* unqualified names MUST NOT be used.
*
* This regex does not handle comments and folding whitespace. While
* this is technically valid in an email address, these parts aren't
* actually part of the address itself.
*/
and preg_match_all(
'/^(?!(?:(?:\\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',
$email)
);
if( $valid )
{
if( $checkDNS && ($domain = end(explode('@',$email, 2))) )
{
/*
Note:
Adding the dot enforces the root.
The dot is sometimes necessary if you are searching for a fully qualified domain
which has the same name as a host on your local domain.
Of course the dot does not alter results that were OK anyway.
*/
return checkdnsrr($domain . '.', 'MX');
}
return true;
}
return false;
}
//-----------------------------------------------------------------
var_dump(isValidEmail('nechtan@tagon8inc.com', true));
// bool(true)
Этот фильтр был недавно обновлен. http://codepad.org/Lz5m2S2N - кажется, что в версии, используемой кодовой панелью, ваш случай фильтруется правильно
Вы также можете посмотреть на http://bugs.php.net/49576 и http://svn.php.net/viewvc/php/php-src/trunk/ext/filter/logical_filters.c. Regexp довольно страшно.