LINUX.ORG.RU
ФорумAdmin

Массовая проверка адресов email перед рассылкой

 , , ,


0

1

Приветствую, коллеги! С праздником! :-)

Итак, поставлена вполне прикладная задача: не принимать от маркетологов списки рассылки, в которых содержится множество непроверенных (в т.ч. - путём простого считывания) адресов email.

Сами адреса попадают в списки от девочек-вводисток, которые читают вручную запоненные анкеты и вколачивают оттуда данные в какую-то первичную Excell-подобную систему (а то и в сам Эксель). Грязь и ошибки, которые при этом возникают, как легко догадаться, самые разные:

  • забыла «собаку»
  • поставила запятую вместо точки
  • забыла переключить язык
  • задела мизинцем какой-то непечатный символ
  • и т. п.

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

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

Разумеется, предварительно просмотрел, кто и как к этой задаче подходил до меня и понял, что создавать прийдётся самому. Иначе как обяснить, что кто-то, прочитав коротенький раздел 3.4.1. Addr-spec specification RFC2822 в итоге пришёл к чему-то вроде

((([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))

Итого имеем две заготовки скриптов в Bash:

  1. Выборка только годных адресов
  2. Выбрка НЕгодных адресов с целью, со всей деликатностью и доброжелательностью, но всё же ткнуть в них носом коллег-маркетологов

Мои попытки привели меня к следующим результатам. В первом случае:

#!/bin/bash
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }
/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | sed -n '/^[a-zA-Z0-9_.-]\+@[a-zA-Z0-9_.-]\+\.[a-zA-Z]\+$/p' | /usr/bin/sort -u > "$1.clean"

И - во втором (по сути - зеркальном первому):

#!/bin/bash
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }
/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | /usr/bin/sed '/^[a-zA-Z0-9_.-]\+@[a-zA-Z0-9_.-]\+\.[a-zA-Z]\+$/d' "$1" | /usr/bin/sort -u | /usr/bin/sed = | /usr/bin/sed 'N;s/\n/\t/'

Осознавая всю мощь и, как следствие, опасность скрытых ошибок sed надеюсь услышать подсказки и рекомендации коллег по данному вопросу.

P.S. Предвижу встречный вопрос из аудитории: «а что ты дурью мучаешься, если знаешь, что большинство спам-мейлеров сами проводят предварительную проверку списков адресов перед началом рассылки?!» Отвечу: мы планируем автоматизировать данный процесс через создание набора простых и надёжных скриптов, (по-возможности) полностью исключив интерактив с живым сотрудником. Да и не очень-то я доверяю этим роботам-спамерам ;-)

Заранее признателен за конструктивные комментарии.


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

bvn13 ★★★★★ ()
perl -MEmail::Valid -lpe 'BEGIN { open $good, ">good.txt"; open $bad, ">bad.txt"; } Email::Valid->address($_) ? select $good : select $bad; END { close $good; close $bad; }' list.txt

Здесь list.txt — исходный список адресов (по одному на строку), good.txt и bad.txt — резуьтирующие списки корректных и некорректных адресов соответственно. Принципы определения корректности см. в perldoc Email::Valid.

dexpl ★★★★★ ()
Ответ на: комментарий от anonymous
filter_var('bob@localhost', FILTER_VALIDATE_EMAIL); // false
filter_var('bob@customtld', FILTER_VALIDATE_EMAIL);// false
deep-purple ★★★★★ ()

Коллеги, искренне благодарен всем, кто откликнулся!

Итого, со счётом 2:1 пока побеждает встроенная функция PHP filter_var(). Perl забирает серебро :-)

Очевидно, что предложенные решения - рабочие, однако для меня это остаётся чёрным ящиком с неизвестными встроенными фильтрами.

Абсолютный контроль над происходящим даёт лишь собственный скрипт, который за эти дни получил следующую форму:

  • для выборки «правильных» адресов
#!/bin/bash
[[ -z "$1" ]] && { echo "Usage: $0 <file_name>"; exit 0; }
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }

/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | /usr/bin/sed -n '/^[a-zA-Z0-9._-]\{2,\}@\([a-zA-Z0-9._-]\)\{2,\}\.[a-zA-Z0-9]\{2,\}$/p' | /usr/bin/sort -u > "$1.clean"
  • и, соответственно, для отсева непроходящих под мои правила
#!/bin/bash
[[ -z "$1" ]] && { echo "Usage: $0 <file_name>"; exit 0; }
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }

/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | /usr/bin/sed '/^[a-zA-Z0-9._-]\{2,\}@\([a-zA-Z0-9._-]\)\{2,\}\.[a-zA-Z0-9]\{2,\}$/d' "$1" | /usr/bin/sort -u | /usr/bin/sed = | /usr/bin/sed 'N;s/\n/\t/'

Здесь, видимо, стоит перечислить, что я подразумеваю под «моими правилами». Их немного:

  • буквы только основного латинского алфавита (ASCII <128);
  • цифры в названии ящика и доменов второго и следующих уровней (но не первого);
  • заглавные буквы допустимы в написании, т.к. по сути ни на что не влияют (см. п.1)
  • хотелось бы реализовать, но пока не придумал - как (и здесь вопрос к профессиональному сообществу) запрет на глубоко вложенную поддоменную структуру вида address@subdomain.subsubdomain.subdomain.company.com

Буду рад увидеть свежие идеи и методы их реализации. Спасибо за поддержку!

root66 ()
Ответ на: комментарий от Mike_RM

Видел. Упоминал в своём первом сообщении. Выглядит, как анекдот, не меньше :-)

Устарело, как и пришедшее ему на смену RFC2822. Сейчас актуально RFC5322 (https://tools.ietf.org/html/rfc5322), однако от него не легче.

root66 ()
Ответ на: комментарий от root66

Закрывая тему

Нашёл решение по своей же задаче «хотелось бы реализовать, но пока не придумал - как (и здесь вопрос к профессиональному сообществу) запрет на глубоко вложенную поддоменную структуру вида address@subdomain.subsubdomain.subdomain.company.com»

В итоге парные скрипты на sed, которые меня полностью устраивают и решают мою задачу, выглядят следующим образом:

#!/bin/bash
# ~/bin/clean-spamlist

[[ -z "$1" ]] && { echo "Usage: $0 <file_name>"; exit 0; }
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }

/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | /usr/bin/sed -n '/^[a-zA-Z0-9._-]\{2,\}@\([a-zA-Z0-9_-]\{2,\}\.\)\{0,3\}[a-zA-Z0-9_-]\{2,\}\.[a-zA-Z0-9]\{2,\}$/p' | /usr/bin/sort -u > "$1.clean"
#!/bin/bash
# ~/bin/show-bad-emails

[[ -z "$1" ]] && { echo "Usage: $0 <file_name>"; exit 0; }
[[ -f "$1" ]] || { echo "File not found: $1"; exit 0; }

/usr/bin/sed 's/[[:blank:]]//g;/^$/d;' "$1" | /usr/bin/sed '/^[a-zA-Z0-9._-]\{2,\}@\([a-zA-Z0-9_-]\{2,\}\.\)\{0,1\}[a-zA-Z0-9_-]\{2,\}\.[a-zA-Z0-9]\{2,\}$/d' "$1" | /usr/bin/sort -u | /usr/bin/sed = | /usr/bin/sed 'N;s/\n/\t/'

Ещё раз спасибо всем, кто проявил интерес к обозначенной проблеме!

root66 ()
16 ноября 2019 г.
Ответ на: Закрывая тему от root66

С адресами мэйл.ру работает проверка?

Сколько не пробовал чем проверять именно с мэйл.ру адресами проблема все равно, всегда показывает что ок все с адресом. Не смотрели https://smtp.bz/features/validator Я проверил бесплатный пакет который дают там вроде нашел мэйл.ру, не понимаю как просто…

revision12revision ()

а как насчет почты в idn доменах?

slowpony ★★★ ()
Ответ на: комментарий от Bootmen

:-)

У меня есть письменное согласие от каждого получателя рассылки, коллега. Все бы работали настолько корректно, Мир был бы добрее.

root66 ()
Ответ на: С адресами мэйл.ру работает проверка? от revision12revision

15k адресов в бесплатной версии - маловато для наших задач. У нас - десятки тысяч получателей.

Второй вопрос: что за шаблон (алгоритм) они используют? Я доверяю только тому, что вижу (и в состоянии понять) сам, а это - black box. Допускаю, что - хороший и тем не менее.

root66 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.