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

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

Лучший способ проверить email на валидность — отправить туда письмо.
Валидность с точки зрения стандарта? С точки зрения большинства сервисов (иначе если почта будет ходить между двумя-тремя серверами, и примут такую почту на полутора сайтах, то она не то чтобы валидна)? С точки зрения своего мейлера?
Лучший способ валидации для каждого сценария разный.
занудаOFF:
Но вообще я с вами согласен, что для практических целей лучше просто отправить письмо.
Если это допустимо. Часто валидация почты письмом ухудшает конверсию. А проверить при регистрации надо.
Лично я проверяю штатным фильтром пхп, после чего проверяю существование МХ у домена почты. И прочтение статьи меня ничуть не сподвигло проверять насколько строгий фильтр встроен в пхп. Все им пользуются, значит для практических целей это можно условно считать стандартом.
Про сценарии различные согласен, разумеется.
Вообще интересны какие-нибудь исследования про долю ошибок в поле емейла, которые отсекаются чем-то сложнее проверкой наличия коммерческого at и точки, отделяющей TLD.
По стандарту mx записи может и не быть, тогда почтовый сервер пытается отправить на сервер полученный из A записи…
Это вы старым sendmail теперь расскажите =)
В RFC это всегда было написано. А вот sendmail этого «не знал», года до 2005го.
книга по шлимылу как раз. А вот про rfc слукавил. Сейчас хотел найти и не нашел там такого.
И как я только пользовался почтой в 94-м на юникс-машинах для которых никто и никогда не стал-бы прописывать отдельные MX-ы?
Я вам больше скажу, есть подозрение, что само понятие MX-ов появилось заметно позже, чем sendmail начал передавать письма по А-записям. Но лень искать подтверждения.

Ну дык, так оно и есть. Сначала отправляли сразу серверу-адресату, а потом наткнулись на ситуацию "адресат в оффлайне, и чо делать бум?", добавили MXы — "если меня нет, оставляйте письма для меня Максу, я вернусь — он мне передаст."

На самом деле я обычно проверяю SOA, но решил в подробности не вдаваться именно потому, что по стандарту МХ, а использование А это воркэраунд.
Так-то да, но можно жеж проверить и предупредить пользователя о возможной опечатке… Ну т.е. просто warning-ом «Вы возможно очепятались...», без запрещения дальнейшего действа.

Накидал для примера на коленке, кому будет интересно — [github]/.../tcl-test-valid-mail/tcl/check valid email.tcl
(результат исполнения и лог внизу файла).
Большое количество сайтов, где регистрировался, не понимают символа + в адресе, и это меня прям крайне печалит. А ведь он разрешен и более того, крайне удобен. Например user+habr@mail будет приходить к пользователю user, но он сможет выставить фильтр для адресата user+habr, чтобы распределять папки, настраивать уведомления.
Более того, не всегда надо выставлять фильтр. В Cyrus IMAP, если у вас есть пользователь user@domain.com (его INBOX будет user.user@domain.com) и у него есть ящик user.user.sub@domain.com (дочердний sub в INBOX), и у ящика sub стоит ACL anyone p (кому угодно можно постить) или хотя бы p для lmtp-аккаунта, под которым MTA осуществляет доставку почты в Cyrus, то письмо на user+sub@domain.com сразу попадёт в дочерний ящик, без каких-либо дополнительных правил. Если ящик глубже (user.user.sub.another@domain.com), то писать надо на user+sub.another@domain.com. А если создать «ничейный» общий ящик common@domain.com и дать ему ACL anyone p, то можно написать на +common@domain.com и письмо попадёт в этот ящик.

Раузмеется, если MTA настроен на обработку подобных случаев. Postfix умеет: у него есть отдельный конфигурационный параметр «разделитель», который по умолчанию (или рекомендуется, я не помню точно) имеет значение "+", и если это включено, то при проверке существования локального адреса user+sub@domain.com он будет делать запросы и для user@domain.com.
Для себя настроил на своем домене сборку почты для всех неизвестных адресов в ящик spam@domain.ru и радостно регистрируюсь на всех сайтах с почтой вида habr@domain.ru, mailru@domain.ru, etc :)
Такую фичу имеют многие почтовые сервера, но в этом случае конечно нужно иметь свой домен.
Это оказывается очень неудобно, если Вы захотите перенести свою почту на какой-нибудь gmail.
Ну и переносите. У gmail так же можно подключить свой домен. В чём проблема? А можно почту на gmail сделать и сборщики настроить. Не ищите проблемы там где её нет.
Вообще я сначала на gmail почту поднял для организации, а потом оттуда переехал на яндекс. Ноу проблем. Проблема была только в размере архива писем (>50 гигов, а может и больше, уже точно не помню, даты писем с 2002 года и несколько писем ещё старше были)
В ПдД от Яндекса так же можно настроить ящик по умолчанию и в него будут сыпаться все письма, которые не нашли явного получателя.
Меня как-то опечалило, что много сайтов не принимают казалось бы валидный символ минуса/тире если его ставить дважды (user--name@domain.com).

Не связано ли это с тем, что в некоторых вариантах SQL двойной дефис обозначает начало комментария? Соответственно, могут его запрещать просто на всякий случай, для защиты от инъекций.

в некоторых вариантах SQL двойной дефис обозначает начало комментария?
Ну и пусть себе обозначает. Использовать экранирование опасных последовательностей вместо тупого
exec_sql_query("select * from some_table where some_field ='" + $REQUEST['value_key'] + "'")
разработчикам религия запрещает?

Так-то оно так, но попадалась где-то коммерческое программное решение — что-то вроде обратного прокси, кажется — которое пыталось отлавливать "потенциально опасные" в плане инъекций запросы и банило их. Типа "да, ваш бэкенд писали криворукие стажёры, но если вы купите наш продукт, то мы вас спасём от Sql-инъекций, которых у вас наверняка куча".

Уже много было написано статей по этому поводу и лучшая из них была из одной строки: адрес почты проверять не надо.
НЛО прилетело и опубликовало эту надпись здесь
Про валидацию email очень подробно описано описано в книге «Регулярные выражения» Джеффри Фридла www.ozon.ru/context/detail/id/4066500
В качестве приложения приводится выражение, которое проверяет соответствие email RFC, это выражение занимает несколько страниц :)
Не знаю, как у вас, а у нас это не одно регулярное выражение, а много, т.к. у нас емейл активно используется в тех же рассылках, и периодически идут жалобы от людей, которые ввели и @ya.ru и yandex.ru или гмейл пяти видов с точками. Если у вас 1.5 землекопа на сайте, то имеет смысл использовать регулярки согласно rfc, а если сотни тысяч людей, при том многие ждут от вас писем, то вы потонете в bounce и жалобах от невнимательных пользователей.
Всё жду, когда кто-нибудь напишет такую же статью, но с учётом национальных TLD.

Хороший был бы емейл вася@пупкин.рф. Упс, а что делать с кодировкой локальной части?
НЛО прилетело и опубликовало эту надпись здесь
Домены — да. Я говорю про локальную часть адреса («вася» в данном случае). Она не кодируется никаким punycode, и правила обработки определяются исключительно сервером получателя (см. текст статьи).
В локальной части нельзя использовать кириллицу. Только латиница. Поэтому вася@мыло.рф работать сейчас не будет.
Подробности можете в вики посмотреть.
Прямо по вашей же ссылке:
In addition to the above ASCII characters, international characters above U+007F, encoded as UTF-8, are permitted by RFC 6531


Может это мне приснилось, но раньше (до RFC 6531) не было требования UTF-8. Просто не было. Было можно что угодно, за небольшим исключением, и всё. А как это понимать, решает получатель.
А, да. Действительно. Всё уже поменялось с тех пор, как я туда заглядывал в последний раз.
Спасибо за подсказку.
↑↑↑↑↑↑↑↑
И вот здесь, уважаемые коллеги, мы собственными глазами наблюдаем очередное подтверждние тезиса автора статьи о том, что чукчи программисты — не читатели.
не совсем так. программисту ставят задачу -> он прочел RFC -> заимплеменил -> RFC поменяли -> программист не в курсе
Ой расскажите это Rit Labs. Наверное, ни один почтовый RFC ни в одной редакции не заимплементили правильно в The Bat.

Вот уж точно не читатели.
P.S. Если автор использует .NET то зачем регулярные выражения? Почему бы не использовать встроенные средства для валидации? К примеру вот.
там кстати внутри этого атрибута регулярное выражение интересное очень. то что в статье по сравнению с этим выглядит как то бледновато:

^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$
Какое там!
У меня в адресе на GMail есть точка. Когда я её регистрировал там в качестве примера имени ящика был ящик вида name.surname@gmail.com.

Знаете, кто меня не пустил регистрироваться с таким адресом? Foursquare! Пришлось пользоваться тем фактом, что точка в имени e-mail игнорируется и писать тот же адрес без точки.
Игнорирутся Gmail-ом. А другими, вообще говоря, не игнорируется. Я тут выше упоминал Cyrus IMAP, там в именах ящиков точка — недопустимый символ (в конфигурации по умолчанию).

У меня Яндекс с точкой, интересно что кроме точки я могу использовать дефис. Итого в Яндексе количество почтовых адресов увеличилось вдвое.

Я знаю: в адресе должен быть хотя бы один символ @ и хотя бы по одному байту до и после.

через которое они все прошли бы. Вот оно.

Коротенькое уж больно. Читайте RFC дальше. filter_var из PHP в исходнике регулярку за килобайт размером имеет.
github.com/php/php-src/blob/PHP-7.0.2/ext/filter/logical_filters.c#L575
Кстати, в комментариях в коду есть ответ на популярный вопрос «какого размера делать поле в БД»: 320 байт. согласно RFC 2821.
НЛО прилетело и опубликовало эту надпись здесь
О как, спасибо. Да, я не нашёл времени прочитать все rfc посвящённые почте, только некоторые =)
tools.ietf.org/html/rfc5321#section-4.5.3
The maximum total length of a user name or other local-part is 64 octets.
The maximum total length of a domain name or number is 255 octets.

Вот они, исходные 320 байт

Но сверху ограничивает RFC 2821, который принимает только 254 октета.
В таком случае вы, уверен, будете меня рады видеть на своем проекте с е-мейл адресом — @@@

Или, как вариант, с —
<lets make some SQL inj magic>@<lets make some SQL inj magic>
Конечно буду рад! Вы ведь сможете подтвердить адрес?
На сколько мне известно, в interanet вы можете настроить email и без домена. Отправлять тупо по имени.
Вы хотели сказать, в рамках одного хоста.
Не изменяет моего предложения. Я же не говорю как, говорю, что " в intranet можете настроить". С использованием default host/domain на mail server.
В Вашем предложении использован несуществующий термин «interanet», поэтому я уточнил.
Опечатка, да.
RFC822? Регуляркой?
Есть такая
(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
 \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
 \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
 \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)
(взято здесь)
Странно, что ни автор статьи, ни предыдущие комментаторы не стали гуглить готовые решения. Двухстрочечный регексп автора вызывает улыбку.
НЛО прилетело и опубликовало эту надпись здесь
… и мы сразу получаем кучу сайтов, которые не позволяют ввести валидные email?
НЛО прилетело и опубликовало эту надпись здесь
Где-то читал небезынтересную статью на тему этой проверки. Автор приходил к выводу, что проверить регуляркой на полное соответствие c RFC невозможно, и надо проверять конечным автоматом. Проверка конечным автоматом дает еще такой бонус, что можно пользователю выводить осмысленные ошибки.

Конечно, если речь о лендингах и конверсии, такие заморочки не нужны. Но ведь есть места, где нужна защита от дурака.
А что, в принципе можно доказать теорему, что граматика адреса — сложнее, чем регулярная, определить место в иерархии (по Хомскому) и успокоиться с проверкой емейлов регулярками :)
Нет, успокоиться не удастся.
  1. Конкретные реализации регулярных выражений охватывают больше, чем регулярные грамматики,
  2. На практике можно не рассматривать регулярку как самодостаточный парсер,
  3. Можно построить такое приближение грамматики, которое будет корректно работать в 99.9% случаев, скажем, реализовать вложенность скобок до какого-то уровня N

А вообще, раз есть ограничение на длину адреса, то количество возможных значений конечно, а значит это просто набор константных строк, которые записываются очень длинной регуляркой вида a@a|a@b|a@c|… :)

А вообще, раз есть ограничение на длину адреса, то количество возможных значений конечно, а значит это просто набор константных строк, которые записываются очень длинной регуляркой вида a@a|a@b|a@c|… :)

Очень очень очень длинной регуляркой...
Подключать терабайты кода для проверки регулярки... Тогда уже пилить отдельный сервис с этим терабайтом специально под проверки адресов..

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

Я не прав?
Я в этом плаваю. Но вот HTML регулярками распарсить невозможно, а конечными автоматами — да.
Возможно, это потому что регулярные грамматики мощнее, чем регулярные выражения. Но я тут тоже не уверен.
Вообще-то регулярные грамматики в точности совпадают и с автоматами и с регулярными выражениями. И всё это вместе взятое так и не сможет сказать — у вас в последовательности из всего-навсего двух символов «(» и «)» баланс скобок соблюдён или нет. Какой тут, к бесу, разбор HTMLя или e-mail адресов?
Буду знать.

Не вижу проблем с проверкой на e-mail адрес. Зачем там, например, контекстно-сводобная грамматика?
Вы не поверите :-) Комментарии. В скобочках. В которых, вы не поверите, могут быть комментарии. В скобочках. Дальше — смотри про разбор баланса скобок с помощью регулярок.
На распарсите вы HTML ни регулярками, ни конечными автоматами. Теорема Клини, однако. Памяти нет. Проверьте хотя бы скобочный баланс регуляркой или конечным автоматом — а я над вами посмеюсь.
Очень может быть. Тем не менее, браузеры как-то парсят HTML. Как они это делают?
НЛО прилетело и опубликовало эту надпись здесь
Там написано «state machine».
Конечный автомат плюс бесконечная лента — это «машина Тьюринга», вообще-то. При желании ленту можно заменить счётчиками (минимум двумя, если ничего не путаю). Главное — в системе должно быть что-то потенциально бесконечное. Без этого — никак.
А если оно не потенциально бесконечное — то это линейно-ограниченный автомат. Тоже образует подкласс языков.
Это только токенизация. Разумеется, токенизация доступна коенчному автомату.
HTML парсится на МП-автомате.
HTML парсится массой разных вещей. Но все эти вещи имеют имеют обну общую особенность: они все могут эмулировать машину Тьюринга, а значит могут реализовать все алгоритмы без исключения. МП-автомат — да, годится.
Не обязательно. МП-автомат не может эмулировать машину Тьюринга, он образует свой подкласс языков (и почти все практически интересные языки в него входят).
Oops. Да, простите, перепутал. Да, МП-автоматы «не умеют» машину Тьюринга. Редкий случай чего-то практически полезного между «конечными автоматами» и машиной Тьюринга…
В смысле «редкий»? На практике есть КА, МПА и различная экзотика. А над всем этим стоит машина Тьюринга, которая, вообще говоря, тоже экзотика, но важная в теоретическом отношении.
С смысле «практически редкий». Как правило всякие примочки (типа языка BPF) стартуют с чего-то, что может обработать конечный автомат, потом их делают «немного мощнее», потом ещё, и почти всегда когда происходит выход за пределы конечных автоматов выясняется что у нас в руках — уже нечто полное по Тьюрингу (с «проблемой остановки» и прочими прелестями).

Игра Жизнь полна по Тьюрингу, к примеру :-) Что как бы сходу ни разу не очевидно…
Как правило, язык токенизируется КА, а затем разбирается в структуру МПА. Крайне редко встречается такой язык, который невозможно было транслировать МПА. А учитывая, что МПА относительно легко разрабатывать — это очень популярный класс трансляторов, внутри которого есть уже много подклассов, отличающихся логикой работы со стеком.
Проверьте хотя бы скобочный баланс регуляркой или конечным автоматом — а я над вами посмеюсь.

(([^()]|\((?1)\))*)

Смейтесь на здоровье. С PCRE нам даже КС не страшны:
boost::regex re("(?(DEFINE)"
  "(?<symbol>[^()])"
  "(?<expr>((?&symbol)|\\((?&expr)\\))*)"
")"
"^(?&expr)$");
Хотел упомянуть про то, кто perlовые регулярные выражения регулярными выражениями, строго говоря, не являются, но потом решил, что тот, кто про это знает понимает так же, о чём я.

А так-то да: PCRE'шные регулярные выражаения это, конечно, умеют, потому что у них есть память (хотя и ограниченное количество памяти, но для скобочек этого хватает, да).
Регулярки мощнее. Вот если не использовать запоминание подстрок и заглядывание вперёд — тогда полностью эквивалентны.
Хорошо. Ну есть такая спецификация. Но вот регистрируюсь я в GMail или подобных системах. Они ведь не пропускают даже нижнее подчеркивание. Либо случай с habrahabr.ru/post/274985/#comment_8736743
Почему так происходит. Или что будет если я на своем домене таки сделаю нетипичный адрес и начну жаловаться на сервисы которые его не пропускают?
У гмыла есть интересный нюанс:

johndoe@gmail.com
john.doe@gmail.com
j.O.h.N.d.O.e@gmail.com
johndoe+sometext@gmail.com

Это всё ещё один ящик. Я часто пользовался комбинацией email+sometext@gmail.com чтобы регистрироваться на разных сервисах, с разными техническими именами ящиков, чтобы потом собирать всю почту в один и рулить фильтрами не по имени отправителя, а по ящику получателя, что ощутимо проще.

Но пару раз столкнулся с тем, что на некоторых сайтах email+sometext зарегистрировать можно, а вот при обращении к нему приходил или invalid email, или полный крах. Пришлось отказаться.
Не дают зарегистрировать такое имя или не дают проходить почте с такими адресами? Это очень разные вещи.
Регулярка у автора смешная получилась, слишком маленькая. Ещё работать и работать над ней! :)
Думаю, я создам email-адрес типа phil.h\@\@ck@haacked.com и начну жаловаться в техподдержку на сайтах, которые требуют ввода email-адреса, но не позволяют мне создать учётную запись с этим адресом. Люблю шалить!

был у меня адрес всецифры@домен — где-то не проходил проверку. жаловался. в ответ игнор. сомневаюсь что шалить будет весело.
У меня было веселее — с год назад в одном магазине не принимали емейл вида vasya@pupkin.name — считали, что TLD не может быть длиннее 3 символов.

(edit: не заметил: следующим комментом ↓ ↓ ↓ коллега аналогичный случай уже отметил )
У меня главный email на домене .email. Встречаюсь достаточно часто с сайтами, которые его не понимают. Видимо ожидают 2 или 3 символа.
а их антиподы видимо ожидают до точки больше символов и ругаются на домен i.ua =)

Я уж молчу о 5.ua
Многие не знают, что такие адреса используются

В свое время взял на заметку с некоего движка: ^([a-z0-9]([\-\_\.]*[a-z0-9])*)+@([a-z0-9]([\-]*[a-z0-9])*\.)+[a-z]{2,6}$
Пока не подводил ). Но, не смею претендовать на его незаменимость.

user@тест.рф = user@xn--e1aybc.xn--p1ai не пройдёт.

Нужно больше символов.
Прочитал RFC — расскажи всем. Впрочем, по тому как пипл хавает, очевидно что читали его немногие.
Вдобавок, текст удобрен знатным количеством петросянства, что не способствует восприятию.
it { is_expected.to allow_value("customer\/department=shipping@example.com").for(:email) }
it { is_expected.to allow_value("!def!xyz%abc@example.com").for(:email) }
it { is_expected.to allow_value("_somename@example.com").for(:email) }

Тесты прошли
Мой валидатор, давно устаревший правда: http://habrahabr.ru/post/175399/
С остальными продолжаю возиться, спасибо за челлендж!
НЛО прилетело и опубликовало эту надпись здесь

Адрес электронной почты имеет вид

[часть1]@[часть2].[часть3]

Из этого (исключим всякую экзотику типа кириллических доменов):

  • [часть1] - произвольный текст, состоящий из латинских букв, цифр, точек, дефисов и поддефисов, начинающийся и заканчивающийся на букву или цифру.

  • [часть2] - произвольный текст, состоящий из латинских букв, цифр, точек и дефисов, содержащий не более одной точки подряд, начинающийся и заканчивающийся на букву или цифру.

  • [часть3] - домен, который просто проверяется по списку.

Осталось только всего ничего: узаконить это Ваше видение. Потому что в стандарте не так. О чём, собственно, и статья.

А почему бы почте не быть на верхнем домене? Корпы сейчас вполне могут купить себе такой если захотят, например vasya@yandex - вполне себе валидно.

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

В общем валидация почты проста: должен быть символ @ между любых иных, всё остальное не имеет значения.:)

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

Публикации