В этой статье рассмотривается валидация email изпользуя регулярные выражения. Все регэкспы выполняются с модификатором
Перед тем как писать валидацию, надо знать из чего состоит email адрес. Думаю известно всем что это «username@hostname». Лучше всего будет разбить создание регэкспа на 2 логические части — валидация hostname и валидация username. Начнём с более объёмного.
Для начала подумаем, а из чего же состоит hostname?
Имя хоста состоит из нескольких компонентов, разделённых точкой и не превышающих 63 символа, и суффиксов (домены первого уровня). Компоненты, в свою очередь, состоят из латинских букв, цифр и дефисов, причём дефисы не могут быть в начале или в конце компонента. Суффиксы это ограниченный список доменов первого уровня (я нашёл список на сайте IANA). Для упрощения выражения запишем домены стран как
Для компонентов код будет посложнее:
Разберём выражение:
Рассмотрим необязательную часть:
В итоге мы получили выражение отвечающее за проверку hostname:
Обращу внимание на то, что присутствие компонентов не обязательно, т.к. некоторые домены первого уровня поддерживаются серверами. Пример.
Имя пользователя может в себе содержать:
Приведу сразу выражение:
На самом деле тут все просто: 1 или более символ
Регэксп проверки email:
Это выражение можно каплю оптимизировать (про оптимизацию, я думаю, будет отдельная статья):
Рассмотрим регэксп, который привели в пример в комментарии к вступительному топику:
Какие тут есть главные проблемы?
P.S. Пишите о багах и пожеланиях — обязательно исправлю.
P.P.S. По желанию могу выложить функцию проверки 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, используюмую мной.
