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

Комментарии 92

Допустим, адрес Боба — bob@smith.com. Плюс-адрес можно сделать, добавив + и метку после него: bob+spam@smith.com. Если Боб зарегистрируется на сайте со вторым адресом, он всё равно будет получать письма на bob@smith.com – но теперь он может создать фильтры, или просто отключить один из плюс-адресов.

Это справедливо для gmail'а, где плюс интерпретируется именно так. А вообще local part — opaque, т. е. промежуточные MTA не должны делать каких-либо предположений о его структуре. Тот же ezmlm использует dash в качестве спец-разделителя.
В общем, спрячьте этот "ниочём", не позорьтесь.
Кто не верит — достаточно заглянуть в стандарт rfc5322 (superseeds rfc2822, rfc0822):
The local-part portion is a domain-dependent string. In addresses,
it is simply interpreted on the particular host as a name of a
particular mailbox
.

Ещё см. ниже.
Совершенно верно. Стандартом прямо запрещено трогать локальную часть:
Следовательно — и благодаря длинной череде проблем, вызванных промежуточными хостами, пытавшимися оптимизировать передачу путём изменения их [адресов — перев.], локальная часть ДОЛЖНА быть интерпретирована (и ей должен быть назначен семантический смысл) исключительно сервером, указанным в доменной части адреса.

То есть адрес надо разбирать с конца, и не трогать ничего левее первой встреченной "@".
На ваш адрес Gmail пишет: "Адрес elliotchance+blog в поле Кому не распознан. Проверьте правильность ввода всех адресов."
Получается все-таки нужно проверять email-адрес. Ведь даже если он валиден по RFC822, ваш SMTP-клиент может его не признать.
И не забываем национальные алфавиты в доменах.
Забываем сразу, потому что наплевать.
А что мешает спамерам автоматически убирать из мейлов всё что между плюсиком и собачкой?
Может то, что на серверах кроме gmail'а это будут разные адреса, если не делать специальной обработки?
Пример такого несоответствия можете привести? А коли и так, то хотя бы и для gmail'а...
Достаточно заглянуть в стандарт rfc5322 (superseeds rfc2822, rfc0822):
The local-part portion is a domain-dependent string. In addresses,
it is simply interpreted on the particular host as a name of a
particular mailbox.

Postfix (по умолчанию в rhel/centos) с настройками по умолчанию в /etc/postfix/main.cf имеет:
# ADDRESS EXTENSIONS (e.g., user+foo)
#
# The recipient_delimiter parameter specifies the separator between
# user names and address extensions (user+foo). See canonical(5),
# local(8), relocated(5) and virtual(5) for the effects this has on
# aliases, canonical, virtual, relocated and .forward file lookups.
# Basically, the software tries user+foo and .forward+foo before
# trying user and .forward.
#
#recipient_delimiter = +

Так что без специальной настройки (установленного параметра recipient_delimiter) он считает user@domain и user+tag@domain разными адресами.

Или можно заглянуть сюда, где описываются настройка qmail, sendmail, exim для такого поведения.
А коли и так, то хотя бы и для gmail'а...

Я вам большую тайну открою: gmail игнорирует точки в localpart в целях сравнения аккаунтов. И example@gmail.com совпадает с e.x.a.m.p.l.e@gmail.com. Но это не значит, что также делают остальные. Но это не повод для очередной статьи-откровения на хабре, ИМХО.

Можно пойти дальше и поведать сокровенное: localpart — case-sensitive. И интерпретация его в case-insensitive манере — личное дело конкретного MTA.
А зачем? Массово данную возможность не используют, тем более не везде она работает одинаково. Вот если накопится критическая масса адресов — тогда и будут учитывать, а пока зачем напрягаться?
НЛО прилетело и опубликовало эту надпись здесь
Вы можете сказать, в какой ситуации необходима поддержка полного RFC для почтовых адресов?
Я вижу только одно место, где нужно хотя бы об этом помнить но уж точно не проверять — парсинг писем, чтобы не получить какую-нибудь sql-инъекцию внутри комментария.
p.s. если пользователь сделал что то странное, что придумали люди из далеких 90-ых, не со зла а просто они были первопроходцами, то он сам себе доктор.
Вы можете сказать, в какой ситуации необходима поддержка полного RFC для почтовых адресов?

При написании MTA/MDA, очевидно ,)
Тоже не очевидно. Полностью поддерживать стандарт просто ради того чтобы его поддерживать бессмысленно. Если включить немного логики, то можно всё упростить. Когда ты отправляешь письмо, оно проходит через два сервера. Первому серверу из всего возможного безумия нужно только вычленить адресную часть. Второму серверу, нужно передать письмо тому пользователю, который создавал свой ящик на данном сервере, А значит формат именной части ему заранее известен, так как был ограничен еще на стадии регистрации ящика и реализовать стандарт он может в той мере в которой необходимо ему без фактического ущерба пользователям.
В общем я с вами согласен, сервер получатель вполне может контролировать формат допустимых адресов. Релеям тоже localpart не важен, он для них opaque. В общем, может быть актуально для гейтов. Но, если MTA, MDA или MUA хотят что-то делать с адресами в полях типа From/To/Reply-To/CC/BCC, то корректно обрабатывать их в соответствии с rfc5322 необходимо. Как пример — rewrite адреса.

Проблемы разобрать email и убедиться, что он соответствует rfc никакой нет. Достаточно взять грамматику из rfc5322 и сгенерировать парсер.
Когда ты отправляешь письмо, оно проходит через два сервера.

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

… Ну ничего себе заява!

"Нафига поддерживать этот стандарт на болты? Хрен с вами, диаметр я вам сделаю по стандарту, но шаг резьбы я придумаю свой, я же креакл творческая личность!"

Стандарты вообще-то для того и пишутся, чтобы поддерживаться до, ёпрст, последней запятой!
I_have(bad)ньюс*for*you@real.world
Ну и напиши на него что-нибудь, например через гмайл.
  1. Тыкать Вы своим родственникам можете, а на хабре™ вежливые люди™ общаются.
  2. Какую часть фразы

локальная часть ДОЛЖНА быть интерпретирована (и ей должен быть назначен семантический смысл) исключительно сервером, указанным в доменной части адреса.

Вы не понимаете?

гмайл, если его левая нога захочет, может отказаться принимать почту на адреса с локальной частью длиннее 4 букв — и вообще устанавливать любые правила, потому что это право сервера получателя — решать, как интерпретировать локальную часть. А если я хочу принимать почту на такие адреса на моём личном почтовом серваке — это моё право, и никто не может мне это запретить (равно как и не имеют права резать такие адреса при передаче).
Господи, в какой раз уже читаю статью об этом на хабре. Было же в конце того года.
Ну так год-то уже другой ;)
Я вот в первый раз это слышу. Было полезно. Жаль так и не было предложено решение.
То, что невозможно проверить емейл на допустимость с помощью регулярок — это понятно. Но ведь в реальности никому это обычно и не надо.
Обычно решают проблему как пользователю подсказать, что он напортачил с вводом емейла.
Самое элементарное решение — проверить наличие символа @. Он то уж точно должен быть.
То, что невозможно проверить емейл на допустимость с помощью регулярок — это понятно.

Мне вот непонятно. Множество валидных адресов конечно, а регулярки типа PCRE (вернее их трансляторы) являются конечными автоматами. Почему невозможно на регулярках построить на конечном множестве автомат с двумя состояниями ("валидно" и "невалидно") мне очень непонятно.
Ну потому, что статья вообще не о формальной проверяемости. А о распространенной практике нагугливания регулярки для проверки емейла. Которая как правило отсекает кучу валидных вариантов.
Он же привел в статье пример регулярки — которую тоже врят ли будет кто нибудь использовать и которая тоже не подходит.
В практической плоскости совсем другие проблемы обсуждаются. Проверка емейла на соответствие спецификации имеет смысл разве что для почтовых сервисов, но там им нет никакого резона ограничивать себя регулярками.
Мне кажется, как минимум, потому что в адресах попадаются правильные скобочные последовательности, а они уже не относятся к регулярным языкам. Но это если ограничения на длину нет.
В статье же указана правильная регулярка.
Повторенье — мать питанья ученья!
^(.+)@(.+)\.(.+)$
Все примеры из статьи проходят. Для задач валидации, когда вместо email написано имя или телефон, этого вполне достаточно.

Если мы не пишем почтовый сервер, нам неважно, соответствует этот адрес RFC или нет, потому что можно придумать валидный по RFC, но не существующий email-адрес. А если пишем, то скорее всего не будем проверять валидность регуляркой.
Для задач валидации можно и не ловить совпадения: ^.+@.+\..+$
НЛО прилетело и опубликовало эту надпись здесь
Для этого существует подтверждение email'а. Т.е. совсем другая задача которая проверяется независимо от валидации.
Удивительно, но факт: многие люди до сих пор часто либо путают эти понятия, либо зачем-то пытаются их совмещать.
НЛО прилетело и опубликовало эту надпись здесь
Я даже не знаю как прокомментировать тот бред что вы написали полностью все утрировав и проигнорировав все остальные комментарии.
Я пожалуй соглашусь с вами, при условии, что «более подробная» валидация не будет носить запрещающий характер. Мне очень понравилась ваша фраза «можно было бы подсказать, что с ними что-то не так». Если это будет именно подсказка, что-то в духе «ваш адрес выглядит странно, возможно вы допустили ошибку», и пользователь сможет нажать кнопку «нет, все правильно, это мой адрес», тогда можно сделать проверку на соответствие наиболее распространенным форматам адресов. И это будет действительно полезно и удобно. А вот строго запрещать адреса, не прошедшие валидацию — смысла я не вижу. Если человек не хочет вводить свой адрес, он всегда может ввести корректный с точки зрения стандартов, но несуществующий адрес, или чужой, или свой, но неиспользуемый. И даже без злого умысла, ввел, а потом обнаружилось что пароль от почты забыл. Так что если адрес действительно важен, то в любом случае нужно письмо с подтверждением слать. И периодически, хотя бы раз в полгода, спрашивать у пользователя, не изменился ли его адрес.
Ну и если уж речь зашла про конверсию, нужно учитывать, что сейчас многие люди вообще почтой не пользуются по назначению, и ящики заводят только для регистраций, потому что большинство сайтов требует почту. Человек конечно зайдет в почту, если ему надо восстановить пароль, но если вы хотите, чтобы пользователь оперативно получал ваши сообщения, надо просить у человека не мыло, а то, чем он активно пользуется: телефон, facebook, WhatsApp, Viber и т.д… Все, чем он согласится поделиться. Ситуацию с почтой сейчас только Google вытягивает, привязывая почту к Android аккаунту. Если у человека почта gmail и Adroid, то письма он хотя бы на мобильнике увидит. Если же он вам не gmail'овсую почту дал, то, с высокой вероятностью, он ее проверяет. только когда ждет очередного письма с подтверждением регистрации.
Лично я даже наличие точки проверять бы не стал. Если домен внутренний, точек у него может и не быть. Что-то типа: «ivanov_vv@rogaikopyta».
Если же по какой-то причине действительно нужно проверить соответствие адреса стандарту RFC, например вы пишете программу, которая проверяет адрес на соответствие этому стандарту, то пытаться сделать полную проверку с помощью регулярного выражения это как-то странно. Особенно если это выражение принимает такой монструозный вид, как пример из статьи. Даже если это регулярное выражение будет работать правильно, лучше от него отказаться и написать обычную процедуру. Нет, ну серьезно, вы только представьте, что у вас обнаружился баг и вы подозреваете, что проблема в регулярном выражении. И вот вам надо найти в нем ошибку. Сколько часов это займет?
Касаемо стандарта, из всего что описано в статье, плюсик кажется более-менее полезным. Хотя я бы эту задачу решил подключением нескольких разных адресов к одному почтовому клиенту. Или настроив перенаправление. Тогда тот, кому я дал свой рабочий адрес будет знать только его. Если же написать «vasyapupkin+work@example.com», то любой догадается что отбросив "+work" можно послать Васе письмо на основной ящик. А уж комментарии в адресе вообще не понятно зачем нужны. Если они никак не влияют на то, куда будет доставлена почта, то значит они и частью адреса, по сути, не являются. Если адреса «vasyapupkin(1)@example.com» и «vasyapupkin(2)@example.com» указывают на один и тот же ящик, то можно просто удалить все что находится в скобках. Вообще, давно пора написать новый стандарт, включив в него то, что реально используется на практике и отбросив все лишнее. И уже его дальше продвигать и поддерживать. К тому же, у меня есть подозрение, что полная поддержка стандарта RFC822 никогда и никем так и не была реализована. Поправьте, если я ошибаюсь.
Даже если это регулярное выражение будет работать правильно, лучше от него отказаться и написать обычную процедуру. Нет, ну серьезно, вы только представьте, что у вас обнаружился баг и вы подозреваете, что проблема в регулярном выражении. И вот вам надо найти в нем ошибку. Сколько часов это займет?


Ничто не мешает обернуть регулярку в процедуру, а какую-то другую реализацию писать только когда ошибка в регулярке обнаружится.
Ну, как вариант, конечно. Но это если изначально вы «стащили» откуда-то готовую регулярку. Или она досталась вам по наследству. А так, зачем изначально ее писать, если в итоге получается write-only код? То есть в случае необходимости изменения регулярки мы ее полностью выкидываем и пишем вместо нее процедуру, или другую регулярку. А если бы изначально была обычная понятная процедура, то мы бы могли ее не с нуля переписывать, а найти и исправить то место, которое не соответствует нашим требованиям.
З.Ы. Я не говорю, что вообще не надо использовать регулярные выражения. Просто, по моему мнению, в силу особенностей синтаксиса они не предназначены для реализации в одном регулярном выражении большой и сложной логики. Они должны оставаться маленькими и простыми. А для реализации более сложной логики можно комбинировать несколько регулярных выражений. То есть пишем процедуру, в которой часть обработки делаем через последовательное применение нескольких регулярок, а часть, возможно и с помощью иных строковых функций. Возьмем тот же пример со скобочками в адресе. Как верно подмечено в статье, в регулярках разбирать рекурсивные выражения довольно сложно. Но в данном случае нам достаточно прогнать строку по символам в цикле один раз, походу считая количество открывающих и закрывающих скобок, и как только количество закрывающих скобок совпало с количеством открывающих — закрылась самая внешняя скобка, удаляем все между этими скобками и так далее до конца строки. А потом получившуюся очищенную строку можно уже скормить регулярному выражению. Код получается простейший, его даже студент сможет понять и поддерживать.
Так вы постепенно напишите полноценный парсер. Не проще ли сразу взять грамматику из rfc и сгенерировать его? В смысле поддержки оно куда гуманнее будет.
Если вы про пример со скобками в адресе, то это всего лишь частный случай. Я просто описал на этом примере свой подход к работе с регулярными выражениями. Иногда, дописав пару строк кода на императивном языке, можно на порядок упростить регулярное выражение. То есть речь тут уже не столько об e-mail адресах, сколько о регулярных выражениях.
А как насчет "test example.com"? (обратите внимание на пробел). Вроде как это не валидный email. При этом довольно распространенная ошибка. Так что как минимум надо делать ^\S+@\S+\.\S+$. Ой Постойте. А как же test@example.com test1@example.com (Не знаю как отобразится, но между двумя адресами должен быть перенос сторки). Такой адрес тоже пройдет. Ну тогда надо \A\S+@\S+\.\S+\z. Это кстати не выдуманные, а примеры из жизни.
Ждем следующие комменты, почему и эта регулярка не подходит.
Вы правы, довести проверку до 99.99999% надёжности можно последовательно усложняя регулярку. michael_vostrikov, как мне кажется, говорит о том, что для получения 99% надёжности хватит и простого выражения. А до 100% регулярными выражениями довести не получится никогда.
Каждый сам для себя должен решить насколько ему нужны эти 0.99999%, сколько труда он готов в них вложить.
Ну на мой взгляд проблема в том что изначальная регулярка не будет ловить достаточно большое количество невалидных адресов. Например пробел внутри адреса достаточно распространенная проблема чтоб все-таки ловить. Притом что делается это минимум усилий. Вот про то чтоб проверять на точку в host-части я согласен, не смотря на то что адрес без точки тоже вполне валидный, но, как раз в практическом плане, такой адреса будет невалидным.
Например пробел внутри адреса достаточно распространенная проблема чтоб все-таки ловить.
Я вот, честно говоря, в этом не убеждён. Я не утверждаю, что такого никогда не случается, но понятие «достаточно распространённая» слишком уж расплывчатое. Нужно смотреть какую-то реальную статистику.

Как я и написал, можно последовательно усложнять регулярку, получая условно дополнительную девятку в проценте. Просто каждый следующий шаг приносит всё меньше и меньше реально пользы проекту и нужно в какой-то момент остановиться.
но, как раз в практическом плане, такой адреса будет невалидным
Казалось бы, человек читал статью…

Лично знаю человека с почтой на домене `ua`.
Хм. Не думал что такие существуют. Я знаю что в теории могут быть, но на практике не доводилось встречать.
Я бы ещё удалили проверку точки в домене.
test@localhost:7896 не пройдёт
Ожидал увидеть математическое доказательство, что аппарата регулярных выражений недостаточно для корректного парсинга, например потому что он не является тьюринг-полным
Это кажется забавным, но абсолютно все приведенные вами e-mail адреса, за исключением elliotchance+blog(silvrback)@gmail.com, проходят проверку с помощью того страшного regexp'а из RFC822, о котором вы писали в начале статьи.
Попробуйте сами, вот вам пруф.
Прошу прощения, не заметил что это перевод.
Но все же, как так?
Ну, а, собственно, что не так-то? Никто же не утверждал, что приведённый в начале статьи монстр бесполезен.
Но вот такой адрес, например, явно не валиден, но проверку проходит: (here(is(some)crazy)comments))))))))a@b.com.
страшного regexp'а из RFC822

В rfc822 такого регекспа нет, если что.
Вот бы какую-то реальную статистику увидеть — сколько процентов пользователей имеют такие "нестандартные" адреса.
Такие адреса иметь бесполезно, потому что на каждом сайте своя регулярка, и вам сильно повезёт, даже если банальный "+" примут.
О том и речь — если никто этими функциями не пользуется, то какой смысл каждые три месяца мусолить эту тему?
А, может, окажется наоборот — десятая часть всего интернета не может на Фейсбуке зарегистрироваться, потому что у них email вида #!$%&'"@"*+-/=?^_{}|~+foo@example.org(why(so(serious)))`
Ну, при регистрации часто получаю отказ, когда пытаюсь задать e-mail с плюсом (типа username+sitename@example.org).
Каждые полгода на Хабре стабильно появляется статья про регулярки и емейлы.
никогда не учитывал мейлы по спецификации.
mail@example.com и никаких " ' + и прочей ерунды.
Только тестировщики имеют адреса типа "a@a"@mysite.ru — реальный же человек столкнувшись несовершенством мира (с тем что во многих программах и сайтах такой адрес не получится использовать) заведёт себе адрес нормальный забросив предыдущий.
Обычно на почтовых сервисах не завести адрес со всякими плюсами. Хотя гугл и позволяет использовать в своем адресе +, как написано в статье, я не уверен, что такой адрес там можно завести.
У gmail + это фича. Т.е. если у вас есть адрес vasya.pupkin@gmail.com то почта так же будет приходить и на адрес vasya.pupkin+habrahabr.ru@gmail.com Кстати vasyapupkin@gmail.com — тоже будет работать как и v.a.s.y.a.p.u.p.k.i.n@gmail.com Можете проверить ;)
Регулярка, за которую я получил 16 минусов, матчит даже русские адреса.
/^[^()<>@,;:\\".\[\] \000-\037\177*&]+(\.[^()<>@,;:\\".\[\] \000-\037\177*&]+)*@[^()<>@,;:\\".\[\] \000-\037\177*&]+(\.[^()<>@,;:\\".\[\] \000-\037\177*&]+)*$/i

Тесты на языке Perl
use Test;
use strict;

BEGIN { plan tests => 88 };

my $mail_reg = qr/^[^()<>@,;:\\".\[\] \000-\037\177*&]+(\.[^()<>@,;:\\".\[\] \000-\037\177*&]+)*@[^()<>@,;:\\".\[\] \000-\037\177*&]+(\.[^()<>@,;:\\".\[\] \000-\037\177*&]+)*$/i;
#my $mail_reg = qr/^[a-z0-9\-]+(\.[a-z0-9\-]+)*@[a-z0-9\-]+(\.[a-z0-9\-]+)*$/i;

ok(test('Test@test.ru'), 1);
ok(test('test@a.a'), 1);
ok(test('---@example.com'), 1);
ok(test('root@localhost'), 1);
ok(test('foo-bar@example.net'), 1);
ok(test('mailbox.sub1.sub2@this-domain'), 1);
ok(test('sub-net.mailbox@sub-domain.domain'), 1);
ok(test('Neuman@BBN-TENEXA'), 1);

ok(test('Русский@русский'), 1);#поменять на 0, если используется вторая регулярка

###Всё остальное не проходит###
ok(test('test@aa..aa'), 0);
ok(test('a..a@aa.aa'), 0);
ok(test('.aa@aa.aa'), 0);
ok(test('aa.@aa.aa'), 0);
ok(test('aa@aa.aa.'), 0);
ok(test('aa@.aa.aa.'), 0);
ok(test('.@aa.aa.'), 0);
ok(test('a@.'), 0);
ok(test('.@.'), 0);
ok(test('.@..'), 0);
ok(test('..@..'), 0);
ok(test('ab[]igail@example.com'), 0);
ok(test('ab\[\]igail@example.com'), 0);
ok(test('this is string'), 0);
ok(test('abigail@example.com '), 0);
ok(test(' abigail@example.com'), 0);
ok(test('abigail @example.com'), 0);
ok(test('*@example.net'), 0);
ok(test('"\""@foo.bar'), 0);
ok(test('fred&barny@example.com'), 0);
ok(test('"127.0.0.1"@[127.0.0.1]'), 0);
ok(test('Abigail <abigail@example.com>'), 0);
ok(test('Abigail<abigail@example.com>'), 0);
ok(test('Abigail<@a,@b,@c:abigail@example.com>'), 0);
ok(test('"This is a phrase"<abigail@example.com>'), 0);
ok(test('"Abigail "<abigail@example.com>'), 0);
ok(test('"Joe & J. Harvey" <example @Org>'), 0);
ok(test('Abigail <abigail @ example.com>'), 0);
ok(test('Abigail made this < abigail @ example . com >'), 0);
ok(test('Abigail(the bitch)@example.com'), 0);
ok(test('Abigail <abigail @ example . (bar) com >'), 0);
ok(test('Abigail < (one) abigail (two) @(three)example . (bar) com (quz) >'), 0);
ok(test('Abigail (foo) (((baz)(nested) (comment)) ! ) < (one) abigail (two) @(three)example . (bar) com (quz) >'), 0);
ok(test('Abigail <abigail(fo\(o)@example.com>'), 0);
ok(test('Abigail <abigail(fo\)o)@example.com>'), 0);
ok(test('(foo) abigail@example.com'), 0);
ok(test('abigail@example.com (foo)'), 0);
ok(test('"Abi\"gail" <abigail@example.com>'), 0);
ok(test('abigail@[example.com]'), 0);
ok(test('abigail@[exa\[ple.com]'), 0);
ok(test('abigail@[exa\]ple.com]'), 0);
ok(test('":sysmail"@ Some-Group. Some-Org'), 0);
ok(test('Muhammed.(I am the greatest) Ali @(the)Vegas.WBA'), 0);
ok(test('name:;'), 0);
ok(test('\':;'), 0);
ok(test('name: ;'), 0);
ok(test('Alfred Neuman <Neuman@BBN-TENEXA>'), 0);
ok(test('"George, Ted" <Shared@Group.Arpanet>'), 0);
ok(test('Wilt . (the Stilt) Chamberlain@NBA.US'), 0);
ok(test('Cruisers: Port@Portugal, Jones@SEA;'), 0);
ok(test('$@[]'), 0);
ok(test('*()@[]'), 0);
ok(test('"quoted ( brackets" ( a comment )@example.com'), 0);
ok(test(qq {"Joe & J. Harvey"\x0D\x0A <ddd\@ Org>}), 0);
ok(test(qq {"Joe &\x0D\x0A J. Harvey" <ddd \@ Org>}), 0);
ok(test(qq {Gourmets: Pompous Person <WhoZiWhatZit\@Cordon-Bleu>,\x0D\x0A}), 0);
ok(test(qq { Childs\@WGBH.Boston, "Galloping Gourmet"\@\x0D\x0A}), 0);
ok(test(qq { ANT.Down-Under (Australian National Television),\x0D\x0A}), 0);
ok(test(qq { Cheapie\@Discount-Liquors;}),0);

ok(test('Just a string'), 0);
ok(test('string'), 0);
ok(test('(comment)'), 0);
ok(test('()@example.com'), 0);
ok(test('fred(&)barny@example.com'), 0);
ok(test('fred\ barny@example.com'), 0);
ok(test('Abigail <abi gail @ example.com>'), 0);
ok(test('Abigail <abigail(fo(o)@example.com>'), 0);
ok(test('Abigail <abigail(fo)o)@example.com>'), 0);
ok(test('"Abi"gail" <abigail@example.com>'), 0);
ok(test('abigail@[exa]ple.com]'), 0);
ok(test('abigail@[exa[ple.com]'), 0);
ok(test('abigail@[exaple].com]'), 0);
ok(test('abigail@'), 0);
ok(test('@example.com'), 0);
ok(test('phrase: abigail@example.com abigail@example.com ;'), 0);
#ok(test('invalidЈchar@example.com'), 0);

ok(test(qq {"Joe & J. Harvey"\x0A <ddd\@ Org>}), 0);
# Invalid, CR LF not followed by a space.
ok(test(qq {"Joe &\x0D\x0AJ. Harvey" <ddd \@ Org>}), 0);
# This appears in RFC 822, but ``Galloping Gourmet'' should be quoted.
ok(test(qq {Gourmets: Pompous Person <WhoZiWhatZit\@Cordon-Bleu>,\x0D\x0A} .
qq { Childs\@WGBH.Boston, Galloping Gourmet\@\x0D\x0A} .
qq { ANT.Down-Under (Australian National Television),\x0D\x0A} .
qq { Cheapie\@Discount-Liquors;}), 0);
# Invalid, only a CR, no LF.
ok(test(qq {"Joe & J. Harvey"\x0D <ddd\@ Org>}), 0);

sub test {
my $mail = shift;
return ($mail ~~ $mail_reg) ? 1 : 0;
}

НЛО прилетело и опубликовало эту надпись здесь
У меня складывается ощущение, что я перевод того же уже читал на хабре. Хотя, возможно, показалось.
Вам показалось, оригинальная статья от 1 апреля 2016 года.
Эти статьи каждый год на хабре появляются.
Самый лучший способ проверить email:
  1. Если есть символ @, то идём на п2
  2. Отправляем email — если дошло, email правилен.

ВСЁ
А как проверить, что дошло? :)
Как обычно, через форму активации почты.
не, проверка через юзера — это слишком сложно. Для тех случаев, когда юзверь в этом заинтересован — да. А когда не очень — нет.
Ну и когда адресов десятки и сотни тысяч, то посылать на невалидные адреса — это тоже не дело. Лишний трафик, лишняя нагрузка…
Какие есть кейсы, где «десятки и сотни тысяч» новых email-адресов, каждый день. Да еще «когда юзверь в этом не очень заинтересован»?
Вся проблема тут кроется в «юзверь не заинтересован». Если он не заинтересован, то остается только вежливо попросить мыло, и надеяться что пользователь согласится его дать. И при этом не соврет. Потому что тут проверяй/не проверяй, а мыло может быть просто несуществующим. Или он может опечататься. Конечно дополнительная проверка корректности в этом случае может слегка улучшить ситуацию. Но опять же, если «пользователь не заинтересован», он может просто плюнуть на заполнение мыла, после одной-двух вылетевших ошибок, типа «адрес некорректен». В конце концов, стоит спросить себя, нужно ли нам вообще тратить свое время и ресурсы на того, кто не заинтересован. Какая с него будет конверсия?
И еще, тут нужно поднять другой, очень важный вопрос. Я так понимаю, вы предлагаете в некоторых случаях собирать e-mail'ы пользователей, не посылая им письмо с подтверждением регистрации. Мол они не очень заинтересованы, и просто поленятся лезть в ящик, нажимать ссылки в письме. На первый взгляд логично, но тут есть серьезная проблема. И она заключается отнюдь не в том, что адрес может быть неправильным или несуществующим. Что если кто-то введет чужой адрес? Он корректен, ни регулярка, ни даже полноценный парсер его не смогут отсеять. Письмо с подтверждением мы не шлем, просто по умолчанию считаем что адрес правильный и принадлежит тому. кому надо. Сохраняем его в базу. А для чего сохраняем? Чтобы слать различные коммерческие предложения, извещения об акциях, и т.д. Иными словами слать рекламу. Но слать мы ее будем человеку, который на это не подписывался и даже не знает о нашем сайте. Какими будут его действия? Кнопка «пожаловаться на спам» — вот его ответ. Более того, он может так поступить, даже если в письмах не реклама будет. Просто посчитает это подозрительным и даже будет прав. Разбираться что к чему он врятли станет, ведь он в этом «не очень то заинтересован». А теперь представьте что таких случаев за год наберется несколько тысяч. А может наши конкуренты и зложелатели специально нарегистрируют подписок на левые чужие адреса. А как работают спам фильтры у того же gmail? Набирается много жалоб и отправитель попадает в черный список — вот и весь алгоритм. Это конечно не единственный алгоритм, и у каждого почтового провайдера свой набор методов, но вот именно этот алгоритм самый очевидный и есть у всех в том или ином виде. Иными словами мы рискуем попасть в черные списки, и наша рассылка перестанет приходить даже тем, кто не против был ее получать. Скажу даже больше — попадание в черные списки будет заслужено. Ведь мы нарушили общепринятый этикет — проверять что почта не только корректна, но и действительно принадлежит тому, кто нам ее предоставил.
Резюмирую: отказ от проверки почты через активацию противоречит общепринятым нормам, может доставить неудобства посторонним людям, и кроме всего прочего, несет серьезные риски для нас самих.
А для чего сохраняем? Чтобы слать различные коммерческие предложения, извещения об акциях, и т.д. Иными словами слать рекламу.


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

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

Это всё достаточно серьезные операции. Если пользователь введет валидное, но неправильное мыло (volch@gmali.com вместо volch@gmail.com). То доступ уже не восстановит, документы не дойдут, важные операции не возможно будет произвести.
Какой-то не реальный кейс.
Добавлю свои 5 копеек
  1. Самая первая регулярка из статьи посчитает валидным email: #@*%ab
  2. В локальной части email могут быть русские буквы. Встречал компании в которых все корпоративные email были такими.
  3. Домен верхнего уровня может содержать цифры (.i2p) и русские буквы (.рф)
  4. Домен верхнего уровня может быть длиннее 5 символов. Пример: .example, .localhost (RFC2606) это конечно не рабочие домены, но все равно домены.

Желающие могут полистать RFC4185
4. Уже давно есть .travel или, например, .moscow, вполне рабочие TLD
Интернациональные домены переводятся в punycode, а там всё едино.
Я ожидал этот комментарий. Есть одно но. Мы используем регклярку для проверки email введенного пользователем, а он не будет переводить свой интернациональный email в punycode только чтоб угодить вам
Верно, но можно привести интернациональный email в punycode и после валидировать по минимуму email. Как вариант, если не обращать внимание на накладные расходы, то проверять используя exim, вроде как опция -bt
4 апреля 2013 в 01:12
Прекратите проверять Email с помощью регулярных выражений!
habrahabr.ru/post/175375
30 мая 2014 в 00:12
Никогда не проверяйте e-mail адреса по стандартам RFC
habrahabr.ru/post/224623
13 января 2016 в 02:20
Я знал, как валидировать email-адрес. Пока не прочитал RFC
habrahabr.ru/post/274985
Чем больше экспертов изучало, консультировало, разрабатывало, тестировало тем лучше.
Как уже писали на Хабрахабре, лучшая проверка валидности email адреса — просто отправить на него письмо.
Зачем делать из мухи слона?
Если e-mail важен — все равно нужно подтверждение, если нет — пусть вводят что угодно…
У нас есть традиция — каждый год на хабре кто-то пишет о том, как сложно и почти нереально парсить email хранимками…
А между тем, проверка проста —

contains('@') в поле
Отослать письмо в качестве реальной проверки
Если вы хотите добавить или убрать из имени пользователя точки (.), ничего менять не нужно. Если ваше имя пользователя выглядит как «мой.адрес@gmail.com», сообщения, отправленные на адрес «мойадрес@gmail.com» и «м.о.й.а.д.р.е.с@gmail.com», также будут доставляться вам.
Стоит понимать, что это относится только к gmail.

Postgres Professional
Приглашаю вас к прочтению этой статьи в связи с попыткой валидации вашим сайтом postgrespro.ru моего адреса вида user+postgrespro.ru@gmail.com

Вопрос решен, спасибо!

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации