Не редко при разработке различных web-приложений разработчикам приходится реализовывать функции по проверке правильности введённого пользователем адреса электронной почты. Как правило, такие проверки ограничиваются простой проверкой на соответствие регулярным выражениям, а то и просто на наличие в строке символа ‘@’. Я же предлагаю использовать более объективный вариант.
- Проверка на правильность написания адреса
- Проверка домена на наличие MX-записей
- Общение с почтовым сервером, проверка существования почтового ящика
Проверка на правильность написания адреса
Итак, для начала нам необходимо проверить, представляет ли собой строка правильно сформированный адрес электронной почты. Для подобной проверки уже существует множество вариантов регулярных выражений, некоторые из них довольно длинные, я же пользуюсь следующим кодом для проверки:
$name = '[^@\s]+';
$sub_domain = '[-a-z0-9]+\.';
// country codes
$cc = '[a-z]{2}';
// top level domains
$tlds = "$cc|com|net|edu|org|gov|mil|int|biz|pro|info|arpa|aero|coop|name|museum";
$email_pattern = "/^$name@($sub_domain)+($tlds)$/ix";
preg_match($email_pattern, $email);
Проверка домена на наличие MX-записей
Следующим шагом мы пытаемся проверить, есть ли у домена MX-записи, в этих записях содержатся назания серверов, отвечающих за обмен почтой:
if(checkdnsrr($host, "MX")) {
if (!getmxrr($host, $mxhost, $mxweight)) {
echo "Can't found mail servers records!";
}
}
Общение с почтовым сервером, проверка существования почтового ящика
После того, как записи найдены, мы обращаемся к почтовым серверам с запросом, существует ли на них, интересующий нас почтовый ящик:
$fp = fsockopen($host, 25);
fputs($fp, "HELO {$_SERVER['SERVER_NAME']}\r\n");
fgets($fp, 1024);
fputs($fp, "MAIL FROM: <httpd@{$_SERVER['SERVER_NAME']}>\r\n");
fgets($fp, 1024);
fputs($fp, "RCPT TO: <$email>\r\n");
$line = fgets($fp, 1024);
fputs($fp, "QUIT\r\n");
fclose($fp);
Анализируя ответ от сервера мы можем узнать, существует ящик, или нет:
if (substr($line, 0, 3) != "250") {
// не существует
} else {
// существует
}
А если на сервере включена SMTP аутентификация - ответ будет таким же?
Ну и в догонку - если включен SMTP через ssl или STARTTLS.
У меня такое чувство, что если бы предложенный тобой способ работал - можно было бы брутфорсом вытягивать списки пользователей всех SMTP серверов. Kind of spammer’s heaven
Kooper, приведённый мной способ точно работает с наиболее распространённми почтовыми провайдерами — GMail, Hotmail, AOL, Mail.ru; а вот с Yahoo не работает, точнее работает некорректно — любой адрес выдаёт как существующий.
Что же касается SMTP-аутентификации и SSL, если у тебя есть возможность это проверить и выдать своё авторитетное заключение, буду рад опубликовать твои результаты.
А с какой целью так проверять адрес на существование?
Т.е. раз нет 100%-ой уверенности в точности проверки? И кроме того, мы не может точно определить принадлежит ли данный адрес человеку, который его назвал.
Я проверяю адрес только на правильность его написания (чтобы сразу отбросить всякую ерунду), а затем отправляю пароль/код подтверждения на почту.
Виктор, история, что называется, основана на реальных событиях. Во время работы над одним проектом заказчик попросил изменить стандартную функциональность CMS в части реализации регистрации пользователей. Конечно, я с тобой полностью согласен, достаточно проверить правильность написания адреса, а дальше высылать письмо с кодом подтверждения, но вот заказчик посчитал иначе. У меня, по правде, есть одна идея почему он на этом настоял. Дело в том, что сайт над которым я работал представляет собой электронный “глянцевый” журнал для девочек и, видимо, этим самым девочкам было сложно понять для чего нужно переходить по ссылке с подтверждением…
Теперь понятно
Да, и ещё. Подумал, что наверное даже лучше после регистрации высылать не код подтверждения, а просто пароль для входа (автоматически генерируемый, само собой) :).
P.S. Какой приятный движок сайта, “С возвращением, Виктор” написал :).
Не согласен насчёт идеи высылать пароль. Не совсем правильно с точки зрения безопасности. Элементарно кто-нибудь может этот пароль подглядеть из-за плеча (в офисе или в интернет-клубе). Восстановление забытого пароля в ЖЖ (если я ичего не путаю) никогда не высылает новый пароль в открытом виде, а отправляет тебя на страницу, где ты вбиваешь новый пароль.
То есть Вы против того, чтобы пароль был представлен в открытом виде хоть где-то?
Ну да, наверное Вы правы. Здесь есть над чем подумать.