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

Это пересказ довольно старой статьи (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('any@mail.box')
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 ")

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

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

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

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

Ссылки

Комментарии (7)


  1. anzay911
    01.07.2023 04:06
    +3

    Как можно не знать получателя? Он же заявку на рассылку оставил и свой ящик подтвердил. /sarcasm


    1. Story-teller Автор
      01.07.2023 04:06
      +1

      На самом деле, без всякого сарказма, чаще всего пользователь допускает ошибки в когда оставляет адрес в форме, получается undex.ru и тому подобное) а если форма рукописная, то беда совсем.

      Хотя и сарказм конечно понятен, базы рассылок, часто никуда не годятся, но надеюсь, что закон о рекламе, коллегами всё-таки соблюдается в той или иной мере


  1. kvazimoda24
    01.07.2023 04:06
    +6

    Регулярка для проверки валидности адреса сломается на национальных доменах в национальных кодировках. Так же, есть куча доменов верхнего уровня длиннее четырёх букв.

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


    1. Story-teller Автор
      01.07.2023 04:06

      Да, замечание верное, с регуляркой нужно быть аккуратным  на Хабре тема довольно полно раскрыта: 123.


  1. Ryav
    01.07.2023 04:06
    +1

    Есть же email-validator.


  1. Tangeman
    01.07.2023 04:06
    +1

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

    Что же нужно? Нужно убедиться что потенциальный получатель действительно может получить, прочитать и понять письмо.

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

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

    Проверки доступен ли сервер (HELO/EHLO), ответа на RCPT TO и любые другие которые не отправляют писем - недостаточны - во-первых, сервер может быть недоступен в данный конкретный момент времени (даже если это Гугль или Microsoft), во-вторых, он вполне может отбить письмо и после отправки тела через DATA, причём не просто отбить а даже сказать "нет такого ящика" (для корпоративных серверов вполне себе реалистичный сценарий, если там пара прокси по дороге).

    Если сразу отправить не удалось - можно сказать про это пользователю и предложить подождать, а через некоторое время - и повторить. Если письмо отбито после DATA - об этом тоже можно сказать и попросить разобраться или изменить email, или повторить позже.

    В любом случае результат валидации нужно сообщить пользователю - либо сказать "всё ок", либо дать максимум информации если что-то пошло не так (включая ответ его почтовика - сильно помогает с разборками).

    Что же до самого адреса (до @) - как уже выше заметили, не надо его проверять, он может быть любым - включая "A & Б сидели на трубе!"@почта.где-то.там и без ограничения по длине в 16-20 символов. Сервисы же которые выпендриваются и даже "+" не разрешают в адресе вообще должны гореть в аду, не говоря уже о тех которые отказываются принимать вполне себе символьные имена которые по их мнению "неправильные" или "невозможные" (вспоминается eBay - они не разрешали email независимо от домена если в нём была подстрока "ebay", причём служба поддержки отморозилась в духе "у вас не может быть такого email").


  1. Mas73r
    01.07.2023 04:06

    Не обязательно наличие MX-записи для получения почты. Читаем почтовые RFC.