twixed.ru huh… nothing interesting here

14Ноя/1022

Проверка существования E-mail адреса на PHP

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

Реализовать эту мысль на PHP я и взялся одним субботним вечером. И вот, что из этого вышло...

Сразу скажу, что реализация эта - простейшая. И она в любом случае требует доработки под какие бы то ни было условия. Но представленное решение работоспособно, и выполняет поставленную задачу вполне успешно.

Мысль использовать какие-нибудь уже существующие средства для работы с SMTP была отметена сразу, в силу невозможности выполнить лишь минимальный набор команд, не отправляя письма, и неявности происходящего. Представленный же пример работает с сокетами, предельно прост и понятен, что делает его удобным для модернизации. Реализация его настолько же проста, насколько проста и сама идея: выяснить, каким сервером обслуживается интересующий адрес электропочты, подключиться к нему и, отправив три нехитрых команды, по ответам попытаться выяснить, существует указанный ящик или нет. Реализация нуждается в доработке, потому что разные почтовые серверы могут по-разному отвечать на запрос "RCPT TO:", но для простейшей проверки предложенного варианта должно быть вполне достаточно.

Код снабжен всеми необходимыми комментариями, и, в принципе, в больших пояснениях не нуждается:

<?php
// эта функция отправляет команду в сокет, и возвращает ответ от сервера
function sWrite( $socket, $data, $echo = true ){
   // отображаем отправляемую команду, если это требуется
   if( $echo ) echo $data;
   // отправляем команду в сокет 
  fputs( $socket, $data );
   // получаем первый байт ответа от сервера
   $answer = fread( $socket, 1 );
   // узнаем информацию о состоянии потока
   $remains = socket_get_status( $socket ); 
  // и получаем оставшиеся байты ответа от сервера 
  if( $remains --> 0 ) $answer .= fread( $socket, $remains['unread_bytes'] );
  // функция возвращает ответ от сервера на переданную команду
  return $answer;
}
 
// адрес электропочты, который надо проверить
$email = "a.twixed@gmail.com";
// получаем данные об MX-записи домена, указанного в email
$mx = dns_get_record( end( explode( "@", $email ) ), DNS_MX );
$mx = $mx[0]['target'];
// открываем сокет и создаем поток
$socket = fsockopen( $mx, 25, $errno, $errstr, 10 );
if( !$socket ){
  echo "$errstr ($errno)\n";
}else{
  // отправляем пустую строку, чтобы получить приветствие сервера
  echo sWrite( $socket, "" );
  // представляемся сами
  echo sWrite( $socket, "EHLO example.com\r\n" );
  echo sWrite( $socket, "MAIL FROM: dummy@example.com\r\n" );
  // запрашиваем разрешение на отправку письма адресату
  $response = sWrite( $socket, "RCPT TO: $email\r\n" );
  echo $response;
  // закрываем соединение
  echo sWrite( $socket, "QUIT\r\n" );
  fclose( $socket );
  // ниже идет простейшая обработка полученного ответа
  echo "\nCheck report:\n";
  if( substr_count( $response, "550" ) > 0 ) echo "Required email address does not exist.\n\n";
  else if( substr_count( $response, "250" ) > 0 ) if( substr_count( $response, "OK" ) > 0 ) echo "  Required email address exists.\n\n";
  else echo "  Email address accepted but it looks like the server is working as a relay host.\n\n";
  else echo "  Required email address existence was not recovered. Last response:\n  ---\n$response  ---\n\n";
}
 
?>

В скором времени этот код будет применен на одном из моих проектов, чтобы почистить базу от пользователей, чьи почтовые ящики были уничтожены за давностью лет, что делает невозможным получение этими пользователями инструкций по восстановлению пароля и писем рассылки.

Post to Twitter Post to Digg Post to Facebook Post to Google Buzz Send Gmail Post to LinkedIn

Комментарии (22) Пинги (0)
  1. А вот на сайте http://*****.ru/ есть такая услуга — проверка существование почтового ящика.
    Очень удобно, и сочинять ничего не надо.

    • на самом деле, таких сайтов много. перечислять их смысла нет, потому как все отлично гуглится.
      дело в том, что далеко не ко всем из них можно обратиться каким-нибудь AJAX-запросом или запросом через, допустим, cURL с последующим парсингом страницы, чтобы полученный результат использовать в своих программах… к тому же контролировать процесс проверки в таком случае Вы не сможете.
      приведенный пример же дает полный контроль над процессом проверки от начала и до конца, Вы сами можете добавить дополнительные проверки и возвращаемые результаты до открытия сокета и после отключения от удаленного сервера. так что, если Вы программист, то, имхо, предложенный вариант пусть и будет велосипедом, зато даст значительно больше возможностей, нежели сайты, подобные указанному Вами, даже если у них имеется какой-никакой API

  2. Автор хорошо придумал такой скрипт создать.Только как его юзать у меня выдает такое:

    220 mx.google.com ESMTP w16si303842eei.65
    EHLO example.com
    250-mx.google.com at your service, [195.250.70.152] 250-SIZE 35651584 250-8BITMIME 250-STARTTLS 250-ENHANCEDSTATUSCODES 250 PIPELINING
    MAIL FROM: dummy@example.com
    555 5.5.2 Syntax error. w16si303842eei.65
    RCPT TO: a.twixed@gmail.com 503 5.5.1 MAIL first. w16si303842eei.65
    QUIT 221 2.0.0 closing connection w16si303842eei.65
    Check report: Required email address existence was not recovered. Last response: — 503 5.5.1 MAIL first. w16si303842eei.65 —

    А здесь что как непонимаю.

    Надобы чтобы сказал есть или нету такого адреса.

    Помогите разобратся пожалуйста.

    • сервер же указывает на возникшую проблему:
      555 5.5.2 Syntax error.
      попробуйте заключить электроящик отправителя в запросе «MAIL FROM:» в треугольные скобки:
      MAIL FROM: <dummy@example.com>

  3. twix — я хотел вам задать вопрос. Я понимаю, что вы удалите этот комент. И ещё понимаю что тема очень актуальна и делает трафик вашему сайту.
    Вопросы:
    1. Как вы проверяли работоспособность скрипта?
    2. Зачем написаны программы для парсера страниц в серпе?
    3. Ну и философский вопрос. Если б в принципе существовал бы такой 100% рабочий скрипт, во сколько раз повысился бы уровень спама в Мире?

    Кстати этот сервис то же лажовый (http://*****.ru/mail-checker/) попробуйте проверить 100% работающие почтовые ящики.

    100% (да и то с условием) может дать лишь подтверждение пользователем из п.ящика отправленного ему какого-то кода.

    Таким образом можно лишь проверить существование почтового сервера в домене, НО НИ КАК НЕ ЯЩИКА в этом домене!

  4. Забыл ещё вопрос.
    Зачем нужно подтверждение email, при регистрации? Если всё так просто.

    • зачем же мне комменты удалять? я лучше постараюсь ответить сразу на два комментария…
      работоспособность скрипта проверена запуском его из консоли. особенно удобно, если дописать в его начале «#!/bin/php», выставить бит выполнения в атрибутах файла и подставлять в адрес почтового ящика первый параметр, переданный скрипту.
      если бы и существовал метод проверки существования почтового ящика, дающий 100%-й результат, то количество спама в мире бы не изменилось. потому что спамеры все-равно собирают адреса в свою базу по различным сайтам, форумам, социальным сетям, etc., а если пробовать подбирать имя почтового ящика брутфорсом (это вообще жесть) или по словарю, то проще сразу попытаться отправить письмо, чем перепроверять ответы сервера.
      а вообще, скрипт писался не для того, чтобы проверить существование какого-то еще непроверенного ящика электропочты, а для того, чтобы проредить базу данных пользователей. а то при массовых рассылках с сайта мне, как постмастеру, на почту наваливается несколько сотен писем от почтовых серверов с сообщением об отсутствии на них запрошенного ящика. т.е. пользователь, который когда-то зарегистрировался на сайте, и подтвердил существование почтового ящика, перестал им пользоваться, и он был по какой-то причине удален с почтового сервера. и я еще раз скажу, что скрипт старается проверить существование именно почтового ящика на сервере, ведь, по RFC, тот должен честно отвечать клиенту командами из того же документа.

  5. У меня ругается на эту функцию dns_get_record

    • какая версия PHP используется?
      dns_get_record появилась только в 5-й версии PHP, а под Windows только с верии 5.3.0

  6. У меня возникает ошибка:
    Warning: fsockopen() [function.fsockopen]: unable to connect to mx.yandex.ru:25 (No route to host)…

    Для всех почтовых серверов.

    • если для всех опробованных ящиков выпадает ругань на один только mx.yandex.ru, то проблема в скрипте есть — почтовый сервер яндекс где-то задан жестко.
      однако, указанная ошибка возникает на сетевом уровне. попробуйте в консоли выполнить ‘telnet mx.yandex.ru 25’ — может подключиться? а пинги на него проходят? может, на вашем шлюзе запрещено все, кроме http/https трафика? а DNS нормально работает?

      • Адрес «mx.yandex.ru» приведен для примера.
        Скрипт был опробован на двух хостингах: «one.com» и «reg.ru»
        В первом случае выдается сообщение о таймауте, во втором — «варнинги» о невозможности подключиться.
        Подозреваю, что оба хостера просто прикрыли 25-й порт в пылу борьбы со спамом.

        Аналогично ведет себя скрипт http://htmlweb.ru/php/example/is_e-mail.php
        т.е. на на своем хостинге он работает, но будучи запущенном на вышеупомянутых хостингах — нет.

        Может подкинете идейку на вскидку, где собака зарыта?

        • скрипт перепроверил, отрабатывает нормально.
          вероятно, проблема все-таки в вашем шлюзе. есть подозрение, что он не пропускает трафик, отличный от http/https/ftp(?). или, возможно, у вас стоит какой-нибудь Outpost Firewall, который молча блокирует некоторый трафик.
          ситуация со скриптом, подсмотренным по приведенной вами ссылке, это подтверждает. проверьте настройки своего firewall, если оный установлен, и пытайте админа паяльником, пока он не разрешит использовать SMTP-порт.

  7. Тут можите посмотреть прикреплённый файл. Там php скрипт проверки адреса электронной почты в 3 этапа:
    http://www.easy2code.com/ru/notes/view/proverka_e-mail_adresa_na_suschestvovanie/

  8. Жесть! В примере скрипт показывает что ящик существует … раз так то попробуйте его зарегать и увидите что такого мыла нет в природе!
    220 Mail.Ru ESMTP EHLO example.com 250-mx82.mail.ru ready to serve 250-SIZE 31457280 250 8BITMIME MAIL FROM: dummy@example.com 250 OK RCPT TO: anton77777Rfcrdvdrervter@mail.ru 250 OK QUIT 221 mx82.mail.ru closing connection Check report: Required email address exists.

  9. Совет автору, не в тему но очень полезный! С точки зрения СЕО ссыли типа http://*****.ru/mail-checker/ отватительны так как они есть, индексируются, но никуда не ведут, а только отнимают вес страницы! Статья оказалась полезной, потому и хочу вам дать совет: устанавливайте лучше теги dofollow или noindex, или вообще удаляйте теги с сылкой. Програмно это делается 10мин. этот коментарий адресуется лично вам, так что удалите после прочтения!

  10. На мой взгляд, лучшая и 100% проверка — это обработка ответных писем после рассылки. Как правило, если ящика не существует, то на почту с которой происходила рассылка приходит соответствующее письмо, поэтому автоматически отбираем такие письма по заголовку и содержанию, вытаскиваем нерабочий адрес и удаляем его из базы. Конечно, такой способ будет работать у имеющих собственный почтовый сервер или не брезгующий проверять ящик вручную после рассылок.

    • Более того, на отработку данного метода потребуется больше времени, и, в случае завязки фронтенда на этот скрипт, пользователь будет дольше наблюдать картинку-лоадер.

  11. Для полной проверки существования адреса необходимо отправить на него письмо со случайным кодом и попросить получателя письма ввести этот код а форме, на вашем сайте. CodeNet.

    • Всё правильно. Регистрацию, например, так и следует делать: с подтверждением через письмо.
      Такой же способ подойдёт и для уже зарегистрированных пользователей. Можно попросить их кликнуть по ссылке в письме с просьбой, например, подтвердить свою учётную запись в связи с изменившимися политиками сайта. Однако, этот метод может отсеять и «живых» пользователей: кто-то проигнорирует письмо, кто-то его сразу удалит, не читая, а к кому-то оно попадёт в спам. Многие из таких сайту будут не нужны, и их можно будет смело удалять, но среди них могут оказаться и лояльные пользователи, учётная запись которых окажется удалённой из-за их невнимательности или лени. Быть может всякое.
      Я же привёл скрипт, который отрабатывает без участия пользователя, и отсеивает заведомо несуществующие (или маскирующиеся) ящики.
      Статья же не описывает единственный метод, а предоставляет один из возможных.


Leave a comment

Нет обратных ссылок на эту запись.