Используйте этот контрольный список валидации синтаксиса email, соответствующий RFC, чтобы поймать краевые случаи парсинга — кавычные локальные части, плюс-адресацию и хитрые субдомены — до запуска.

Используйте специализированный парсер, когда это возможно. Регулярные выражения обычно упускают крайние случаи вроде кавычек в локальной части, плюс-тегов и доменов с несколькими метками, поэтому они либо отклоняют реальных пользователей, либо принимают некорректный ввод.
Синтаксис задаёт вопрос «правильно ли записан адрес?», а политика — «разрешаем ли мы его в продукте?». Разделяйте их, чтобы случайно не блокировать валидные адреса при попытке уменьшить риски регистрации.
Нет. «Соответствие RFC» означает, что строку можно распарсить как корректный адрес по правилам RFC. Это не доказывает, что домен существует, у него есть MX-записи или что почтовый ящик может принять почту.
Сначала обрежьте начальные и конечные пробелы, затем отклоняйте управляющие символы вроде табов и переводов строки. Не «нормализуйте» адрес, удаляя внутренние символы — это может изменить адрес, который ввёл пользователь.
Разрешайте по умолчанию. [email protected] — обычный и широко используемый формат; его блокировка создаёт лишнее трение при регистрации и не повышает безопасность сама по себе.
Да. Субдомены распространены, и домены часто содержат несколько точек, например sub.example.co.uk. Валидатор, который ожидает «только одну точку» в домене, отклонит много реальных адресов.
Требуйте ровно один символ @ с как минимум одним символом по обе стороны. Не разделяйте строку по первому @, игнорируя остальные, и не принимайте вводы с несколькими @ как есть.
Решайте сознательно. Они валидны по стандарту, но редки и могут ломать downstream-системы, которые ожидают упрощённый формат. Если вы их отклоняете — оформите это как политику и показывайте понятную ошибку.
Они помогают отсеять злоупотребления и странные кейсы. Практические ограничения: 254 символа всего адреса, до 64 символов — локальная часть, до 253 — домен, до 63 — каждая метка домена.
Используйте коды причин, которые соответствуют конкретным ошибкам, например: CONTROL_CHAR, PARSE_FAIL, LENGTH или DOMAIN_LABEL. Это делает поддержку и отладку намного проще, чем общий «invalid email».
Адреса электронной почты кажутся простыми, пока вы не начнёте их валидировать. Многие баги в продакшне возникают из-за отношения к email как к «нескольким буквам, @ и точке» с опорой на быстрый регекс. Реальные адреса допускают больше вариаций, чем ожидают формы, и небольшие решения в парсинге могут превратить валидный адрес в «недействительный».
Частая путаница — в смешении двух разных вопросов:
Если вы хотите уменьшить риск регистрации злоумышленников, вы можете блокировать отдельные шаблоны. Если же ваша цель — не отвергать реальных пользователей, сначала надо корректно реализовать синтаксис, а затем поверх него применять политику. Разделение этих слоёв — разница между валидатором, которому можно доверять, и тем, который тихо отсекает регистрации.
Отклонение валидных адресов ломает реальные вещи. Кто-то вводит полностью корректный адрес с плюс-адресацией или субдоменом, форма говорит «недопустимо», и пользователь уходит. Вы теряете регистрацию и часто не собираете достаточно данных, чтобы разобраться, почему.
Принятие неправильных адресов ломает другие вещи. Неверные адреса увеличивают количество bounce-сообщений, что может повредить репутации отправителя и доставляемости. Они также привлекают низкокачественные регистрации и мошенничество, когда злоумышленники швыряют формы мусором.
Большинство сбоев в продакшне сводятся к нескольким шаблонам: регексы слишком строгие (или слишком свободные), неправильное разделение вокруг @, чрезмерная обрезка или «нормализация», и смешивание синтаксических проверок с проверками доставляемости.
Пример: кто‑то регистрируется как [email protected]. Простейший валидатор отклонит его, потому что ожидает только одну точку в домене. Адрес может быть полностью нормальным, но пользователь никогда не получит подтверждение.
В этой статье мы сосредоточимся на синтаксисе: записан ли адрес в корректном формате. Это не доказывает, что почтовый ящик существует или что домен может принимать почту — такие проверки относятся к последующим слоям.
«Соответствующий RFC» в основном про синтаксис: можно ли распарсить строку как адрес по правилам RFC 5322? Это полезно, но лишь первый фильтр. Синтаксически валидный адрес всё ещё может быть недоставляемым, небезопасным или низкого качества.
Думайте о валидации слоями:
Практическая цепочка: парсинг синтаксиса, проверка базовых характеристик домена, затем применение вашей политики (блокировка известных одноразовых доменов, ловушек спама и других рисков). Сам по себе синтаксис не должен претендовать на гарантию доставляемости.
Для форм регистрации это обычно означает принимать распространённые форматы из реальной жизни (плюс-теги, субдомены, длинные TLD) и не отклонять валидные адреса только потому, что они выглядят необычно.
Некоторые команды сознательно ужесточают правила. Это допустимо, но должно быть осознанным решением, задокументированным и покрытым тестами. Например, вы можете всё ещё отклонять:
@ или отсутствие локальной части или доменаСценарий: [email protected] синтаксически может быть валиден. Если у домена нет MX-записей — вы поймаете это на слое проверки домена. Если это известный одноразовый провайдер — это политика.
Большинство багов в валидации возникают потому, что валидатор догадывается. Прежде чем хвататься за регекс, проясните структуру: локальная часть, ровно один @ и доменная часть.
@. Здесь живут хитрые случаи: плюс-теги, точки и иногда кавычные строки.@. Она следует правилам меток домена и может быть интернационализирована.Разделение этих частей делает логику проще для понимания и тестирования.
Реальные адреса могут содержать не‑ASCII символы в локальной части (EAI) и не‑ASCII домены (IDN). Решите заранее, что вы поддерживаете.
Если вы принимаете только ASCII — отклоняйте не‑ASCII сразу и ясно объясняйте причину. Если вы поддерживаете IDN, обычно вы валидируете домен в его ASCII-совместимой форме (punycode) внутри системы.
Ограничения по длине помогают избежать крайних случаев и защитить формы от злоупотреблений. Часто используемые практические лимиты:
Перед парсингом сделайте базовую очистку: обрежьте начальные и конечные пробелы и отклоняйте адреса с внутренними пробелами, если вы явно не поддерживаете кавычные локальные части. Не приводите локальную часть к нижнему регистру (она может быть чувствительна к регистру), но обычно безопасно привести домен к нижнему регистру.
Плюс-адресация — когда пользователь добавляет тег после знака плюс, например [email protected]. Люди используют это для фильтрации и отслеживания регистраций, поэтому отказ от таких адресов добавляет трение без пользы.
Относитесь к + как к нормальному символу в локальной части (за пределами кавычных строк). Даже если некоторые провайдеры игнорируют тег при доставке, он всё равно часть адреса в том виде, как его ввёл пользователь.
Многие команды принимают «безопасный набор» в локальной части (буквы, цифры и немного разделителей, таких как ., _, -, +). Это покрывает большинство реальных адресов и упрощает реализацию.
Правила RFC допускают больше знаков пунктуации, но расширять набор стоит только если вы готовы правильно это реализовать и покрыть тестами.
В обычной некавычной форме точки разрешены в локальной части, но не везде:
[email protected] — неверно[email protected] — неверноНе привязывайте синтаксис к поведению провайдеров. Некоторые провайдеры считают firstlast и first.last одним и тем же почтовым ящиком, но это не правило синтаксиса.
Пара быстрых кейсов для тестов:
[email protected] (плюс-тег)[email protected] (точка)[email protected] (ведущая точка)[email protected] (две точки)[email protected] (плюс-тег с субдоменом)Кавычные строки появились, потому что правила адресов покрывают старые системы и необычные имена ящиков. Они появляются в локальной части, когда адресу нужны символы, которые иначе были бы недопустимы или неоднозначны.
Кавычная локальная часть оборачивается двойными кавычками, например \"john smith\"@example.com. Внутри кавычек пробелы допустимы. Если нужна литеральная двойная кавычка или обратный слеш внутри кавычек, их нужно экранировать обратным слешем.
Запутанность в том, что правила внутри кавычек меняются. Две точки подряд обычно недопустимы в некавычной локальной части, но они разрешены внутри кавычной строки. Значит \"a..b\"@example.com может быть валидным, в то время как [email protected] — нет.
Для регистрации у вас есть реальный выбор:
Любой вариант защитим. Баги возникают, когда вы случайно отклоняете их из‑за регекса, на который не рассчитывали.
Тест-кейсы, синтаксически валидные:
\"john smith\"@example.com\"a..b\"@example.com\"john\\\"smith\"@example.com\"back\\\\slash\"@example.com\"weird()[],:;\u003c\u003e@\"@example.comКавычные строки влияют только на локальную часть. Домен всё равно нужно валидировать отдельно.
Многие валидаторы некорректно обрабатывают домены. Субдомены — нормальная и распространённая вещь. [email protected] не должен удивлять ваш парсер.
Простой подход — валидировать домен как набор меток, разделённых точками, и применять несколько простых правил.
Для большинства потребительских регистраций эти правила хорошо работают:
Требовать «как минимум одну точку» часто полезно как фильтр опечаток для публичных адресов, но это уже политическое решение, если вы поддерживаете внутренние домены.
Проблемы с точками и разбиением скрывают баги. Это жёсткие ошибки:
[email protected][email protected], [email protected].[email protected][email protected], [email protected]a@sub_domain.exampleБольшинство «недопустимый адрес» ошибок вызвано валидаторами, которые делают допущения вместо последовательных правил.
Пробелы — одна из больших проблем. Копирование/вставка может добавить ведущие пробелы, завершающие пробелы, табы, неразрывные пробелы или скрытый перевод строки. Если валидировать до обрезки — вы отклоните валидный адрес. Если «нормализовать» слишком агрессивно (например, удалять все пробелы внутри), вы можете изменить смысл адреса.
Ещё одна ловушка — наивное разбиение по @. Нужен ясный принцип: ровно один разделитель @, минимум по одному символу с каждой стороны. Не принимайте мусор, разделяя по первому @ и игнорируя остальные, и не падайте с ошибкой, разделяя по всем @.
Некоторые библиотеки частично поддерживают возможности RFC вроде комментариев (например john.smith(comment)@example.com). Частичная поддержка хуже, чем последовательное отклонение, потому что создаёт несоответствия между frontend и backend.
Сигналы тревоги:
@ без проверки «ровно один»Юникодные визуальные клоны сложны. Даже если вы поддерживаете интернационализированные адреса, полезно логировать подозрительные случаи и показывать понятную ошибку, когда что‑то выглядит неуместно.
Надёжный валидатор — это не одно хитрое правило. Это небольшой набор правил, примененных в правильном порядке.
Обрежьте начальные и конечные пробелы, затем отклоняйте управляющие символы (табы, переводы строки, нулевые байты). Решите, как обращаться с неразрывными пробелами и прочими странными Unicode-пробелами. Ясно укажите, поддерживаете ли вы не‑ASCII.
Подход «только регекс» часто отклоняет валидные адреса или принимает сломанные. Используйте парсер, который понимает локальную часть и домен, и знает, как обрабатывать кавычные строки, если вы решили их поддерживать.
Отделяйте парсинг от политики. Парсер отвечает на вопрос «синтаксически валиден?», политика — «разрешаем ли в продукте?».
После парсинга примените жёсткие лимиты и базовые проверки домена (длины, отсутствие пустых меток, отсутствие ведущих/завершающих дефисов, субдомены допустимы при корректной форме). Это ловит вводы, которые технически могут распарситься, но создадут проблемы позже.
Создайте сознательное решение по крайним случаям вроде кавычных локальных частей. Если вы блокируете их — зафиксируйте это и показывайте понятную ошибку. Если поддерживаете — добавьте тесты для экранированных символов и пробелов.
И самое важное: используйте одинаковые правила на вебе, в мобильном приложении и на бэкенде, чтобы пользователи не сталкивались с несоответствиями.
Когда служба поддержки спрашивает, почему email отклонён, ответ «invalid» бесполезен. Логируйте набор кодов причин (например: CONTROL_CHAR, PARSE_FAIL, LENGTH, DOMAIN_LABEL). Это упрощает диагностику и помогает находить проблемы вроде того, что iOS‑клавиатура вставляет скрытый перевод строки.
Валидатор хорош ровно настолько, насколько хорошы тесты, которые закрепляют его поведение. Держите небольшой набор «обязательных на вход» на основе реальных регистраций, набор «обязательных на отказ» для универсальных отклонений и набор краевых случаев для парсерных ловушек.
Примеры, которые должны проходить:
Примеры, которые должны отклоняться:
plainaddress (нет @)alex@ (нет домена)@example.com (нет локальной части)[email protected] (две точки в локальной части)Если вы поддерживаете кавычные строки, добавьте явные тесты вроде \"john..doe\"@example.com и \"john\\\"doe\"@example.com. Если вы не поддерживаете их — всё равно держите такие тесты, но отметьте их как отклоняемые по политике, чтобы выбор был виден.
Не ограничивайтесь pass/fail. Храните ожидаемые коды причин, чтобы ошибки были осмысленными.
{ \"input\": \"[email protected]\", \"expected\": \"fail\", \"reason\": \"LOCALPART_DOT_SEQUENCE\" }
Запускайте один и тот же набор тестов везде, где валидируете: веб, мобильные клиенты, бэкенд и любые сторонние потоки аутентификации. Именно там обычно появляются рассинхронизации.
Если вы хотите меньше багов с регистрациями и меньше обращений «почему этот email не проходит?», держите правила синтаксиса короткими и последовательными. Практический минимум выглядит так:
@, минимум по одному символу по обе стороныПримите одно решение и зафиксируйте его: принимать ли кавычные локальные части вроде \"john smith\"@example.com. Они допустимы по RFC 5322, но редки при регистрациях и часто неправильно обрабатываются последующими системами.
После синтаксической проверки добавьте то, что синтаксис покрыть не может: проверьте существование домена, MX-записи и фильтры одноразовых email и ловушек спама. Если вы не хотите сами поддерживать эти уровни, Verimail (verimail.co) — API для валидации email, который сочетает синтаксические проверки с проверкой домена, MX lookup и сопоставлением блоклистов и одноразовых провайдеров, чтобы вы могли держать логику регистрации последовательной, не нагружая один регекс.