Валидация email

    В этой статье рассмотривается валидация email изпользуя регулярные выражения. Все регэкспы выполняются с модификатором i, т.е. делают регистронезависимую проверку.

    Подготовка


    Перед тем как писать валидацию, надо знать из чего состоит email адрес. Думаю известно всем что это «username@hostname». Лучше всего будет разбить создание регэкспа на 2 логические части — валидация hostname и валидация username. Начнём с более объёмного.

    Валидация hostname


    Для начала подумаем, а из чего же состоит hostname?

    Имя хоста состоит из нескольких компонентов, разделённых точкой и не превышающих 63 символа, и суффиксов (домены первого уровня). Компоненты, в свою очередь, состоят из латинских букв, цифр и дефисов, причём дефисы не могут быть в начале или в конце компонента. Суффиксы это ограниченный список доменов первого уровня (я нашёл список на сайте IANA). Для упрощения выражения запишем домены стран как [a-z][a-z] (любые 2 символа от a до z не зависимо от регистра). Так же не будем использовать не латинские символы, пока они официально не введены в публичное пользование. В итоге получим выражение проверяющее суффикс (конструкция (foo|bar) говорит о том что происходит поиск либо foo либо bar, т.е. заменяет или):

    (aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])

    Для компонентов код будет посложнее:

    ([a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)

    Разберём выражение:

    [a-z0-9] # обязательная буква латинского алфавита или цифра
    ([-a-z0-9]{0,61}[a-z0-9])? # необязательная часть
    \. # точка


    Рассмотрим необязательную часть:

    # дефис ставиться на первое место в группе символов, иначе он принимается за промежуток
    # {0,61} после группы символов означает, что группа может повторятся от 0 до 61 раза
    [-a-z0-9]{0,61}
    # 61 для того, чтобы в группе не было более 63 символов в сумме
    [a-z0-9]


    В итоге мы получили выражение отвечающее за проверку hostname:

    ([a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*(aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])

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

    Валидация username


    Имя пользователя может в себе содержать:
    • латиницу
    • цифры
    • знаки! # $ % & ' * + — / =? ^ _ ` { | } ~
    • точку, за исключением первого и последнего знака, которая не может повторятся

    Приведу сразу выражение:

    [-a-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*

    На самом деле тут все просто: 1 или более символ [-a-z0-9!#$%&'*+/=?^_`{|}~], далее 0 или больше компонентов \.[-a-z0-9!#$%&'*+/=?^_`{|}~]+.

    В итоге


    Регэксп проверки email:

    ^[-a-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*@([a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*(aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])$

    Это выражение можно каплю оптимизировать (про оптимизацию, я думаю, будет отдельная статья):

    ^[-a-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*(?:aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])$

    Бонус


    Рассмотрим регэксп, который привели в пример в комментарии к вступительному топику:

    ^(\S+)@([a-z0-9-]+)(\.)([a-z]{2,4})(\.?)([a-z]{0,4})+$

    Какие тут есть главные проблемы?
    • Так как username может состоять из любых символов кроме пробелов, username "日本国" является валидным.
    • Домен первого уровня может состоять из любых 4 латинских букв, например .habr
    • Ужасная проверка домена: 1 или более символов, обязательная точка, 2-4 обязательных символа, необязательная точка, 0-4 символа в прибавок. Причём каждый из этих блоков сохраняется в память.


    P.S. Пишите о багах и пожеланиях — обязательно исправлю.
    P.P.S. По желанию могу выложить функцию проверки email, используюмую мной.
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 122
    • +4
      При проверке хоста скоро нужно будет учитывать вот это:
      http://www.icann.org/en/announcements/announcement-4-26jun08-en.htm
      • +28
        а если завтра введут новый домен, переделывать все рэги?)
        • 0
          и в чем я не прав?
          • –2
            а если завтра ввдеуть новый язык разметки, переделывать все сайты?
            • +2
              в данном случае надо всего лишь универсальное крепление для колеса добавить, а не переделывать машину заново.
              • НЛО прилетело и опубликовало эту надпись здесь
          • +22
            Изобретаете лисапед уважаемый.

            Вот кстати самая надёжная
            Ну а для php > 5.2 вот это:

            filter_var($mail, FILTER_VALIDATE_EMAIL)

            • +1
              Сагалаев на этот счёт писал, что и от правильной RFC-шной валидации толку немного. Во-первых, потому что не все почтовые серверы так требовательны, и существуют емэйлы, не соответствующие RFC, и вполне валидные. Во-вторых, обратное: не все RFC-валидные емэйлы существуют на самом деле. В-третьих, если они существуют, не факт, что их кто-то читает. И если читает, то не факт, что понимает :)

              Ссылка.
              • +1
                Да, но сужать область валидных e-mail-ов по сравнению с определенной в RFC просто не прилично, на мой взгляд.

                (пользуясь случаем, посылаю еще один луч ненависти тем, кто «+» в username не разрешает)
                • 0
                  Луч ваш поймал, спасибо. Плюс разрешать всё равно не буду :-)
                  • 0
                    Чёрт, проверил только что — а ведь плюсик-то разрешён :-) Я и забыл — давно дело было. Луч возвращаю.
                • 0
                  а вот из Django: code.djangoproject.com/browser/django/trunk/django/forms/fields.py#L422

                  email_re = re.compile(
                      r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
                      r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
                      r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
                  
                  • +3
                    во второй строчке на меня подозрительно хмурятся два смайлика…
                • 0
                  Валиден ли следующий email (не по RFC, а в реальности): ----@----.----
                  • –2
                    В домене нельзя больше 2 "-" подряд.
                    • 0
                      Вот вот, а «самый надежный» регэксп, написаный по RFC, это допускает.
                      • +7
                        • +4
                          Гм, не знал.
                          Сорри за общественную дезинформацию.
                          • 0
                            а теперь все правильно — хром блокирует с ошибкой DNS_PROBE_FINISHED_NXDOMAIN.
                        • 0
                          а как же punnycode, например xn--suz.net?
                          • +1
                            Поэтому я и сказал — больше 2.
                            В punycode — ровно два.
                          • 0
                            не, это можно, но нельзя начинать имя с минуса
                        • +1
                          Это уже не регэксп, а матрица какая-то о__О
                          • +1
                            О, спасибо за filter_var()!
                            • НЛО прилетело и опубликовало эту надпись здесь
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • 0
                                Вы считали не правильно. 63 — длинна одного «куска» домена от точки до точки, весь домен может быть длинной 255 символов (с точками, iirc).
                                • НЛО прилетело и опубликовало эту надпись здесь
                                • 0
                                  Я делаю проверку вне регэкспа.
                                • –4
                                  А где проверка существования домена второго и последующих уровней? А иначе какой смысл проверять домены первого уровня?
                                  • 0
                                    Хм. Это проверятся контрольным email'ом по адресу.
                                  • 0
                                    в копилку вариантов:
                                    /\\A(?:^([a-z0-9][a-z0-9_\\-\\.\\+]*)@([a-z0-9][a-z0-9\\.\\-]{0,63}\\.([a-z]{2,4}))$)\\z/i
                                    • +1
                                      Я понял что нельзя затрагивать столь спорную тему. Даже для попытки обучения. :)

                                      В следующий раз возьмем тему нейтральнее.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                        • 0
                                          А как же IDN?
                                          • –1
                                            ну и еще вариант: /^[0-9a-z]([\.-]?\w+)*@[0-9a-z]([\.-]?[0-9a-z])*(\.[0-9a-z]{2,4})+$/
                                            • 0
                                              Пример не рабочий в валидации hostname у вас…
                                              • 0
                                                Пожалуйста, объясните.
                                                • 0
                                                  Нажмите на ссылку «Пример» и сами все уведите ;)
                                                  • 0
                                                    Странно все это. В firefox меня редиректит на ai.com, а ie не открывает вообще.
                                                    Вообщем об этом я узнал в книге, посмотрел в firefox и подумал что так должно быть.
                                                    • 0
                                                      Чтобы зайти, надо писать «ai.»
                                                      Запись у корневого домена действительно есть:
                                                      [borisko@vaiofw ~]$ whois -h whois.iana.org ai
                                                      [Querying whois.iana.org]
                                                      [whois.iana.org]

                                                      IANA Whois Service
                                                      Domain: ai
                                                      ID: ai
                                                      [skip]
                                                      Nameserver Information:
                                                      Nameserver: ns1.pair.com.
                                                      IP Address: 209.68.1.11
                                                      Nameserver: ns2.offshore.ai.
                                                      IP Address: 208.75.85.241
                                                      Nameserver: whois.ai.
                                                      IP Address: 209.59.119.1

                                                      Registration Date: 16-February-1995
                                                      Last Updated Date: 21-November-2007
                                                      [borisko@vaiofw ~]$ dig @209.68.1.11 ai A
                                                      [skip]
                                                      ;; ANSWER SECTION:
                                                      ai. 14400 IN A 209.59.119.34
                                                      [skip]
                                                      [borisko@vaiofw ~]$
                                                      • 0
                                                        Спасибо, исправил. А если на этом домене есть мыло, отправляться должно тоже с точкой?
                                                        • 0
                                                          Мыло на нем тоже есть %)
                                                          [borisko@vaiofw ~]$ dig @209.68.1.11 ai MX
                                                          [skip]
                                                          ;; QUESTION SECTION:
                                                          ;ai.                            IN      MX
                                                          
                                                          ;; ANSWER SECTION:
                                                          ai.                     14400   IN      MX      10 mail.offshore.ai.
                                                          [skip]
                                                          [borisko@vaiofw ~]$ 
                                                          

                                                          Думаю, да.
                                                          Хотя exim у меня не отправил ни с точкой, ни без.
                                              • –1
                                                ну в принципе уже обсуждаемое:
                                                "/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,4})(\]?)$/"
                                                • +1
                                                  Вариант валидации email из CakePHP:
                                                  "/^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2,4}|museum|travel)$/i"
                                                  • 0
                                                    интересно, а если админ сайта захочет найти частичным совпадением в базе мыло, которое содержит %? =)
                                                  • +5
                                                    Я бы не советовал с фанатизмом подходить к вопросу проверки email'ов. Когда я ее использую, то ставлю цель формально проверить, что пользователь не ввел чепухи, а так же, чтобы он сам не ошибился, забыв собаку или точку. Если так хочется убедиться, что адрес существующий, лучше ввести подтверждение по почте, чем городить трехэтажные конструкции из регулярных выражений.
                                                  • +4
                                                    думал зачем поднимается подобная тема, в гугле можно найти десяток вариаций на эту тему.
                                                    но даже такого ужоса не ожидал.
                                                    вот какой смысл проверять домены первого уровня более двух символов, если при этом условие для двухбуквенных позволит ввести некоректную страну?
                                                    ну и очень актуальная проблема, что для внутрикорпоративного использования не подходит: manager1@callcenter.server
                                                    • +1
                                                      Вот-вот. Это не говоря про адреса вроде username@localhost или username@192.168.1.2 — такие вообще почти никогда не валидируются.
                                                      • 0
                                                        Спустя три года всё же уточню, на случай, если кому-то интересно. Для того, чтобы указать, что письмо надо отправить на сервер по IP-адресу (а не по hostname), IP-адрес необходимо поместить в квадратные скобки, то есть:

                                                        username@[192.168.1.2]

                                                        Теоретически, RFC1123 позволяет сегментам имени узла начинаться с цифры (а не только с буквы), поэтому адрес без квадратных скобок может быть интерпретирован как имя узла.

                                                        Кстати, в Википедии можно найти ещё много интересных вариантов необычных (но корректных) email-адресов. Бо́льшая часть регулярных выражений, кстати, не принимает многие из них за корректные. И наоборот — ниже приводятся некорректные адреса, и, опять же, многие из них обычно проходят валидацию.
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                    • +1
                                                      Не раз обсуждалось.
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                    • –1
                                                      Вот regexp из довольно старой, но хорошей книги «Профессиональное PHP программирование»:
                                                      ^[_\-\.0-9a-z]+"([0-9a-z][_0-9a-z\.]+)\.([a-z]{2,4}$)
                                                      Суть такова:
                                                      Имя ящика начинается с одного или нескольких буквенно-цифровых символов, за которыми следует @. Допустимы также точка, подчеркивание и дефис.
                                                      Имя хоста содержит одну или более точек и оканчивается строкой длины от 2 до 4 символов.

                                                      В вашем примере вижу большой минус в том что ограничение по доменам очень сложно поддерживать. Невозможно регулярно ходить и проверять список доменов первого уровня. Да и не нужно это, фильтр по домену лишний.
                                                      • 0
                                                        Правда вариант из книги устарел, т.к. есть домены аля travel
                                                        • 0
                                                          Впринципе да, для простой проверки ошибок в адресе сойдет. А подделать не составит труда.

                                                          Я, впрочем, просто хотел немного разжевать.
                                                        • +1
                                                          а как же .museum и .travel?
                                                          Мне кажется, проверка tld все равно нужна жесткая. Не так часто они и добавляются.
                                                          • +1
                                                            Ну, есть понятие ошибок первого и второго рода.
                                                            В данном случае, случайно не пропустить куда болезненнее, чем случайно пропустить неправильное. Поэтому жесткая проверка tld таит в себе немало проблем.
                                                        • 0
                                                          Домен первого уровня может состоять из любых 4 латинских букв, например .habr

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

                                                          Как сказали выше, глупо перечислять все доменные зоны из более чем трех символов. Достаточно [a-z]{2,6}. А учитывая регистрацию доменов первого уровня, ваши регекспы можно просто выкинуть.

                                                          Ну и наконец, информации об этом настолько много, что ваши «статьи» — надоедливое переливание из пустого в порожнее.
                                                          • +1
                                                            Абсолютно согласен. Я изредка вспоминаю про свой блог и знаю, что писать про то, что уже написано, нельзя. Взяли давно изжеваную тему. Не ново, совсем не ново…
                                                          • –1
                                                            Имя пользователя может в себе содержать:

                                                            * латиницу
                                                            * цифры
                                                            * знаки! # $ % & ' * + — / =? ^ _ ` { | } ~

                                                            что курит афтар, вставляя всё это (и кавычки!!!) в имена юзеров?
                                                            • +1
                                                              Я курил вот это.
                                                              • –3
                                                                «Ваш мозг сделан по стандарту» (с)
                                                                очень интересно посмотреть на то, как вы в базе будете хранить юзернейм с кавычкой и к какой магии прибегните, чтобы юзер мог нормально функционировать ;)
                                                                • 0
                                                                  Какие, если не секрет, проблемы в том, чтобы хранить кавычки в базе?
                                                                  • 0
                                                                    Вы что! Это же страшная тайна профессиональных php-программистов! :)
                                                              • 0
                                                                а ещё если вы внимательно посмотрите свою ссылку, то увидите:

                                                                RFC invalid e-mail addresses

                                                                * Abc.example.com (character @ is missing)
                                                                * Abc.@example.com (character dot(.) is last in local part)
                                                                * Abc..123@example.com (character dot(.) is double)
                                                                * A@b@c@example.com (only one @ is allowed outside quotations marks)
                                                                * ()[]\;:,@example.com (none of the characters before the @ in this example, are allowed outside quotation marks)

                                                                вообще создается впечатление, что вы никогда систем регистрации не делали =)))
                                                                • –4
                                                                  а ну да. подходит, сорри =)

                                                                  но все равно "!#$%&'*+/=?^_`{|}~" и прочий бред в мыле не должен быть, просто следуя здравому смыслу.
                                                                  • 0
                                                                    Тут все противоречиво. Одни говорят RFC и все дела, другие твердаят про здравый смысл.
                                                            • 0
                                                              Господа, а как же IDN?

                                                              Я бы понимал \w, но уж никак не [a-z].
                                                              • 0
                                                                Вообще-то, local part может даже символ 0 (\0) содержать, а доменная часть — -путевой адрес через восклицательные знаки… Учим мат-часть (RFC).
                                                                • +4
                                                                  Mail::RFC822::Address: regexp-based address validation
                                                                  www.ex-parrot.com/~pdw/Mail-RFC822-Address.html
                                                                  • +2
                                                                    Вот и баг. Хабр ссылки не корректно определяет, разработчики не учили мат часть.
                                                                    • 0
                                                                      Мне этот регэксп будет сниться.
                                                                    • 0
                                                                      У меня как-то юзер на сайте зарегистрировался с таким адресом (имя я изменил):
                                                                      www.vasya@meil.ru

                                                                      Вообще, несколько раз ввв приделывали в начале.
                                                                      • 0
                                                                        А что, такие e-mail вполне могут быть валидны.
                                                                        • 0
                                                                          Могут быть, да. Но не валидны :-)

                                                                          А потом такие юзеры жалуются, что им не приходит письмо с ключом авторизации.
                                                                          • 0
                                                                            У меня был юзер с mail.ru и с www. вначале. Без ошибки.

                                                                            Однако да, обычно что только народ не пытается в поле адреса писать…
                                                                        • 0
                                                                          оу меня тоже пачка таких, причем все с www именно на mail.ru лол
                                                                          • 0
                                                                            Ха! У меня отдельные личности не различают пароль на VKontakte и на корпоративный прокси-сервер. Тут уж только лоботомия, боюсь, поможет, regexp'ы бессильны.
                                                                        • 0
                                                                          бредово как-то проверять имейлы именно...\
                                                                          лучше ипишники откуда коннектятся, имо.\
                                                                          я делаю так, и результаты более чем
                                                                          • 0
                                                                            Я туплю, или в списке доменов нет «ru»?
                                                                          • 0
                                                                            > точку, за исключением первого и последнего знака, которая не может повторятся
                                                                            эээээттооо еще как — не может повторяться?
                                                                            you.will.be@satisfied.org.ua — две точки.

                                                                            upd. или вы имеете в виду отсутствие двух точек подряд?..
                                                                            • 0
                                                                              test@mail.com проходит всегда :)
                                                                              • 0
                                                                                fuck@the.usa обычно тоже :)

                                                                                И таких е-мейлов масса.
                                                                                • 0
                                                                                  Слышал существует возможность проверки имейла на сучествование на сервере.

                                                                                  Кто ни будь сталкивался?
                                                                                  • 0
                                                                                    Я сталкивался и даже делал. Есть одна, а точнее 3 больших проблемы:

                                                                                    1) SMTP Delay;
                                                                                    2) Greylisting;
                                                                                    3) Корпоративные релеи, которые едят всю почту на любой логин;

                                                                                    В общем, кровь портит борьба со спамом.

                                                                                    Поэтому у себя ограничился проверкой наличия mx-записи у введеного домена. При отсутствии, соответственно отлуп. Это кстати, тоже противоречит RFC ибо при отсутствии mx по RFC почта должна уходить куда-то на A-запись.
                                                                                    • 0
                                                                                      Благадарю примим к сведению.
                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • +1
                                                                                    search.cpan.org/~pdwarren/Mail-RFC822-Address-0.3/Address.pm

                                                                                    Mail::RFC822::Address: regexp-based address validation

                                                                                    This regular expression will only validate addresses that have had any comments stripped and replaced with whitespace (this is done by the module).

                                                                                    (?:(?:\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*)
                                                                                    


                                                                                  • 0
                                                                                    Мои скромные 5 копеек — список расширений доменов неплохо бы проверять точнее.
                                                                                    В Вашем варианте мейл cool_hacker_will@fool.yo будет валидным.
                                                                                    • 0
                                                                                      А список доменов буде выглядеть так:
                                                                                      aero|biz|com|coop|edu|eu|gov|info|int|mil|museum|name|net|org|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw
                                                                                      • 0
                                                                                        Я убедился, что достаточно проверить на @ и точку.
                                                                                        • 0
                                                                                          не заметил в этом списке домена рф
                                                                                      • 0
                                                                                        sorry за некропост, но что касается доменов, то вот оно и пришло: www.iana.org/domains/root/db
                                                                                        gTLD, господа :)
                                                                                        • 0
                                                                                          Суффикс предлагаю записать так: [a-zа-я]{2,}

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