Как стать автором
Обновить

Верификация e-mail по протоколу smtp. Узнаем, что почта есть и ждёт писем при помощи python

Уровень сложности Средний
Время на прочтение 3 мин
Количество просмотров 2.7K
Спам и антиспам Python *Email-маркетинг *
Кейс
Перевод
Автор оригинала: Scott Brady

Пригодится для решения задач по организации рассылок, а также как средство предварительной проверки эл. почты при регистрации.

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

Процесс верификации состоит из 4 частей:

  1. Проверка синтаксиса 

  2. Проверка домена и MX-записи

  3. Проверка ответа helo

  4. И, наконец, server.rcpt (готовность принять на конкретный адрес)

Проверка синтаксиса 

По проверке синтаксиса материалов довольно много, можно ознакомиться самостоятельно (1, 2, 3). Скотт предлагает своё выражение, которое тоже вполне рабочее.

import re

match = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', addressToVerify)

Проверка домена и MX-записи

Пожалуй самое ценное во всём этом материале, это проверка домена и существования на нём маршрутизации электронных писем. Делается при помощи библиотеки dnspython.

import dns.resolver

try:
    records = dns.resolver.resolve("mail.ru", 'MX')    
    mxRecord = records[0].exchange
    mxRecord = str(mxRecord)
except Exception as ex:
    print(ex)

По опыту использования именно здесь и было большинство ошибок, либо несуществующие домены, либо отсутствие MX-записи. Что автоматически означает бессмысленность попытки отправить почту.

Проверка ответа helo

В то же время существование домена и наличие MX-записи не говорят, о том, что письмо может быть отправлено, с сервером надо вступить в разговор.

import smtplib

server = smtplib.SMTP()
server.set_debuglevel(0)

try:
    server.connect(mxRecord)
    code, message = server.helo(host)    
except Exception as ex:
    print(ex)   

На этом этапе ошибки ловить не приходилось. Если всё хорошо, code будет 250, и ответное сообщение сервера разной степени учтивости. У mail.ru это 'mxs.mail.ru', Гугл более приветливый и отвечает:

mx.google.com at your service

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

А ещё есть проверка ehlo.

Готовность принять на конкретный адрес

В библиотеке smtplib есть специальный метод SMTP.verify(address), однако прямо в документации обозначено, что многие сервисы его поотключали из-за деятельности спамеров, поэтому предлагается другой способ проверки, существования конкретного ящика, а именно SMTP.rcpt(address).

server.mail('[email protected]')
code, message = server.rcpt(str(addressToVerify))

Это низкоуровневый метод, который идентифицирует конверт получателя. Если всё хорошо, получаем 250 код и сообщение типа:

(250, b'Go ahead')

В этом месте тоже ловится много проблем. Например, mail.ru не стесняется говорить: "Go ahead" при явно несуществующих адресах. Гугл, даёт более содержательные ответы по содержанию конверта.

(550, b"5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser ")

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

Если коротко, то по большому счёту это ручной проход всех этапов отправки письма кроме собственно отправки.

Закон о рекламе

На всякий случай напомню, что рассылки попадают под закон о рекламе и требуется предварительное согласие на её получение. Почтовые сервисы требуют указывать в подобных письмах где было получено согласие на получение и большими буквами надпись "ОТПИСАТЬСЯ".

Ссылки

Теги:
Хабы:
Всего голосов 2: ↑2 и ↓0 +2
Комментарии 10
Комментарии Комментарии 10

Публикации

Истории

Работа

Data Scientist
127 вакансий
Python разработчик
154 вакансии