Проверка правильности адресов электронной почты

Задача
Необходимо проверить, является ли адрес электронной почты правильным.

Решение
Это очень популярный вопрос, и каждый отвечает на него по-своему, в зависимости от собственного определения правильности. Если правильным считать имя почтового ящика, принадлежащего законному пользователю узла с реально существующим именем, то, честно говоря, вы не сможете ответить на этот вопрос корректно, можете даже не
беспокоиться. Однако иногда регулярные выражения помогают избавиться от некоторых простых и очевидных попыток мошенничества.

Приведем наш любимый шаблон, упомянутый выше и не требующий подробных пояснений:

/^[^@\s]+@([-a-z0-9]+\.)+[a-z]{2,}$/i

Если доступно расширение IMAP, можно также использовать функцию Imap_rfc822_parse_adrlist():

$parsed = imap_rfc822_parse_adrlist($email_address, $default_host)
if ('INVALID_ADDRESS' == $parsed['mailbox']) {
// неправильный адрес
}

Ирония заключается в том, что эта функция так уступчива к RFC, что может выдать совсем не тот результат, который вы от нее ожидаете.

Обсуждение
Шаблон в данном разделе «Решение» принимает любой адрес электронной почты, в котором имя ящика представлено произвольной последовательностью символов, отличных от @ и пробельных символов.

После символа @ должно следовать по крайней мере одно имя домена, состоящее из букв a–z, цифр 0–9 и дефиса, и любое количество имен поддоменов, разделенных точками.


Наконец, все должно завершаться двухбуквенным кодом страны или иным доменом верхнего уровня, например .com или .edu.Шаблон, приведенный в разделе «Решение», удобен, поскольку он будет работать, даже если ICANN создаст новые домены верхнего уровня.

Тем не менее он способен пропустить некоторые ошибочные имена. Следующий, более строгий шаблон явным образом перечисляет домены верхнего уровня, не относящиеся в настоящее время к доменам стран:

/
^ # начальная привязка
[^@\s]+ # именем являются все символы, за исключением @
и пробельных символов
@ # символ @ отделяет имя от домена
(
[-a-z0-9]+ # поддомены – это буквы, цифры и дефис,
\. # разделенные точкой,
)+ # и мы можем указать один или больше
(
[a-z]{2} # домены верхнего уровня
# могут быть двухбуквенным кодом страны
|com|net # или одной
|edu|org # из многих
|gov|mil # возможных
|int|biz # трехбуквенных
|pro # комбинаций
|info|arpa # или даже
|aero|coop # нескольких
|name # четырехбуквенных комбинаций
|museum # плюс одна комбинация длиной в шесть букв!
)
$ # привязка в конце
/ix # и все это безотносительно к регистру

Оба шаблона умышленно либеральны к принимаемой ими информации, поскольку мы предполагаем, что вам нужно лишь, чтобы кто-нибудь случайно не потерял домен верхнего уровня или не впечатал какую-нибудь импровизацию, вроде «не указывается».


Например, домен "-.com" не существует, но адрес "foo@-.com" пройдет без звука. (Нетрудно было бы модифицировать шаблон, чтобы исправить эту ситуацию, но мы оставим это читателям в качестве упражнения.) С другой стороны, допустимым является адрес "Tim O'Reilly@oreilly.com", но наш шаблон его не пропустит. Однако пробелы в адресах электронной почты встречаются не часто, а т. к. пробел почти всегда является ошибкой, мы отмечаем этот адрес как ошибочный.

Каноническое определение формально корректного адреса описано в RFC 822, однако написание программы для обработки всех возможных случаев – задача не из приятных. Вот лишь один пример: придется принять во внимание, что пользователям разрешается вставлять в адреса комментарии! Комментарии заключаются в круглые скобки,
поэтому допустимо написать:

Tim (is the man @ computer books) @ oreilly.comЭто эквивалентно адресу "tim@oreilly.com". (Увы, наш шаблон опять
забракует этот адрес.)

Есть и альтернатива – расширение IMAP включает в себя удовлетворяющий RFC 822 анализатор адреса. Этот анализатор успешно справляется с пробельными символами и другими причудами, но допускает очевидные ошибки, поскольку предполагает, что адреса без указания имени хоста являются локальными:

$email = 'stephen(his account)@ example(his host)';
$parsed = imap_rfc822_parse_adrlist($email,'');
print_r($parsed);
Array
(
[0] => stdClass Object
(
[mailbox] => stephen
[host] => example
[personal] => his host
)
)

Собрав снова почтовый адрес и хост, вы получите "stephen@example", что, возможно, представляет собой не то, что ожидалось.


Пустая строка, которую необходимо передать в качестве второго аргумента, лишает вас возможности проверять действительность имен хостов.

Некоторые стараются осуществить дополнительную фоновую проверку, посылая DNS-серверу запрос, зарегистрирован ли данный адрес.

Большого смысла в этом нет, т. к. технически это не всегда выполнимо, и вы можете не допустить на свой сайт ни в чем не повинных и совершенно законных пользователей, действуя таким образом. (Кроме того, маловероятно, чтобы почтовый администратор выстроил собственную систему обработки почты с целью обойти схему проверки достоверности почты лишь одного сайта.)

Проверяя достоверность адресов электронной почты, надо принимать во внимание, что для пользователя не составляет большого труда ввести абсолютно законный и работающий адрес, принадлежащий комуто другому. Например, один из авторов имел нехорошую привычку вводить "billg@microsoft.com", заходя на веб-сайты Microsoft (а вдруг
Билл Гейтс не знает об этой новой версии Internet Explorer?).

Если больше всего вы беспокоитесь из-за возможных опечаток, заставьте пользователей вводить адрес дважды и сравнивайте результаты ввода.


Если они совпадают, то, возможно, являются верными. Кроме того, отсекайте часто используемые фиктивные адреса, такие как "president@ whitehouse.gov" и упомянутый выше адрес "billg@microsoft.com". (Не стоит волноваться о том, что президент Соединенных Штатов или
Билл Гейтс не получат писем, зарегистрировавшись на вашем сайте.) Однако если вы хотите проверить, действительно ли пользователи имеют доступ к почтовому ящику, адрес которого они указали, то одним из способов убедиться в этом является отправка на их адрес сообщения с просьбой прислать ответ или посетить страницу вашего сайта
и ввести специальный код, напечатанный в теле сообщения, для подтверждения регистрации. Если вы предпочтете вариант со специальным кодом, то рекомендуем не генерировать абсолютно случайную строку символов, похожую на HSD5nbADl8. Это напоминает мусор, и правильно повторить его ввод довольно трудно. Вместо этого используйте список слов; создавайте кодовые слова, такие как television4coatrack.
Несмотря на то что иногда вполне удается воссоздать наборы, используемые при составлении этих комбинаций, вы сможете резко сократить количество ошибок при вводе и собственные затраты на поддержку пользователей..



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Выбор между поглощающим и непоглощающим сравнением
Нахождение n-го совпадения
Переход от ereg к preg
Поиск в файле всех строк, соответствующих шаблону
Поиск слов

Вернуться в раздел: PHP / 13. Регулярные выражения