指南

Gmail 点号和加号别名:如何识别重复注册

j.doe+7@gmail.com 和 jdoe@gmail.com 是同一个收件箱。Gmail 地址规则如何运作、JavaScript 和 Python 版的规范化函数,以及容易踩坑的边界情况。

阅读约 6 分钟 · 更新于 2026-10-31 · Attrelix

一个收件箱,无数个地址

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 去掉点号;其他匹配视为信号。
  • 匹配时引导用户登录,不要再给第二次试用。

更多指南