Regexp распознавание адреса электронной почты трудно?

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

Кто-нибудь может дать некоторое представление о том, почему это так?

Существуют ли известные и проверенные регулярные выражения, которые действительно делают это полностью?

Какие есть хорошие альтернативы использованию регулярных выражений для сопоставления адресов электронной почты?

19 ответов

Решение

Для формальной спецификации электронной почты, да, это технически невозможно через Regex из-за рекурсии таких вещей, как комментарии (особенно если вы сначала не удаляете комментарии в пробел), а также из-за различных форматов (адрес электронной почты не всегда кто-то@somewhere.tld). Вы можете приблизиться (с некоторыми массивными и непонятными шаблонами Regex), но гораздо лучший способ проверить электронную почту - это сделать очень знакомое рукопожатие:

  • они говорят вам свою электронную почту
  • вы отправляете им по электронной почте ссылку для увлечения с помощью Guid
  • когда они нажимают на ссылку, вы знаете, что:

    1. адрес электронной почты правильный
    2. это существует
    3. им принадлежит

Гораздо лучше, чем слепо принимать адрес электронной почты.

Есть ряд модулей Perl (например), которые делают это. Не пытайтесь написать собственное регулярное выражение для этого. смотреть на

Mail::VRFY будет выполнять синтаксические и сетевые проверки (и SMTP-сервер где-нибудь принимает этот адрес)

https://metacpan.org/pod/Mail::VRFY

RFC::RFC822::Address - парсер адресов электронной почты с рекурсивным спуском.

https://metacpan.org/pod/RFC::RFC822::Address

Mail::RFC822::Address - проверка адреса на основе регулярных выражений, на которую стоит обратить внимание только на безумное регулярное выражение

http://ex-parrot.com/~pdw/Mail-RFC822-Address.html

Подобные инструменты существуют для других языков. Безумное регулярное выражение ниже...

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

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

Если вы хотите убедиться, что адрес действителен, у вас нет выбора, кроме как отправить подтверждение по электронной почте.

Если вы просто хотите быть уверены, что пользователь вводит что-то, похожее на электронное письмо, а не просто как "asdf", то проверьте @. Более сложная проверка на самом деле не дает никакой выгоды.

(Я знаю, что это не отвечает на ваши вопросы, но я думаю, что стоит упомянуть в любом случае)

Сейчас я сопоставил контрольные примеры Кэла Хендерсона, Дейва Чайлда, Фила Хаака, Дуга Ловелла и RFC 3696. Всего 158 тестовых адресов.

Я провел все эти тесты со всеми валидаторами, которые смог найти. Сравнение здесь: http://www.dominicsayers.com/isemail

Я постараюсь обновлять эту страницу по мере того, как люди улучшат свои валидаторы. Спасибо Кэлу, Дейву и Филу за помощь и сотрудничество в составлении этих тестов и конструктивную критику моего собственного валидатора.

Люди должны знать об ошибках в RFC 3696 в частности. Три из канонических примеров на самом деле являются недействительными адресами. И максимальная длина адреса составляет 254 или 256 символов, а не 320.

В BNF существует контекстно-свободная грамматика, которая описывает действительные адреса электронной почты в RFC-2822. Это сложно. Например:

" @ "@example.com

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

Это не все чепуха, хотя разрешающие символы, такие как "+", могут быть очень полезны для пользователей, борющихся со спамом, например, myemail+sketchysite@gmail.com ( мгновенные одноразовые адреса Gmail).

Только когда сайт принимает это, хотя.

Принимать ли странные, необычные форматы адресов электронной почты, на мой взгляд, зависит от того, что с ними делать.

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

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

Честно говоря, действительно ли кто-то хочет, чтобы кто-то вводил адрес электронной почты из 200 символов с комментариями, новыми строками, цитатами, пробелами, круглыми скобками или другим бредом при подписке на список рассылки, информационный бюллетень или веб-сайт? Правильный ответ на таких клоунов: "Возвращайся позже, когда у тебя будет адрес, похожий на username@domain.tld".

Проверка, которую я делаю, состоит в том, чтобы убедиться, что есть ровно один '@'; что нет пробелов, нулей или переносов; что часть справа от '@' имеет хотя бы одну точку (но не две точки подряд); и что нет кавычек, круглых скобок, запятых, двоеточий, восклицательных знаков, точек с запятой или обратной косой черты, причем все они с большей вероятностью являются попытками взлома, чем части реального адреса электронной почты.

Да, это означает, что я отклоняю действительные адреса, по которым кто-то может попытаться зарегистрироваться на моих веб-сайтах - возможно, я "неправильно" отклоняю до 0,001% реальных адресов! Я могу жить с этим.

Цитирование и различные другие редко используемые, но действительные части RFC усложняют задачу. Я не знаю достаточно об этой теме, чтобы комментировать окончательно, кроме "это сложно" - но, к счастью, другие люди написали об этом подробно.

Что касается действительного регулярного выражения для него, модуль Perl Mail::Rfc822::Address содержит регулярное выражение, которое, очевидно, будет работать - но только если какие-либо комментарии уже были заменены пробелами. (Комментарии в адресе электронной почты? Вы видите, почему это сложнее, чем можно было бы ожидать...)

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

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

Просто добавьте регулярное выражение, которое менее сумасшедшее, чем перечисленное @mmaibaum:

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

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

Записано в обсуждении на http://houseoffusion.com/, ресурсе ColdFusion мирового уровня.

Простой и хороший способ проверить адреса электронной почты в Java - это использовать EmailValidator из библиотеки Apache Commons Validator.

Я бы всегда проверял адрес электронной почты в форме ввода на предмет чего-то подобного перед отправкой электронного письма - даже если вы поймете только некоторые опечатки. Вы, вероятно, не хотите писать автоматический сканер для уведомлений о "доставке не удалось".:-)

Это действительно сложно, потому что есть много вещей, которые могут быть действительными в адресе электронной почты в соответствии со спецификацией электронной почты, RFC 2822. Вещи, которые вы обычно не видите, такие как +, являются абсолютно допустимыми символами для адреса электронной почты.. согласно спецификации.

Есть целый раздел, посвященный адресам электронной почты на http://regexlib.com/, который является отличным ресурсом. Я бы посоветовал вам определить, какие критерии важны для вас, и найти тот, который соответствует. Большинству людей действительно не нужна полная поддержка всех возможностей, предусмотренных спецификацией.

Если вы работаете в.NET Framework, попробуйте создать экземпляр MailAddress возражать и ловить FormatException если он взорвется или вытаскивает Address если это удастся. Не вдаваясь ни в какую чушь о производительности по отлову исключений (на самом деле, если это только в одной веб-форме, это не будет иметь большого значения), MailAddress Класс в.NET Framework проходит довольно полный процесс синтаксического анализа (он не использует RegEx). Откройте рефлектор и найдите MailAddress а также MailBnfHelper.ReadMailAddress() чтобы увидеть все модные вещи, которые он делает. Кто-то умнее меня потратил много времени на создание этого парсера в Microsoft, и я собираюсь использовать его, когда отправлю электронное письмо на этот адрес, так что я мог бы также использовать его для проверки входящего адреса.

В этом классе для Java есть валидатор: http://www.leshazlewood.com/?p=23

Это написано создателем Сиро (формально Ки, формально JSecurity)

Плюсы и минусы тестирования на достоверность адреса электронной почты:

Существует два типа регулярных выражений, которые проверяют электронную почту:

  1. Слишком свободные.
  2. Слишком строгие.

Регулярное выражение не может совпадать со всеми действительными адресами электронной почты и недействительными адресами электронной почты, поскольку некоторые строки могут выглядеть как действительные адреса электронной почты, но фактически не попадают в чей-либо почтовый ящик. Единственный способ проверить, является ли электронное письмо действительно действительным, - это отправить электронное письмо на этот адрес и посмотреть, получите ли вы какой-либо ответ. Имея это в виду, регулярные выражения, которые слишком строги в сопоставлении электронных писем, на самом деле, похоже, не имеют особой цели.

Я думаю, что большинство людей, которые запрашивают регулярное выражение по электронной почте, ищут первый вариант, слишком свободные выражения. Они хотят проверить строку и посмотреть, выглядит ли она как электронная почта, если это определенно не электронная почта, тогда они могут сказать пользователю: "Эй, вы должны поместить здесь электронную почту, и это определенно неправильный адрес электронной почты. Возможно, вы не поняли, что это поле предназначено для электронной почты или, возможно, содержит опечатку ".

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

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

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

Попробуй это:

"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"

Посмотрите здесь для деталей.

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

В дополнение к ответу Уэйна, на сайте http://www.regular-expressions.info/email.html есть также раздел, посвященный электронной почте, с несколькими примерами.

Вы всегда можете задаться вопросом, стоит ли это того, или же на самом деле любое регулярное выражение с менее чем 100%-ным вкладом только способствует ложному чувству безопасности.

В конце концов, отправка электронного письма - это то, что обеспечит настоящую окончательную проверку. (-вы узнаете, есть ли ошибки на вашем почтовом сервере;-)

При попытке создать регулярное выражение для проверки электронных писем всегда кажется, что существует неучтенный формат. Хотя есть некоторые символы, которые недопустимы в электронном письме, основным форматом является local-part@domain и составляет примерно 64 символа максимум в локальной части и примерно 253 символа в домене. Кроме того, это похоже на дикий дикий запад.

Я думаю, что ответ зависит от вашего определения подтвержденного адреса электронной почты и от того, что допускает ваш бизнес-процесс. Регулярные выражения отлично подходят для обеспечения правильного форматирования электронного письма, и, как вы знаете, существует множество их вариантов, которые могут работать. Вот несколько вариантов:

Вариант 1:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Вариант 2:

\A(?:[a-z0-9!#$%&'*+/=?^_‘{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_‘{|}~-]+)*| "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])\z

То, что электронное письмо является синтаксически правильным, не означает, что оно действительное.

Электронное письмо может соответствовать RFC 5322 и передавать регулярное выражение, но не будет точного понимания фактической доставляемости писем. Что, если вы хотите знать, было ли это электронное письмо поддельным, одноразовым, не подлежащим доставке или известным ботом? Что, если вы хотите исключить вульгарные, в некотором роде противоречивые или проблемные электронные письма? Между прочим, чтобы все знали, я работаю в компании по проверке данных, и я просто хотел полностью раскрыть, что работаю на Service Objects, но, будучи профессионалом в области проверки электронной почты, я чувствую, что предлагаемое нами решение обеспечивает лучше проверка, чем регулярное выражение. Не стесняйтесь взглянуть, я думаю, это может очень помочь. Вы можете увидеть больше информации об этом в нашем руководстве для разработчиков. На самом деле он выполняет множество классных проверок электронной почты и проверок.

Вот пример:

Электронная почта: mickeyMouse@gmail.com

{
  "ValidateEmailInfo":{
      "Score":4,
      "IsDeliverable":"false",
      "EmailAddressIn":"mickeyMouse@gmail.com",
      "EmailAddressOut":"mickeyMouse@gmail.com",
      "EmailCorrected":false,
      "Box":"mickeyMouse",
      "Domain":"gmail.com",
      "TopLevelDomain":".com",
      "TopLevelDomainDescription":"commercial",
      "IsSMTPServerGood":"true",
      "IsCatchAllDomain":"false",
      "IsSMTPMailBoxGood":"false",
      "WarningCodes":"22",
      "WarningDescriptions":"Email is Bad - Subsequent checks halted.",
      "NotesCodes":"16",
      "NotesDescriptions":"TLS"
  }
}

Для полноты этого поста, также для PHP есть встроенная функция языка для проверки электронной почты.

Для PHP Используйте хороший filter_var с определенным типом проверки EMAIL:)

Нет больше безумных регулярных выражений электронной почты в php: D

var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));

http://www.php.net/filter_var

Кто-нибудь может дать некоторое представление о том, почему это так?

Да, это чрезвычайно сложный стандарт, который допускает множество вещей, которые сегодня никто не использует.:)

Существуют ли известные и проверенные регулярные выражения, которые действительно делают это полностью?

Вот одна попытка полностью разобрать весь стандарт...

http://ex-parrot.com/~pdw/Mail-RFC822-Address.html

Какие есть хорошие альтернативы использованию регулярных выражений для сопоставления адресов электронной почты?

Использование существующего фреймворка для него на любом языке, который вы используете? Хотя те, вероятно, будут использовать регулярное выражение внутри. Это сложная строка. Регулярные выражения предназначены для анализа сложных строк, так что это действительно ваш лучший выбор.

Изменить: я должен добавить, что регулярное выражение, с которым я связался, было просто для удовольствия. Я не одобряю использование такого сложного регулярного выражения - некоторые люди говорят, что "если ваше регулярное выражение содержит более одной строки, оно гарантированно где-то содержит ошибку". Я связался с ним, чтобы проиллюстрировать, насколько сложен стандарт.

Другие вопросы по тегам