Итак, что делает электронную почту действительной? Если следовать определению в RFC (RFC5322 и ссылки на него), это будет слишком сложно. Для обычных случаев использования достаточно использовать регулярное выражение, предоставленное WHATWG:

/^[a-zA-Z0–9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0–9](?:[a-zA-Z0–9-]{0,61}[a-zA-Z0–9])?(?:\.[a-zA-Z0–9](?:[a-zA-Z0–9-]{0,61}[a-zA-Z0–9])?)*$/

Давайте разберем регулярное выражение

  • Должен быть ровно один символ @.
  • Основная форма local-part@domain.
  • Локальная часть должна содержать хотя бы один буквенно-цифровой символ или специальный символ (. ! # $ % & ‘ * + \ / = ? ^ _ ` { | } ~ -).
  • Домен должен содержать хотя бы одну метку, разделенную точкой.
  • Метка ограничена 63 символами. Он должен содержать только буквенно-цифровые символы или дефисы. Однако первый и последний символы не могут быть дефисами.

Технически,

email = local-part "@" domain
local-part = 1*(atext / ".")
domain = label *("." label)
label = let-dig [[ldh-str] let-dig] ;limited to 63 characters
let-dig = ALPHA / DIGIT
ldh-str = *(let-dig / "-")
 
atext = ALPHA / DIGIT / ! # $ % & ' * + / = ? ^ _ ` { | } ~ -
ALPHA = a-z A-Z
DIGIT = 0-9
 
*(n) = 0 or more (n)
1*(n) = 1 or more (n)
(n){x,y} = x-y occurrence of (n)

Как указано в самом документе, это регулярное выражение

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

Поддержка Юникода

С расширением SMTP RFC6531 Unicode разрешено использовать в адресах электронной почты. Это расширение очень актуально, если у вас интернационализированный продукт. На самом деле, я сталкивался с просьбами пользователей разрешить Unicode в своих электронных письмах. В большинстве случаев нам достаточно поддерживать только умлауты. Но иногда вам может понадобиться поддержка китайских или японских символов. Теоретически адрес электронной почты типа 客服@买卖.商务 вполне подойдет.

Я искал через различные источники, но не достиг хорошего результата. Поэтому я решил изменить регулярное выражение, предоставленное WHATWG, для поддержки символов Unicode.

/^(?:[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]|[^\u0000-\u007F])+@(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?(?:\.(?:[a-zA-Z0-9]|[^\u0000-\u007F])(?:(?:[a-zA-Z0-9-]|[^\u0000-\u007F]){0,61}(?:[a-zA-Z0-9]|[^\u0000-\u007F]))?)*$/

Вот Plunker, с которым вы можете поиграться.

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

  • Допускаются только символы, отличные от ASCII UTF8. Это означает, что символы от \u0000 до \u007F должны быть исключены. Все остальное в порядке.
  • Остальные правила следуют исходному.

Технически,

email = local-part "@" domain
local-part = 1*(atext / "." / utf8-non-ascii)
domain = label *("." label)
label = let-dig [[ldh-str] let-dig] ;limited to 63 characters
let-dig = ALPHA / DIGIT / utf8-non-ascii
ldh-str = *(let-dig / "-")
atext = ALPHA / DIGIT / ! # $ % & ' * + / = ? ^ _ ` { | } ~ -
utf8-non-ascii = NOT(\u0000-\u007F)
ALPHA = a-z A-Z
DIGIT = 0-9
 
*(n) = 0 or more (n)
1*(n) = 1 or more (n)
(n){x,y} = x-y occurrence of (n)
NOT(n) = Non-existence of (n)

В основном [^\u0000-\u007F] вводится для всех частей регулярного выражения с использованием шаблона (?:<original>|[^\u0000-\u007F]. Дайте мне знать, можно ли улучшить это регулярное выражение. Спасибо!

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