Что, если бы я попросил вас написать регулярку для проверки e-mail адреса? Вы бы, наверное, подумали минутку, и потом бы нагуглили запрос. И получили бы нечто вроде:

^([a-zA-Z0-9_-.]+)@([a-zA-Z0-9_-.]+).([a-zA-Z]{2,5})$


Регулярок на эту тему существуют тысячи. Но почему? Наверняка же кто-нибудь, да прочёл стандарт 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*)



И даже этот монстр не в силах проверить емейл-адрес. Почему? Оказывается, в скромном адресе может скрываться очень многое. Некоторые части стандарта RFC822 достаточно полезны, а некоторые – просто безумны. Но в любом случае это интересно – давайте разбираться.

Плюс-адреса


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

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

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

Когда ломается регулярка


#!$%&'*+-/=?^_`{}|~@example.org


Немногие знают, что вышеприведённый адрес абсолютно допустим – все символы можно использовать в локальной части (до символа @). Более того, локальная часть может содержать даже символ @, если заключить её в двойные кавычки. Например:

"dream.within@a.dream"@inception.movie
bob."@".smith@mywebsite.com


А теперь – карнавал безумия


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

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

(here)a@b.com
a(here)@b.com
a@(here)b.com
a@b.com(here)


Все варианты семантически идентичны. Они работают, как и плюс-адреса – просто добавляют некий визуальный шум. Все письма должны будут прийти на a@b.com

Если что-то достойно старания, то ради него можно и перестараться
Айн Рэнд, она же Алиса Зиновьевна Розенбаум


Добавим ещё немного безумия


Комментарии могут быть вложенными:

(here(is(some)crazy)comments)a@b.com




Если вы пробовали парсить рекурсивные выражения, вы знаете, что это очень сложно. А теперь вспомните монстра из начала статьи, чтобы ваш мозг взорвался.

Несмотря на RFC822, мы лучше согласимся, что использовать простые и запоминающиеся емейл-адреса – это правильный выбор. Может, мы найдём лучшее применение всем этим удивительным возможностям – а пока что пишите мне на адрес

elliotchance+blog(silvrback)@gmail.com


P.S. Надеюсь, что спам-боты не догадаются, что это емейл-адрес.

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


  1. grossws
    04.04.2016 00:49
    +2

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

    Это справедливо для gmail'а, где плюс интерпретируется именно так. А вообще local part — opaque, т. е. промежуточные MTA не должны делать каких-либо предположений о его структуре. Тот же ezmlm использует dash в качестве спец-разделителя.


    1. grossws
      04.04.2016 00:50
      -11

      В общем, спрячьте этот "ниочём", не позорьтесь.


    1. grossws
      04.04.2016 10:45
      +17

      Кто не верит — достаточно заглянуть в стандарт 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
      .

      Ещё см. ниже.


    1. Wesha
      04.04.2016 19:10
      +4

      Совершенно верно. Стандартом прямо запрещено трогать локальную часть:

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

      То есть адрес надо разбирать с конца, и не трогать ничего левее первой встреченной "@".


  1. dkukushkin
    04.04.2016 00:49
    -5

    На ваш адрес Gmail пишет: "Адрес elliotchance+blog в поле Кому не распознан. Проверьте правильность ввода всех адресов."
    Получается все-таки нужно проверять email-адрес. Ведь даже если он валиден по RFC822, ваш SMTP-клиент может его не признать.


  1. Zavtramen
    04.04.2016 00:52
    +7

    И не забываем национальные алфавиты в доменах.


    1. YaakovTooth
      04.04.2016 08:22
      -12

      Забываем сразу, потому что наплевать.


  1. Londoner
    04.04.2016 01:10
    +3

    А что мешает спамерам автоматически убирать из мейлов всё что между плюсиком и собачкой?


    1. grossws
      04.04.2016 01:12
      -1

      Может то, что на серверах кроме gmail'а это будут разные адреса, если не делать специальной обработки?


      1. Londoner
        04.04.2016 09:29

        Пример такого несоответствия можете привести? А коли и так, то хотя бы и для gmail'а...


        1. grossws
          04.04.2016 10:36
          +8

          Достаточно заглянуть в стандарт 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.


    1. cratu
      05.04.2016 13:51

      А зачем? Массово данную возможность не используют, тем более не везде она работает одинаково. Вот если накопится критическая масса адресов — тогда и будут учитывать, а пока зачем напрягаться?


  1. kloppspb
    04.04.2016 01:45
    +25

    Может ещё древнюю статью Касперски из «Хакера» сюда вытащим? А то недостаточно некрофилии.


  1. rPman
    04.04.2016 02:17
    +1

    Вы можете сказать, в какой ситуации необходима поддержка полного RFC для почтовых адресов?
    Я вижу только одно место, где нужно хотя бы об этом помнить но уж точно не проверять — парсинг писем, чтобы не получить какую-нибудь sql-инъекцию внутри комментария.
    p.s. если пользователь сделал что то странное, что придумали люди из далеких 90-ых, не со зла а просто они были первопроходцами, то он сам себе доктор.


    1. grossws
      04.04.2016 10:40
      +3

      Вы можете сказать, в какой ситуации необходима поддержка полного RFC для почтовых адресов?

      При написании MTA/MDA, очевидно ,)


      1. EvilPartisan
        04.04.2016 13:02
        -1

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


        1. grossws
          04.04.2016 16:08
          +1

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

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

          Когда ты отправляешь письмо, оно проходит через два сервера.

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


        1. Wesha
          04.04.2016 19:13
          +3

          Полностью поддерживать стандарт просто ради того чтобы его поддерживать бессмысленно

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

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

          Стандарты вообще-то для того и пишутся, чтобы поддерживаться до, ёпрст, последней запятой!


          1. EvilPartisan
            04.04.2016 19:38

            I_have(bad)ньюс*for*you@real.world


            1. Wesha
              04.04.2016 19:41

              И где тут проблема? Это валидный адрес.


              1. EvilPartisan
                04.04.2016 19:45
                -2

                Ну и напиши на него что-нибудь, например через гмайл.


                1. Wesha
                  04.04.2016 19:54
                  +5

                  1. Тыкать Вы своим родственникам можете, а на хабре™ вежливые люди™ общаются.
                  2. Какую часть фразы

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

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

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


  1. Gordon01
    04.04.2016 03:40
    +29

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


    1. Frankenstine
      04.04.2016 09:40
      +7

      Ну так год-то уже другой ;)


    1. pletinsky
      04.04.2016 12:47

      Я вот в первый раз это слышу. Было полезно. Жаль так и не было предложено решение.
      То, что невозможно проверить емейл на допустимость с помощью регулярок — это понятно. Но ведь в реальности никому это обычно и не надо.
      Обычно решают проблему как пользователю подсказать, что он напортачил с вводом емейла.
      Самое элементарное решение — проверить наличие символа @. Он то уж точно должен быть.


      1. VolCh
        04.04.2016 13:13

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

        Мне вот непонятно. Множество валидных адресов конечно, а регулярки типа PCRE (вернее их трансляторы) являются конечными автоматами. Почему невозможно на регулярках построить на конечном множестве автомат с двумя состояниями ("валидно" и "невалидно") мне очень непонятно.


        1. pletinsky
          04.04.2016 13:19

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


        1. h0tkey
          04.04.2016 21:19

          Мне кажется, как минимум, потому что в адресах попадаются правильные скобочные последовательности, а они уже не относятся к регулярным языкам. Но это если ограничения на длину нет.


        1. dbanet
          05.04.2016 09:02

          В статье же указана правильная регулярка.


    1. Wesha
      06.04.2016 00:50

      Повторенье — мать питанья ученья!


  1. michael_vostrikov
    04.04.2016 07:08
    +8

    ^(.+)@(.+)\.(.+)$
    Все примеры из статьи проходят. Для задач валидации, когда вместо email написано имя или телефон, этого вполне достаточно.

    Если мы не пишем почтовый сервер, нам неважно, соответствует этот адрес RFC или нет, потому что можно придумать валидный по RFC, но не существующий email-адрес. А если пишем, то скорее всего не будем проверять валидность регуляркой.


    1. koceg
      04.04.2016 08:38
      +1

      Для задач валидации можно и не ловить совпадения: ^.+@.+\..+$


      1. Aingis
        04.04.2016 10:24
        +1

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

        P.S. admin@localhost — тоже валидный адрес и эта регулярка его не словит. Адрес может быть полезен для локального тестирования. Точно так же может быть адрес на национальном домене: info@ru


        1. shir
          04.04.2016 10:26

          Для этого существует подтверждение email'а. Т.е. совсем другая задача которая проверяется независимо от валидации.


          1. Cromathaar
            04.04.2016 10:53

            Удивительно, но факт: многие люди до сих пор часто либо путают эти понятия, либо зачем-то пытаются их совмещать.


          1. Aingis
            05.04.2016 13:06

            Так и представляю себе: с этими словами вы упрощаете проверку адреса до существования «@», куча ошибочно введённых адресов, про которые можно было бы подсказать, что с ними что-то не так, проходят валидацию. На них отправляются письма, и естественно не доходят.

            Конверсия падает, доходы падают, к вам приходят разъярённые (топ-)менеджеры и просят сделать человеческую валидацию. Ну, или дают задание уже вашему преемнику. А всё потому что надо думать о людях в первую очередь, а не умничать.


            1. shir
              06.04.2016 10:19

              Я даже не знаю как прокомментировать тот бред что вы написали полностью все утрировав и проигнорировав все остальные комментарии.


            1. Cryvage
              06.04.2016 13:17

              Я пожалуй соглашусь с вами, при условии, что «более подробная» валидация не будет носить запрещающий характер. Мне очень понравилась ваша фраза «можно было бы подсказать, что с ними что-то не так». Если это будет именно подсказка, что-то в духе «ваш адрес выглядит странно, возможно вы допустили ошибку», и пользователь сможет нажать кнопку «нет, все правильно, это мой адрес», тогда можно сделать проверку на соответствие наиболее распространенным форматам адресов. И это будет действительно полезно и удобно. А вот строго запрещать адреса, не прошедшие валидацию — смысла я не вижу. Если человек не хочет вводить свой адрес, он всегда может ввести корректный с точки зрения стандартов, но несуществующий адрес, или чужой, или свой, но неиспользуемый. И даже без злого умысла, ввел, а потом обнаружилось что пароль от почты забыл. Так что если адрес действительно важен, то в любом случае нужно письмо с подтверждением слать. И периодически, хотя бы раз в полгода, спрашивать у пользователя, не изменился ли его адрес.
              Ну и если уж речь зашла про конверсию, нужно учитывать, что сейчас многие люди вообще почтой не пользуются по назначению, и ящики заводят только для регистраций, потому что большинство сайтов требует почту. Человек конечно зайдет в почту, если ему надо восстановить пароль, но если вы хотите, чтобы пользователь оперативно получал ваши сообщения, надо просить у человека не мыло, а то, чем он активно пользуется: телефон, facebook, WhatsApp, Viber и т.д… Все, чем он согласится поделиться. Ситуацию с почтой сейчас только Google вытягивает, привязывая почту к Android аккаунту. Если у человека почта gmail и Adroid, то письма он хотя бы на мобильнике увидит. Если же он вам не gmail'овсую почту дал, то, с высокой вероятностью, он ее проверяет. только когда ждет очередного письма с подтверждением регистрации.


      1. Cryvage
        05.04.2016 13:51

        Лично я даже наличие точки проверять бы не стал. Если домен внутренний, точек у него может и не быть. Что-то типа: «ivanov_vv@rogaikopyta».
        Если же по какой-то причине действительно нужно проверить соответствие адреса стандарту RFC, например вы пишете программу, которая проверяет адрес на соответствие этому стандарту, то пытаться сделать полную проверку с помощью регулярного выражения это как-то странно. Особенно если это выражение принимает такой монструозный вид, как пример из статьи. Даже если это регулярное выражение будет работать правильно, лучше от него отказаться и написать обычную процедуру. Нет, ну серьезно, вы только представьте, что у вас обнаружился баг и вы подозреваете, что проблема в регулярном выражении. И вот вам надо найти в нем ошибку. Сколько часов это займет?
        Касаемо стандарта, из всего что описано в статье, плюсик кажется более-менее полезным. Хотя я бы эту задачу решил подключением нескольких разных адресов к одному почтовому клиенту. Или настроив перенаправление. Тогда тот, кому я дал свой рабочий адрес будет знать только его. Если же написать «vasyapupkin+work@example.com», то любой догадается что отбросив "+work" можно послать Васе письмо на основной ящик. А уж комментарии в адресе вообще не понятно зачем нужны. Если они никак не влияют на то, куда будет доставлена почта, то значит они и частью адреса, по сути, не являются. Если адреса «vasyapupkin(1)@example.com» и «vasyapupkin(2)@example.com» указывают на один и тот же ящик, то можно просто удалить все что находится в скобках. Вообще, давно пора написать новый стандарт, включив в него то, что реально используется на практике и отбросив все лишнее. И уже его дальше продвигать и поддерживать. К тому же, у меня есть подозрение, что полная поддержка стандарта RFC822 никогда и никем так и не была реализована. Поправьте, если я ошибаюсь.


        1. VolCh
          06.04.2016 11:40

          Даже если это регулярное выражение будет работать правильно, лучше от него отказаться и написать обычную процедуру. Нет, ну серьезно, вы только представьте, что у вас обнаружился баг и вы подозреваете, что проблема в регулярном выражении. И вот вам надо найти в нем ошибку. Сколько часов это займет?


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


          1. Cryvage
            06.04.2016 12:23

            Ну, как вариант, конечно. Но это если изначально вы «стащили» откуда-то готовую регулярку. Или она досталась вам по наследству. А так, зачем изначально ее писать, если в итоге получается write-only код? То есть в случае необходимости изменения регулярки мы ее полностью выкидываем и пишем вместо нее процедуру, или другую регулярку. А если бы изначально была обычная понятная процедура, то мы бы могли ее не с нуля переписывать, а найти и исправить то место, которое не соответствует нашим требованиям.
            З.Ы. Я не говорю, что вообще не надо использовать регулярные выражения. Просто, по моему мнению, в силу особенностей синтаксиса они не предназначены для реализации в одном регулярном выражении большой и сложной логики. Они должны оставаться маленькими и простыми. А для реализации более сложной логики можно комбинировать несколько регулярных выражений. То есть пишем процедуру, в которой часть обработки делаем через последовательное применение нескольких регулярок, а часть, возможно и с помощью иных строковых функций. Возьмем тот же пример со скобочками в адресе. Как верно подмечено в статье, в регулярках разбирать рекурсивные выражения довольно сложно. Но в данном случае нам достаточно прогнать строку по символам в цикле один раз, походу считая количество открывающих и закрывающих скобок, и как только количество закрывающих скобок совпало с количеством открывающих — закрылась самая внешняя скобка, удаляем все между этими скобками и так далее до конца строки. А потом получившуюся очищенную строку можно уже скормить регулярному выражению. Код получается простейший, его даже студент сможет понять и поддерживать.


            1. grossws
              06.04.2016 13:10

              Так вы постепенно напишите полноценный парсер. Не проще ли сразу взять грамматику из rfc и сгенерировать его? В смысле поддержки оно куда гуманнее будет.


              1. Cryvage
                06.04.2016 14:03

                Если вы про пример со скобками в адресе, то это всего лишь частный случай. Я просто описал на этом примере свой подход к работе с регулярными выражениями. Иногда, дописав пару строк кода на императивном языке, можно на порядок упростить регулярное выражение. То есть речь тут уже не столько об e-mail адресах, сколько о регулярных выражениях.


    1. shir
      04.04.2016 10:25

      А как насчет "test example.com"? (обратите внимание на пробел). Вроде как это не валидный email. При этом довольно распространенная ошибка. Так что как минимум надо делать ^\S+@\S+\.\S+$. Ой Постойте. А как же test@example.com test1@example.com (Не знаю как отобразится, но между двумя адресами должен быть перенос сторки). Такой адрес тоже пройдет. Ну тогда надо \A\S+@\S+\.\S+\z. Это кстати не выдуманные, а примеры из жизни.
      Ждем следующие комменты, почему и эта регулярка не подходит.


      1. koceg
        04.04.2016 10:33

        Вы правы, довести проверку до 99.99999% надёжности можно последовательно усложняя регулярку. michael_vostrikov, как мне кажется, говорит о том, что для получения 99% надёжности хватит и простого выражения. А до 100% регулярными выражениями довести не получится никогда.
        Каждый сам для себя должен решить насколько ему нужны эти 0.99999%, сколько труда он готов в них вложить.


        1. shir
          04.04.2016 10:40

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


          1. koceg
            04.04.2016 10:48

            Например пробел внутри адреса достаточно распространенная проблема чтоб все-таки ловить.
            Я вот, честно говоря, в этом не убеждён. Я не утверждаю, что такого никогда не случается, но понятие «достаточно распространённая» слишком уж расплывчатое. Нужно смотреть какую-то реальную статистику.

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


          1. dbanet
            05.04.2016 09:04

            но, как раз в практическом плане, такой адреса будет невалидным
            Казалось бы, человек читал статью…

            Лично знаю человека с почтой на домене `ua`.


            1. shir
              05.04.2016 09:54

              Хм. Не думал что такие существуют. Я знаю что в теории могут быть, но на практике не доводилось встречать.


    1. Veikedo
      05.04.2016 13:51

      Я бы ещё удалили проверку точки в домене.
      test@localhost:7896 не пройдёт


  1. VolCh
    04.04.2016 07:09
    +41

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


  1. LoadRunner
    04.04.2016 08:54
    +1

    Вспомнил этот перевод от Wesha


  1. kvaps
    04.04.2016 10:14

    Это кажется забавным, но абсолютно все приведенные вами e-mail адреса, за исключением elliotchance+blog(silvrback)@gmail.com, проходят проверку с помощью того страшного regexp'а из RFC822, о котором вы писали в начале статьи.
    Попробуйте сами, вот вам пруф.


    1. koceg
      04.04.2016 10:27

      Если вы хотите с автором статьи побеседовать, то вам сюда: https://elliot.land/validating-an-email-address#disqus_thread


      1. kvaps
        04.04.2016 10:44

        Прошу прощения, не заметил что это перевод.
        Но все же, как так?


        1. koceg
          04.04.2016 10:52
          +1

          Ну, а, собственно, что не так-то? Никто же не утверждал, что приведённый в начале статьи монстр бесполезен.
          Но вот такой адрес, например, явно не валиден, но проверку проходит: (here(is(some)crazy)comments))))))))a@b.com.


    1. grossws
      04.04.2016 10:43
      +2

      страшного regexp'а из RFC822

      В rfc822 такого регекспа нет, если что.


  1. koceg
    04.04.2016 10:35
    +1

    Вот бы какую-то реальную статистику увидеть — сколько процентов пользователей имеют такие "нестандартные" адреса.


    1. Athari
      04.04.2016 14:05
      +4

      Такие адреса иметь бесполезно, потому что на каждом сайте своя регулярка, и вам сильно повезёт, даже если банальный "+" примут.


      1. koceg
        04.04.2016 14:13

        О том и речь — если никто этими функциями не пользуется, то какой смысл каждые три месяца мусолить эту тему?
        А, может, окажется наоборот — десятая часть всего интернета не может на Фейсбуке зарегистрироваться, потому что у них email вида #!$%&'"@"*+-/=?^_{}|~+foo@example.org(why(so(serious)))`


    1. LisandreL
      05.04.2016 13:50

      Ну, при регистрации часто получаю отказ, когда пытаюсь задать e-mail с плюсом (типа username+sitename@example.org).


  1. BeLove
    04.04.2016 13:40
    +1

    Каждые полгода на Хабре стабильно появляется статья про регулярки и емейлы.


  1. nikitasius
    04.04.2016 13:58
    -4

    никогда не учитывал мейлы по спецификации.
    mail@example.com и никаких " ' + и прочей ерунды.


  1. Speakus
    04.04.2016 14:10
    +6

    Только тестировщики имеют адреса типа "a@a"@mysite.ru — реальный же человек столкнувшись несовершенством мира (с тем что во многих программах и сайтах такой адрес не получится использовать) заведёт себе адрес нормальный забросив предыдущий.


    1. OlegTar
      04.04.2016 19:39

      Обычно на почтовых сервисах не завести адрес со всякими плюсами. Хотя гугл и позволяет использовать в своем адресе +, как написано в статье, я не уверен, что такой адрес там можно завести.


      1. Speakus
        04.04.2016 21:04

        У 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 Можете проверить ;)


  1. OlegTar
    04.04.2016 16:34
    +3

    Регулярка, за которую я получил 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. maxru
    04.04.2016 16:54

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


    1. OlegTar
      04.04.2016 19:40
      +1

      Вам показалось, оригинальная статья от 1 апреля 2016 года.


  1. Methos
    04.04.2016 17:20
    +10

    Эти статьи каждый год на хабре появляются.
    Самый лучший способ проверить email:

    1. Если есть символ @, то идём на п2
    2. Отправляем email — если дошло, email правилен.

    ВСЁ


  1. ghost404
    04.04.2016 22:46
    +1

    Добавлю свои 5 копеек

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

    Желающие могут полистать RFC4185


    1. Lynn
      05.04.2016 12:45
      +1

      4. Уже давно есть .travel или, например, .moscow, вполне рабочие TLD


    1. IvanGur
      05.04.2016 13:48

      Интернациональные домены переводятся в punycode, а там всё едино.


      1. ghost404
        05.04.2016 18:04
        +3

        Я ожидал этот комментарий. Есть одно но. Мы используем регклярку для проверки email введенного пользователем, а он не будет переводить свой интернациональный email в punycode только чтоб угодить вам


        1. IvanGur
          06.04.2016 22:40

          Верно, но можно привести интернациональный email в punycode и после валидировать по минимуму email. Как вариант, если не обращать внимание на накладные расходы, то проверять используя exim, вроде как опция -bt


  1. alex-khv
    05.04.2016 13:49
    +4

    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


  1. Sergei_77
    05.04.2016 13:49

    Чем больше экспертов изучало, консультировало, разрабатывало, тестировало тем лучше.


  1. tessio
    05.04.2016 13:50
    +1

    Как уже писали на Хабрахабре, лучшая проверка валидности email адреса — просто отправить на него письмо.


  1. ChymeNik
    05.04.2016 13:50

    Зачем делать из мухи слона?
    Если e-mail важен — все равно нужно подтверждение, если нет — пусть вводят что угодно…


  1. zxsanny
    05.04.2016 13:50

    У нас есть традиция — каждый год на хабре кто-то пишет о том, как сложно и почти нереально парсить email хранимками…
    А между тем, проверка проста —

    contains('@') в поле
    Отослать письмо в качестве реальной проверки


  1. phrippy
    05.04.2016 13:51
    -2

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


    1. grossws
      05.04.2016 15:14
      +2

      Стоит понимать, что это относится только к gmail.