Используйте этот чек‑лист проверки email при регистрации: решайте, где валидировать, возвращайте понятные ошибки, не блокируйте реальных пользователей и сохраняйте поток тестируемым.

Проверка почты при регистрации предотвращает попадание плохих адресов в вашу базу изначально. Это снижает количество отказов писем, неудачных сбросов пароля, лишней работы службы поддержки и накопление проблем с доставляемостью со временем.
На стороне клиента делайте быстрые проверки на ошибки, которые пользователь может исправить — например, отсутствие @, пробелы в начале/конце или явно сломанный формат. Все обязательные правила выполняйте на сервере, потому что клиентские проверки легко обойти, и ключи/политики не должны храниться в клиенте.
Синтаксис лишь говорит, что адрес выглядит как адрес. Проверки домена и MX показывают, существует ли домен и настроен ли он на приём почты — это куда более сильный сигнал доступности, но всё равно не доказательство существования конкретного почтового ящика.
Сначала обрежьте пробелы и приведите домен к нижнему регистру. Локальную часть (до @) оставьте как есть — некоторые почтовые системы различают регистр или символы, и изменение может изменить адрес.
Используйте небольшой набор результатов, которые легко объяснить и реализовать: allow (разрешить), block (заблокировать) и warn (предупредить). Предупреждения подходят для случаев со средней или неопределённой степенью риска, когда вы хотите не мешать реальным пользователям, но требовать подтверждение или наложить ограничения до верификации.
Определение одноразовой почты — это вопрос политики, а не технической ошибки. Если ваш продукт подвержен злоупотреблениям (промо‑купонные злоупотребления и т.п.), блокировка одноразовых адресов при регистрации обычно самая простая. Если вы боитесь отбрасывать легитимных пользователей, разрешите регистрацию, но ограничьте чувствительные действия до подтверждения постоянного адреса.
Установите короткий таймаут и заранее решите поведение при таймауте. Если проверка таймаутится, не говорите пользователю, что его почта неверна; предложите повторить попытку или разрешите регистрацию в состоянии «ожидает подтверждения», с повторной проверкой в фоне — в зависимости от вашей терпимости к риску.
Показывайте простые, исправимые сообщения при синтаксических ошибках и держите сообщения о риске общими. Пользователю не нужно знать названия блоклистов или провайдеров; эти детали сохраняйте во внутренних кодах причин, чтобы служба поддержки и инженеры могли отлаживать, не обучая злоумышленников обходить проверки.
Логируйте минимум, необходимый для отладки и метрик. Практичный набор: хеш адреса, домен, статус результата, несколько кодов причин, метка времени и ID запроса/попытки регистрации — вместо повсеместного копирования сырого ввода.
Поместите валидацию за простым интерфейсом и возвращайте стабильный тип результата: valid, invalid, risky или unknown. В модульных тестах подменяйте валидатор фиктивной реализацией, а сетевые вызовы мокируйте в интеграционных тестах, чтобы проверки регистрации оставались быстрыми и детерминированными.
Регистрация — это место, где в вашу систему попадают плохие адреса. Как только они сохранены, они создают работу позже: неудачные сбросы пароля, обращения в поддержку, недоставленные рассылки и запылённая база пользователей. Чек‑лист валидации помогает решить, что блокировать сразу, о чём предупреждать и что просто логировать.
Многие проблемы — простые человеческие ошибки. Люди опечатались в домене (gamil.com), забыли часть адреса или вставили лишние пробелы. Ловите такие ошибки быстро: их легко исправить, и это экономит пользователю раздражающий цикл.
Следующая категория — низкокачественные или рисковые адреса. Некоторые домены не существуют, не настроена почта или они никогда не будут принимать сообщения. Другие — сервисы одноразовой почты, которые берут пробный период и исчезают. Вы также можете встретить спам‑ловушки и шаблоны, связанные со злоупотреблениями. Эти адреса постепенно ухудшают доставляемость и репутацию отправителя.
Хорошая валидация — это баланс:
Где именно вы валидируете имеет значение, потому что это меняет и опыт пользователя, и безопасность.
Клиентские проверки дают мгновенную обратную связь при опечатках, но их легко обойти. Серверные проверки обеспечиваемы, но добавляют задержку и требуют понятной обработки ошибок. Фоновые проверки полезны, когда вы не хотите замедлять регистрацию, но они не должны становиться тихим источником плохих данных.
Согласуйте ожидания с командой заранее: валидация снижает риск, но не гарантирует абсолютную уверенность. Даже технически валидный и доставляемый адрес со временем может отскочить (полный почтовый ящик, отключённый аккаунт). И некоторые внешне рисковые адреса принадлежат реальным пользователям.
Пример: пользователь вводит [email protected]. Поймайте это сразу и предложите исправление. Но если пользователь вводит действительный адрес на одноразовом домене, у вас есть выбор политики: блокировать при регистрации, чтобы предотвратить злоупотребления, или разрешить с ограничениями, чтобы не отвергать легитимного пользователя.
Проверка почты — это не один тест. Это стек мелких проверок, которые отвечают на разные вопросы. Держите слои раздельно, чтобы можно было действовать по результату, не догадываясь, что именно пошло не так.
Обычные слои в чек‑листе валидации почты:
@, пробелы, недопустимые символы и другие ошибки формата. Это не говорит о существовании адреса.example.com) реальна и у неё есть записи DNS.admin@) или вашими собственными рискованными шаблонами. Рассматривайте это как политику, а не истину.Некоторые проверки безопасно запускать мгновенно в браузере. Другие лучше выполнять на сервере.
Синтаксические проверки быстры и надёжны, поэтому они хорошо подходят для клиентской стороны и дают моментальную обратную связь. DNS и MX, как правило, тоже быстры, но зависят от сети и резолвера, поэтому сбои и таймауты следует воспринимать как норму. Совпадение с провайдерами и блоклистами обычно быстрое при использовании хорошего сервиса, но в коде всё равно нужен таймаут и запасной план.
Полезная модель мышления: ошибки форматирования — ясные и исправимые пользователем. Сигналы доступности и риска (DNS, MX, отметки одноразовых) — вероятностны. Используйте их, чтобы решить, что разрешить, о чём предупреждать или что передать на ручную проверку.
Для приватности рассматривайте электронную почту как чувствительные данные. Логируйте аккуратно и избегайте сохранения сырых "плохих вводов" только потому, что валидация провалилась. Если нужны отладочные логи, держите их минимальными (например: хеш почты, код причины и ID запроса).
Место валидации важно не меньше, чем то, что вы проверяете. Хорошая схема использует три уровня, у каждого — своя задача.
Клиентская валидация нужна для скорости и ясности. Ограничьте её очевидными ошибками: отсутствие @, пробелы, двойные точки или явно сломанный формат. Это помогает пользователю, но не является защитой.
Серверная валидация — источник истины. Все реальные правила должны быть тут, потому что сервер — единственное место, которое вы контролируете. Здесь же безопасно вызывать сервисы проверки почты, не раскрывая ключи. Глубокие проверки (домены, MX, одноразовые провайдеры, блоклисты) выполняются на сервере, где можно принять решение: принять, отклонить или попросить подтверждение.
Валидацию выполняйте до создания записи пользователя, когда это возможно. Если вы сначала создаёте аккаунт, а потом проверяете, вы соберёте фейковых пользователей, потратите промо‑почту и откроете дорогу злоупотреблениям.
Фоновые проверки опциональны, но полезны. Статус почты меняется со временем (домены истекают, ящики отключаются, провайдеры попадают в списки одноразовых). Повторная фонова проверка также помогает, когда email меняется позже.
Держите разделение простым:
Если вы делаете повторные проверки, храните небольшой сводный отчёт с пользователем (статус, причины, временная метка). Это избегает повторных вызовов при каждом входе и облегчает поддержку.
Хорошая регистрация сначала проверяет простые вещи, а затем тратит время и API‑вызовы только когда это важно.
Начните с нормализации ввода: обрежьте пробелы в начале и конце. Решите, как обрабатывать внутренние пробелы (многие команды отклоняют их). Приводите к нижнему регистру только доменную часть (пример: [email protected] → [email protected]). Локальную часть оставляйте без изменений, чтобы не менять смысла.
Далее выполните базовые синтаксические проверки и останавливайтесь при явных ошибках. Это самый дешёвый фильтр: ровно один @, отсутствие запрещённых символов, разумная длина, непустой домен. При провале показывайте простое сообщение вроде "Введите корректный адрес электронной почты" и не вызывайте внешние сервисы.
Только после этого имеет смысл вызывать сервис валидации, чтобы узнать то, чего синтаксис не покажет: существует ли домен, есть ли у него записи MX и относится ли он к одноразовым провайдерам или известным ловушкам. Рассматривайте этот вызов частью критического пути. Установите короткий таймаут и определите понятный запасной план.
Большинству команд полезно ограничиться небольшим набором результатов:
Пример: приложение с большим количеством купонов может блокировать одноразовые адреса, чтобы снизить злоупотребления. B2B‑продукт может допустить их, но требовать подтверждённый корпоративный email перед приглашением команды.
Наконец, сохраните короткое резюме произошедшего для поддержки и инженеров: нормализованный email, результат (allow/block/warn), несколько кодов причин (syntax, no_mx, disposable), время ответа и метка времени.
Обработка ошибок — место, где валидация может раздражать. Цель — помочь реальным людям быстро исправить ошибки, но при этом блокировать адреса, которые повредят доставляемости.
Разделяйте «вы можете это исправить» и «мы не можем это принять». Если проблема синтаксическая, скажите это простыми словами. "Email должен содержать символ @" лучше, чем "Неверный email", потому что даёт пользователю подсказку, что исправить.
Для риск‑сигналов, которые не однозначны, подумайте о предупреждении вместо жёсткой блокировки. Если адрес похож на одноразовый, можно разрешить регистрацию, но потребовать подтверждение перед включением важных функций или ограничить возможности до добавления нормального адреса.
Избегайте раскрытия внутренней логики обнаружения. Пользователю не нужны названия блоклистов или списков провайдеров. Делайте сообщение в интерфейсе общим ("Пожалуйста, используйте реальный, доступный адрес электронной почты"), а подробности сохраняйте в логах.
Последовательность важна. Используйте небольшой набор кодов ошибок, которые фронтенд обрабатывает одинаково каждый раз и по которым логи легко фильтровать:
EMAIL_SYNTAX: показать исправимое сообщениеEMAIL_UNREACHABLE: блокировать (домeн не имеет рабочей почтовой настройки)EMAIL_RISKY: предупреждать или мягко блокироватьEMAIL_TIMEOUT: предложить повторитьТаймауты заслуживают особого внимания, потому что часто это не вина пользователя. Если валидация таймаутится, не обвиняйте пользователя в неверном адресе. Скажите что‑то вроде: "Мы не смогли проверить вашу почту прямо сейчас. Пожалуйста, попробуйте снова." Дайте понятный путь повтора и подумайте о разрешении регистрации в состоянии "ожидает подтверждения", если продукт это поддерживает.
Пример: пользователь вводит jane.doe@gmail и нажимает "Зарегистрироваться". UI может поймать отсутствие доменной зоны верхнего уровня и показать короткую подсказку. Если синтаксис в порядке, но сервер пометил адрес как рискованный, сообщение для пользователя должно фокусироваться на следующем шаге: "Попробуйте другой email или продолжите и подтвердите позже."
Поддерживаемость кода регистрации повышается, если разделить три вещи: вызов сервиса проверки, принятие решения по результату и запись произошедшего. Когда всё смешано в контроллере или хэндлере, мелкие изменения политики превращаются в рискованные рефакторы.
Начните с маленького стабильного типа результата, который ваше приложение понимает. Рассматривайте его как единственную вещь, от которой зависит остальной код, даже если потом поменяете провайдера.
export type EmailValidationResult =
| { status: "valid" }
| { status: "invalid"; reason?: string }
| { status: "risky"; reason?: string }
| { status: "unknown"; reason?: string };
Держите решения о политике отдельно от вызова API. Клиент API должен переводить ответ провайдера в EmailValidationResult. Модуль политики решает, блокировать, предупреждать или разрешать на основе правил продукта.
Сетевую часть делайте безопасной по умолчанию. Устанавливайте короткие таймауты, выполняйте одну повторную попытку при временных ошибках и определяйте запасной план. Например: если валидация таймаутится, возвращайте unknown и продолжайте регистрацию, вместо того чтобы прерывать весь поток.
Кешируйте результаты короткое время, чтобы избежать повторных запросов в одной попытке. Кеш на 5–15 минут, ключованный по нормализованному email, может предотвратить двойные вызовы при повторной отправке или обновлении страницы. Не рассматривайте кеш как постоянную истину.
И, наконец, добавьте лёгкие метрики, чтобы быстро заметить проблемы. Отслеживайте количество valid/invalid/risky/unknown, таймауты и повторы, блокировки vs предупреждения, и последующие отказы писем (чтобы сравнить результаты валидации с реальной доставляемостью).
Если валидация прямо в контроллере делает реальные сетевые вызовы, тесты становятся медленными и нестабильными. Рассматривайте валидатор как зависимость, а не побочный эффект.
Оборачивайте валидатор за небольшим интерфейсом, от которого зависит код регистрации. В продакшне этот интерфейс вызывает провайдера валидации. В тестах подменяйте его фиктивной реализацией, которая возвращает заранее заданные ответы. Это сохраняет модульные тесты быстрыми и делает сбои воспроизводимыми.
Тестируйте логику политики отдельно от сети. Поместите принятие решений в одну функцию, которая принимает простой результат (valid, risky, unknown, error) и возвращает действие приложения (allow, block, allow-with-warning, require-confirmation). Протестируйте её таблицей случаев.
Для интеграционных тестов оставьте минимальный и детерминированный набор: один сценарий «всё хорошо» и один сценарий блокировки обычно достаточно. Мокируйте валидатор на границе HTTP (или через локальный стаб), чтобы тесты никогда не зависели от реальной сети.
Если у вас есть повторы, избегайте реального времени и случайных задержек в модульных тестах. Внедрите часы и политику бэкоффа, чтобы протестировать «после 2 повторов мы останавливаемся» без ожидания.
Большинство ошибок при валидации регистрации — не про синтаксис. Они про то, что вы делаете, когда сигнал неполный, и как сохраняете быстроту потока.
Одна частая ловушка — считать валидацию бинарным переключателем. Если вы блокируете всё, что не 100% уверенно, вы будете отбрасывать реальных пользователей (ложные срабатывания). Разделяйте «определённо плохое» (сломанный синтаксис, несуществующий домен, известный одноразовый) и «неопределённое» (временные сетевые ошибки, неоднозначные сигналы). Для неопределённых случаев разрешайте продолжать, но требуйте подтверждение перед полным доступом.
Ещё одна ловушка — полагаться только на браузерные проверки. Клиентские проверки помогают, но их легко обойти. Повторяйте ключевую валидацию на сервере.
DNS может быть нестабилен. Если запрос резолвера таймаутится, считать это окончательной ошибкой раздражает пользователей. Классифицируйте сетевые и DNS‑ошибки как повторяемые. Сохраняйте регистрацию, пометьте email как ожидающий верификации и перепроверьте в фоне.
Несколько практических правил, которые предотвращают большинство проблем:
B2B SaaS‑продукт предлагает 14‑дневный бесплатный пробный период. Регистрация начинается с email: пользователь вводит адрес, получает код подтверждения, затем устанавливает пароль после подтверждения почты. Цель — остановить явный мусор, не блокируя людей, которые опечатались.
Простая политика подходит большинству команд: принимать явно валидные адреса, блокировать одноразовые, предупреждать при рискованных или неопределённых результатах, давая пользователю возможность исправить ошибку.
1) Опечатка: [email protected]
Покажите дружелюбное встроенное сообщение: "Возможно, вы имели в виду [email protected]?" и дайте пользователю отредактировать. Аккаунт не создавайте до исправления.
На бэкенде запустите синтаксис и проверку домена, затем используйте сервис валидации, чтобы подтвердить домен и MX. Если похож на опечатку — верните структурированную ошибку валидации и (опционально) подсказку.
2) Одноразовый: [email protected]
Покажите чёткий блок: "Пожалуйста, используйте рабочий email. Одноразовые провайдеры не допускаются." Кратко и без обвинений.
Бэкенд: совпадение с одноразовым — блокировать регистрацию, не отправлять письмо подтверждения, не создавать рабочее пространство.
3) Корпоративный валидный: [email protected]
Покажите: "Проверьте почту для кода." Бэкенд: проверьте синтаксис, MX, примите, создайте временного (не верифицированного) пользователя, отправьте код подтверждения и активируйте пробный период только после подтверждения.
Это работает, потому что каждое решение основано на одном понятном результате, а не на ворохе разрозненных правил.
Держите логи полезными, не копируя адреса в каждом сообщении. Разумный набор:
Убедитесь, что важные проверки выполняются на сервере. UI‑проверки ловят опечатки, но их легко обходить. Сервер должен решать, можно ли создать аккаунт по email.
Решите, что делать, если валидация медленная. Установите понятный таймаут (например, несколько сотен миллисекунд до пары секунд) и выберите политику: разрешить и пометить аккаунт, предупредить и попросить повторить, или выполнить одну повторную попытку в фоне.
Короткий релиз‑чеклист:
Для ошибок разделяйте то, что вы логируете, и то, что показываете пользователю. Пользователь получает простое руководство ("Проверьте опечатки" или "Попробуйте другой адрес"). Логи содержат детальные коды причин для поддержки и аналитики.
Если вам нужен единый вызов API, который возвращает многоступенчатые сигналы (синтаксис, домен, MX и совпадение с одноразовыми/блоклистами), такие инструменты, как Verimail, позволяют сосредоточиться на политике, а не на инфраструктуре. Если вы оцениваете варианты, Verimail доступен на verimail.co.
Добавьте одну простую метрику: сколько регистраций было заблокировано, помечено предупреждением или разрешено с флагом. Эта обратная связь быстро покажет, слишком строгая или слишком мягкая ваша политика.