Насколько легко проверить, что адрес электронной почты действителен в PHP?

Учитывая адрес электронной почты, как я могу проверить, что он действителен? (Что домен электронной почты будет принимать электронную почту для этого адреса.)

Как это будет выглядеть в PHP?

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

Я бы подумал, что есть какой-то способ сделать это с записью MX или чем-то еще...


person Nathan Osman    schedule 15.05.2010    source источник
comment
Записи MX указывают местоположение почтового сервера... не каждого пользователя/адреса.   -  person Tyler Carter    schedule 15.05.2010
comment
Хорошо. Я действительно мало что знаю об этом... отсюда и мой вопрос.   -  person Nathan Osman    schedule 15.05.2010


Ответы (7)


Я думаю, что вашими единственными вариантами будут команды SMTP RCPT TO или VRFY.

RCPT TO может быть способом проверки, если вы отключитесь после его выдачи. Однако не все серверы загрузят вас, если учетная запись не существует (предотвращение uce, все адреса и т. д.).

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

Класс PHP, который выполняет проверку RCPT TO (среди других методов): http://code.google.com/p/php-smtp-email-validation/

person morbidcoder    schedule 15.05.2010
comment
Спасибо! Это больше то, что я ищу. - person Nathan Osman; 15.05.2010

Поскольку вы конкретно указываете

Что домен электронной почты будет принимать электронную почту для этого адреса.

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

Отправить такое простое электронное письмо с помощью PHP достаточно просто; ознакомьтесь с документацией по функции mail() здесь.

person Syntactic    schedule 15.05.2010
comment
Ну, мне действительно не нужны регулярные выражения. (Я нигде об этом не упоминал.) Итак, вы хотите проверить возвращаемое значение mail(), чтобы убедиться, что сообщение было успешно принято для доставки? - person Nathan Osman; 15.05.2010
comment
Я знаю, как отправлять электронную почту с помощью mail(). Я хочу знать, как подтвердить адрес. - person Nathan Osman; 15.05.2010
comment
Да, мой комментарий о регулярных выражениях был скорее реакцией на другой ответ, чем на ваш вопрос. Возвращаемое значение mail() сообщит вам, была ли доставка успешной в данный момент, хотя на практике это может быть не очень хорошим показателем того, действительно ли существует адрес электронной почты. К сожалению, природа работы электронной почты делает эту задачу сложной. - person Syntactic; 15.05.2010
comment
Я знаю. Я предполагаю, что возвращаемое значение достаточно хорошо на данный момент. Вероятно, единственным другим вариантом является маяк или что-то в этом роде. - person Nathan Osman; 15.05.2010

На самом деле вы не можете проверить, примет ли сервер это. У почтового сервера нет API для этого.

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

Единственное, что вы можете сделать, это проверить действующий адрес электронной почты и надеяться на лучшее:

http://www.linuxjournal.com/article/9585

Это одно из руководств, которые действительно следуют стандартам RFC.

/**
Validate an email address.
Provide email address (raw input)
Returns true if the email address has the email 
address format and the domain exists.
*/
function validEmail($email)
{
   $isValid = true;
   $atIndex = strrpos($email, "@");
   if (is_bool($atIndex) && !$atIndex)
   {
      $isValid = false;
   }
   else
   {
      $domain = substr($email, $atIndex+1);
      $local = substr($email, 0, $atIndex);
      $localLen = strlen($local);
      $domainLen = strlen($domain);
      if ($localLen < 1 || $localLen > 64)
      {
         // local part length exceeded
         $isValid = false;
      }
      else if ($domainLen < 1 || $domainLen > 255)
      {
         // domain part length exceeded
         $isValid = false;
      }
      else if ($local[0] == '.' || $local[$localLen-1] == '.')
      {
         // local part starts or ends with '.'
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $local))
      {
         // local part has two consecutive dots
         $isValid = false;
      }
      else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
      {
         // character not valid in domain part
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $domain))
      {
         // domain part has two consecutive dots
         $isValid = false;
      }
      else if
(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
                 str_replace("\\\\","",$local)))
      {
         // character not valid in local part unless 
         // local part is quoted
         if (!preg_match('/^"(\\\\"|[^"])+"$/',
             str_replace("\\\\","",$local)))
         {
            $isValid = false;
         }
      }
      if ($isValid && !(checkdnsrr($domain,"MX") || 
 ↪checkdnsrr($domain,"A")))
      {
         // domain not found in DNS
         $isValid = false;
      }
   }
   return $isValid;
}

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

person Tyler Carter    schedule 15.05.2010
comment
Нет нет. Я не хочу подтверждать адрес электронной почты, я хочу его подтвердить. (Убедитесь, что домен будет принимать электронные письма, отправленные на него.) - person Nathan Osman; 15.05.2010
comment
Я не уверен, что это спросил ОП. У меня сложилось впечатление, что вопрос в том, чтобы проверить, будет ли сервер принимать почту с указанным адресом. Хотя и требует пояснений. - person Jakub Hampl; 15.05.2010
comment
Я переформулировал вопрос. - person Nathan Osman; 15.05.2010
comment
@ Джордж, и мой ответ все еще в силе :) - person Tyler Carter; 15.05.2010
comment
Конечно, я всегда могу проверить, прошла ли доставка успешно. (Как будто сервер принял сообщение.) - person Nathan Osman; 15.05.2010

Насколько легко проверить, что адрес электронной почты действителен?

Совсем непросто. Взгляните на подтверждение электронной почты Доминика Сэйерса. в PHP, возможно, самая полная библиотека проверки электронной почты на любом языке. Он также включает проверку DNS.

См. также эта связанная статья от Джеффа Этвуда о проверках, необходимых для гарантии доставки электронной почты.

person Mauricio Scheffer    schedule 15.05.2010
comment
Можете ли вы указать мне соответствующую часть, которая выполняет проверку DNS? Я не мог найти его. - person Nathan Osman; 15.05.2010
comment
@George Edison: найдите «checkDNS» на странице, он спрятан в комментариях. - person Mauricio Scheffer; 15.05.2010

Электронная почта (синтаксически) действительна, это не то же самое, что она принимает электронные письма. Чтобы проверить, будет ли домен принимать электронную почту, вам нужно попробовать отправить электронное письмо непосредственно на MX, но даже в этом случае, если оно будет принято SMTP-сервером, вы не гарантируете, что оно не будет впоследствии отклонено. т.е. будет отправлен отчет о недоставке. И SMTP-сервер, вероятно, отклонит вашу электронную почту, если вы находитесь в динамическом пуле адресов или не имеете обратного DNS.

person Artefacto    schedule 15.05.2010

Просто решил упомянуть, что PHP имеет встроенную функцию getmxrr() который извлекает запись MX из домена.

Чем это полезно, не знаю... На странице написано:

Эту функцию не следует использовать для проверки адреса.

Таким образом, его использование ограничено проверкой наличия почтового сервера в домене.

person Nathan Osman    schedule 15.05.2010

Если вы используете PHP 5.2.x, теперь нет необходимости использовать пользовательские функции проверки. В PHP есть встроенная функция.

person Gabriel Sosa    schedule 15.05.2010
comment
Пожалуйста, прочитайте вопрос - это не то, что я ищу. - person Nathan Osman; 15.05.2010