Точки и плюс-алиасы в Gmail: как находить повторные регистрации
j.doe+7@gmail.com и jdoe@gmail.com — один и тот же ящик. Как устроена адресация Gmail, функция нормализации на JavaScript и Python и пограничные случаи, на которых спотыкаются.
Один ящик — бесконечно много адресов
В Gmail действуют два правила адресации, из-за которых создать много аккаунтов из одного ящика проще простого:
- Точки игнорируются. Для адресов
@gmail.comвариантыjane.doe,janedoeиj.a.n.e.d.o.e— один и тот же ящик. У имени из десяти букв сотни вариантов с точками. - Всё после знака плюс игнорируется.
janedoe+test1@gmail.com,janedoe+test2@gmail.comи так далее приходят вjanedoe@gmail.com. Количество вариантов не ограничено.
Кроме того, @googlemail.com — тот же сервис, что и @gmail.com. Каждый вариант проходит подтверждение почты, ведь письмо действительно приходит. Для вашей формы регистрации это всё разные, совершенно новые пользователи.
Плюс-адресация есть не только в Gmail: её поддерживают Fastmail и Proton Mail, а также многие корпоративные почтовые серверы. А вот игнорирование точек — особенность личного Gmail.
Нормализуйте, затем сравнивайте
Решение — хранить рядом с исходным адресом его нормализованную форму и сравнивать новые регистрации с ней. Оригинал оставьте для отправки писем: его ввёл пользователь, и некоторые фильтруют почту по плюс-тегам.
// JavaScript function normalizeEmail(input) { const raw = input.trim().toLowerCase(); const at = raw.lastIndexOf("@"); if (at < 1) return null; let local = raw.slice(0, at); let domain = raw.slice(at + 1).replace(/\.$/, ""); if (domain === "googlemail.com") domain = "gmail.com"; const plus = local.indexOf("+"); if (plus > 0) local = local.slice(0, plus); if (domain === "gmail.com") local = local.replaceAll(".", ""); return `${local}@${domain}`; } normalizeEmail("J.Doe+trial7@GoogleMail.com"); // "jdoe@gmail.com"
# Python def normalize_email(value: str) -> str | None: raw = value.strip().lower() local, sep, domain = raw.rpartition("@") if not sep or not local: return None domain = domain.rstrip(".") if domain == "googlemail.com": domain = "gmail.com" base = local.split("+", 1)[0] or local if domain == "gmail.com": base = base.replace(".", "") return f"{base}@{domain}"
Затем добавьте столбец и индекс и проверяйте при регистрации:
ALTER TABLE users ADD COLUMN email_normalized text; CREATE INDEX users_email_normalized ON users (email_normalized); -- при регистрации SELECT count(*) FROM users WHERE email_normalized = $1;
Пограничные случаи, на которых спотыкаются
- Не удаляйте точки за пределами личного Gmail. У большинства провайдеров и на корпоративных доменах Google Workspace
jane.doe@иjanedoe@— разные люди. Удалив там точки, вы склеите незнакомцев. - Удаление плюса в других сервисах — эвристика. Почти везде плюс-тег — это алиас, но почтовый сервер вправе считать
+обычным символом. Совпадение вне Gmail — сигнал, а не доказательство. - Не отклоняйте сам плюс-тег. Многие аккуратные люди используют
name+service@gmail.comна каждом сайте. Плюс-тег у нового ящика — норма; плюс-тег у ящика, у которого уже есть аккаунт, — сигнал. - Приводите к нижнему регистру перед сравнением и убирайте пробелы и конечные точки. На практике провайдеры не различают регистр в локальной части.
- У других провайдеров свои схемы алиасов (одноразовые адреса Yahoo, алиасы Outlook в одном аккаунте). Нормализацией их не поймать — тут работают сигналы устройства и сети.
Что делать при совпадении
Совпадение после нормализации означает, что новый аккаунт получает почту в ящик, у которого уже есть у вас аккаунт. Обычно правильная реакция — не ошибка, а подсказка: «У вас уже есть аккаунт с этим адресом — войти?». Для пробных периодов и бесплатных кредитов это ещё и веская причина не выдавать пробный период или отправить регистрацию на проверку. Полную схему решений см. в руководстве Как предотвратить злоупотребление пробным периодом.
Как это делает Attrelix
Каждая проверка нормализует адрес (точки Gmail, плюс-теги, googlemail.com и домены Proton), ищет существующие аккаунты с тем же ящиком и при совпадении добавляет причину alias_of_existing. Исходный адрес в ваших данных никогда не меняется, а связанные аккаунты возвращаются в ответе, чтобы вы видели всю группу.
Итог
- Gmail игнорирует точки и плюс-теги; многие провайдеры игнорируют плюс-теги.
- Храните нормализованный адрес рядом с оригиналом и индексируйте его.
- Удаляйте точки только для личного Gmail; остальные совпадения считайте сигналами.
- При совпадении предлагайте войти и не давайте второй пробный период.