一次性邮箱检测
输入一个域名,看它是否属于一次性邮箱服务商。免费、免注册 —— 我们连自己的域名也一起标出来。
20 个常见域名的现成结论
表格里的结论由检测器所用的同一份数据生成,因此永远不可能和检测结果不一致。说明栏讲的是「这是什么服务」,结论栏讲的是「黑名单怎么说它」。
| 域名 | 结论 | 这是什么 |
|---|---|---|
| gmail.com | 未被列为一次性邮箱 | Google 的个人邮箱服务。 |
| outlook.com | 未被列为一次性邮箱 | 微软的个人邮箱服务。 |
| yahoo.com | 未被列为一次性邮箱 | 雅虎邮箱。 |
| icloud.com | 未被列为一次性邮箱 | 苹果的邮箱服务,绑定 Apple 账号。 |
| proton.me | 未被列为一次性邮箱 | 注重隐私的邮箱服务商,有免费和付费方案。 |
| qq.com | 未被列为一次性邮箱 | 腾讯 QQ 邮箱,中国使用最广的邮箱之一。 |
| 163.com | 未被列为一次性邮箱 | 网易邮箱,在中国使用广泛。 |
| gmx.com | 未被列为一次性邮箱 | GMX,运营多年的免费邮箱服务商。 |
| zoho.com | 未被列为一次性邮箱 | Zoho Mail,面向企业和自有域名。 |
| simplelogin.io | 未被列为一次性邮箱 | 别名转发服务,转发到你真实的收件箱。 |
| duck.com | 未被列为一次性邮箱 | DuckDuckGo Email Protection,别名转发服务。 |
| mailinator.com | 已被列为一次性邮箱 | 公开的一次性收件箱,任何人无需注册即可打开。 |
| yopmail.com | 已被列为一次性邮箱 | 一次性收件箱服务商。 |
| guerrillamail.com | 已被列为一次性邮箱 | 一次性收件箱服务商,仍在运营的最老牌之一。 |
| sharklasers.com | 已被列为一次性邮箱 | Guerrilla Mail 的备用域名之一。 |
| 10minutemail.com | 已被列为一次性邮箱 | 短时间后自动过期的一次性收件箱。 |
| temp-mail.org | 已被列为一次性邮箱 | 一次性收件箱服务商,拥有多个地区域名。 |
| 1secmail.com | 已被列为一次性邮箱 | 一次性收件箱服务商,同时提供公开 API。 |
| trashmail.com | 已被列为一次性邮箱 | 基于转发、带有效期的一次性地址。 |
| moemail.app | 这是我们自己的域名 | 就是本站。一次性邮箱服务商 —— 见下方说明。 |
为什么给两级,而不是「是」或「否」
大多数免费检测器只回答 true 或 false,这恰好隐藏了你真正需要知道的东西:这个答案有多确定。我们用两份审核标准不同的列表,并告诉你命中的是哪一份。
已列入
域名在严格审核的黑名单里,条目经过人工复核,误报很少。如果你要做自动拦截或标记,这一级才是可以直接行动的依据。
可能
只在覆盖更广的那份列表里,那份列表牺牲精确度换覆盖率。适合作为多个信号中的一个。只凭这一级就拦截,偶尔会误伤真实用户。
未列入
两份都没有。请注意它意味着什么、不意味着什么:没有任何黑名单是完整的,一个全新的一次性域名会在一段时间内一直通过这项检测。
黑名单命中是证据,不是铁证。任何有实际后果的判断,都该结合你自己掌握的信号 —— MX 记录、域名注册时间、账号行为,或者一封确认邮件。
别名服务和一次性邮箱不是一回事
SimpleLogin、DuckDuckGo Email Protection,以及 Gmail 自带的加号地址,给你的是一个转发到你长期收件箱的地址。地址是可丢弃的,后面的收件箱不是。用户照样会读信、照样会回复、日后照样能找回账号。
各家黑名单对它们的处理并不一致,所以你可能会看到某个别名域名被标记。这一点在你决定拦截之前值得知道:拦掉别名用户,赶走的是注重隐私但完全真实的客户。一次性收件箱几分钟后就被丢弃,而别名可能比它服务的那个账号活得更久。
数据本身就有自相矛盾的地方,值得一看。`addy.io` 被列入了,而同一家公司的旧域名 `anonaddy.com` 没有;`relay.firefox.com` 被列入了,但 Firefox Relay 实际发放的别名地址用的是 `mozmail.com`,而后者根本不在列表里。这两个标记都落在「可能」这一级、而不是「已列入」—— 这正是那一级存在的意义。
我们把自己的域名也标为一次性
MoeMail 提供的就是一次性邮箱服务。我们的域名做的事情和黑名单描述的完全一致,所以诚实的答案是:它们本就该在那些列表上 —— 这个检测器也照实这么说。
我们本可以悄悄把自己排除掉。没有这么做,理由很简单:任何人花五秒钟就能拿自家域名试出来,而一个被抓到偏袒自己的工具毫无价值。如果你在运营网站、想挡掉一次性注册,你应该能用这个工具把我们也挡在外面。
网站实际上是怎么识别一次性邮箱的
像这样的黑名单查询只是第一层。真实系统会叠加好几道检查:拿域名去比对公开和商业列表、解析 MX 记录看它到底收不收信、看域名注册了多久、以及观察账号注册之后的行为。
这也是为什么有些地址明明不在任何名单上却仍被拒绝,而有些一次性地址反而能顺利通过。想看更完整的版本,我们另外写过一篇。
数据来自哪里
检测器查询两份由社区维护的开源黑名单。其中第二份是聚合器,所以下面把喂给它的仓库也一并署名,每一个都回链原始出处。我们从上游重新构建自己的副本,而不是手工改条目,所以你在这里看到的和维护者发布的一致。
- disposable-email-domains/disposable-email-domainsCC0 1.0 Universal
- disposable/disposable-email-domainsMIT
- 7c/fakefilterBSD-3-Clause
- daisy1754/jp-disposable-emailsMIT
- disposable/static-disposable-listsMIT
- FGRibreau/mailcheckerMIT
- flotwig/disposable-email-addressesMIT
- GeroldSetz/emailondeck.com-domainsCC-BY-4.0
- GeroldSetz/Mailinator-DomainsCC-BY-4.0
- martenson/disposable-email-domainsno licence declared
- wesbos/burner-email-providersMIT
这不是数据来源的完整清单。那个聚合器还会直接抓取一次性邮箱网站,那些没有仓库、也没有许可可以署名。它的源码是公开的,你可以自己查全量: generator.py
两份列表都不声称自己是最新或完整的,维护者自己也明说了这一点。域名会转手,服务会关停,新的每天都在出现。请把这里得到的结果当作社区维护的一份快照,而不是实时权威。
免费一次性邮箱检测 API
这个页面跑的就是这个查询,只是换成 JSON 接口。不需要 API key、不需要注册、没有配额要充值 —— 在注册表单里调、在 Worker 里调、在 shell 脚本里调都可以。它读的是上面写明的同两份列表,所以接口给出的答案和你在这个页面看到的完全一致。
curl "https://moemail.app/api/tools/v1/disposable-email/check?domain=mailinator.com"端点
https://moemail.app/api/tools/v1/disposable-email/check?domain=…查一个域名,或者一个完整邮箱地址 —— 地址前半段会被丢弃。返回归一化后域名的判定结果。
https://moemail.app/api/tools/v1/disposable-email/dataset当前回答问题的是列表的哪一份快照:各层规模、构建时间,以及每个上游文件下载时的 SHA-256。如果你需要记录某个决定是由哪份数据做出的,在启动时调一次就够了。
响应字段
domainstring- 判定所针对的归一化域名:已转小写、去掉地址前半段和结尾的点。请拿它来做比对,而不是拿你发过去的原始字符串。
disposableboolean- 域名出现在任意一份列表里(包括我们自己的域名)时为 true。这是粗粒度的答案 —— 在用它拦注册之前,请先读下面那段警告。
verdict"high" | "medium" | "none" | "ours"- 命中的是哪一层。
high是人工严格维护的那份列表。medium只出现在那份广泛聚合的列表里。none是两份都没有。ours是 MoeMail 自己的收件域名 —— 它确实是一次性邮箱,而且没有任何第三方列表收录它。
不要只看 disposable 就拦人
我们知道的约 75,000 个域名里,medium 占了大约 66,000 个,而它来自一份没有人手工审核的广泛聚合列表。把它们全部拦掉,一定会误伤真实用户。如果一次误判会让你丢掉一个客户,那就只对 verdict === "high" 做拦截,把 medium 当成「要求二次验证」的理由,而不是「拒绝」的理由。disposable 这个字段的存在,是为了让原本对接布尔型接口的代码能直接换过来,不是因为布尔值是正确的决策边界。
错误
每个错误都同时带一个机器可读的 code 和一段给人看的 error。请对 code 做分支判断:文案随时可能改写,而这些 code 在 API 版本不变的前提下不会变。
| 400 | missing_domain | 没有传 domain 参数,或者传了空值。 |
| 400 | invalid_domain | 不是一个像样的域名。domain 被重复传入时、以及传入 Unicode 域名时也返回这个 —— Unicode 域名请先转成 punycode(xn--…)。 |
| 400 | input_too_long | 参数超过 320 个字符,而这已经是一个真实地址可能达到的最大长度。 |
限流、缓存与稳定性
每个 IP 每 10 秒 17 次,由 Cloudflare 在边缘执行,不是在这个 API 内部。没有任何 key 能提高这个上限,也没有付费档 —— 如果你需要的量超过它,请直接下载全量列表,在本地查。
超过之后,Cloudflare 会在边缘直接拦掉,请求根本到不了这个 API:429、Retry-After: 10,以及一小段 text/plain 正文 —— 不是上面那个 JSON 结构。有两个后果需要提前考虑。拦截响应**不带** Access-Control-Allow-Origin,所以浏览器看到的是一个不透明的网络错误,而不是一个能读的 429;而且因为请求从未到达这里,也就没有 code 字段可以分支。请把「突发之后立刻失败的请求」当作被限流处理。
响应可缓存一天(s-maxage=86400),并带一个由上游文件哈希推导出来的 ETag,所以在数据没变的期间,条件请求几乎不花任何成本。列表是构建时编译进去的,因此在下一次部署之前答案不会改变。有一个后果值得知道:命中缓存的请求根本到不了限流器,所以这个限额是在塑造流量,而不是在做硬保证。
所有响应都带 Access-Control-Allow-Origin: *,因此浏览器可以直接从你的注册表单调用它,中间不需要任何代理。
v1 承诺的是形状,不是数据:字段不会被删除或改名,状态码的含义也不会变 —— 除非路径里出现新的版本段。至于判定结果本身,只要上游列表变了它就会变。
代码示例
每一段都是对 verdict 做判断,而不是对布尔值做判断,因为后者并不是你真正想做的那个决策。
curl "https://moemail.app/api/tools/v1/disposable-email/check?domain=mailinator.com"
# {"domain":"mailinator.com","disposable":true,"verdict":"high"}
curl "https://moemail.app/api/tools/v1/disposable-email/dataset"
# {"high":8742,"medium":66885,"total":75627,"builtAt":"…","status":"upstream",…}const ENDPOINT = "https://moemail.app/api/tools/v1/disposable-email/check"
async function verdictFor(domain) {
const res = await fetch(`${ENDPOINT}?domain=${encodeURIComponent(domain)}`)
const body = await res.json()
if (!res.ok) throw new Error(body.code) // branch on `code`, never on `error`
return body.verdict
}
// "medium" means "only in the broad aggregator list" — a signal, not a verdict.
// Gate signups on the tier you are willing to defend to a real user.
const verdict = await verdictFor("mailinator.com")
const reject = verdict === "high" || verdict === "ours"import requests
ENDPOINT = "https://moemail.app/api/tools/v1/disposable-email/check"
def verdict_for(domain: str) -> str:
r = requests.get(ENDPOINT, params={"domain": domain}, timeout=5)
r.raise_for_status()
return r.json()["verdict"]
# Note: use requests (or set an explicit User-Agent). Cloudflare's managed bot
# rules block the default "Python-urllib/3.x" agent with a 403 before the
# request ever reaches this API.
if verdict_for("mailinator.com") in ("high", "ours"):
... # reject the signup<?php
function verdict_for(string $domain): string {
$url = 'https://moemail.app/api/tools/v1/disposable-email/check?domain=' . urlencode($domain);
$ctx = stream_context_create(['http' => [
'timeout' => 5,
// Send a real User-Agent: identify your app, and stay clear of any
// bot rule that keys on a default library agent.
'header' => "User-Agent: my-app/1.0\r\n",
]]);
$body = json_decode(file_get_contents($url, false, $ctx), true);
return $body['verdict'];
}
if (in_array(verdict_for('mailinator.com'), ['high', 'ours'], true)) {
// reject the signup
}export default {
async fetch(request) {
const email = new URL(request.url).searchParams.get("email") ?? ""
const domain = email.split("@").pop()
// Responses are cacheable (s-maxage=86400), so the Cache API turns a
// repeated lookup into zero subrequests.
const res = await fetch(
`https://moemail.app/api/tools/v1/disposable-email/check?domain=${encodeURIComponent(domain)}`,
{ cf: { cacheTtl: 86400, cacheEverything: true } },
)
const { verdict } = await res.json()
return Response.json({ allow: verdict !== "high" && verdict !== "ours" })
},
}这些列表由公开的上游数据编译而成,其中一部分的许可证要求署名信息随数据一起传递。因此每个响应都带一个 Link: rel="license" 头指回上面的署名清单,而完整的许可证文本随可下载数据集的文件头一起分发。
和其它免费查询 API 的对比
免费、不需要 key 的一次性域名查询接口有那么几个。下面是这一个和它们的区别 —— 也包括它做得更少的地方。
| 对比项 | MoeMail | Kickbox Open | DeBounce Free | validator.pizza |
|---|---|---|---|---|
| 不需要 API key 或注册 | 是 | 是 | 是 | 是 |
| 浏览器可直接调用(CORS) | 是 | 否 | 是 | 是 |
| 置信度粒度 | 两层,另加自有域名 | 单一布尔 | 单一布尔,但以字符串返回 | 单一布尔 |
| 公开数据来源,并给出校验和 | 是 | 否 | 否 | 否 |
| 可下载全量列表 | 是 | 否 | 否 | 否 |
| 数据版本可查询 | 是 | 否 | 否 | 否 |
| 实时 MX / 域名年龄查询 | 否 | 否 | 否 | 是 |
| 明示的限流 | 每 10 秒 17 次,有文档 | 未标明 | 未标明 | x-ratelimit-limit: 1 |
表中每一格都是在 2026-08-22 通过实际调用对方端点核实的,请求形状与上面那段 cURL 示例一致 —— 你可以自己复跑。这里没有一条取自厂商的宣传页面:曾有一条搜索结果声称 Kickbox 那个端点支持 CORS,实际上并不支持。
这四个都是黑名单查询。它们回答的只是「这个域名是否已知为一次性邮箱」,仅此而已;包括本接口在内,没有一个能告诉你某个邮箱是否真实存在。validator.pizza 走得最远,它会实时解析 MX 记录和域名年龄 —— 如果你要的是这个,就用它。
付费的邮箱验证服务 —— ZeroBounce、Kickbox 自家的验证 API、Bouncer —— 做的事比这里任何一个都多得多,包括邮箱是否真实存在、以及 catch-all 检测,并且按次收费。它们没有进这张表,因为拿一个免费黑名单自己挑的维度去衡量它们,是一张作弊的表。