Email Spam Tester

邮件、收件箱和域名的
垃圾邮件检查 API

向我们发送一封真实邮件,或只提供一个域名。所有结果都以 JSON 返回。

无需密钥,无需账户。

请求

# reserve a single-use address

$ curl -sX POST '.../api/v1/inbox?lang=en'

# send your message to that address, then

$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c/status'

# read the report

$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c'

响应

200 OK

{
  "address": "test-k7m2x9qplw4tz8vn3b6c@t.email-spam-tester.com",
  "slug": "k7m2x9qplw4tz8vn3b6c",
  "expires_at": "2026-10-31T13:00:00Z"
}

200 OK

{
  "analysis_status": "checks_ready",
  "ai_status": "running",
  "checks_done": 42,
  "checks_total": 42
}

200 OK

{
  "score_ours": 86.4,
  "score_compat": 9.2,
  "subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0},
  "complete": true,
  "checks": [{"id": "auth.dmarc", "status": "warn"}],
  "fixes": [{"id": "dmarc-enforce", "gain_ours": 4.0}]
}

请求

# create a test

$ curl -sX POST '.../api/v1/placement' \ -d '{"public_results_accepted":true}'

# put the marker in the subject, send once to all, then

$ curl -s '.../api/v1/placement/wR3kP9xLq2vT8mZc'

响应

201 Created

{
  "marker": "est-3f9a1c7e2b4d6a80c5e1f2d3",
  "status": "waiting",
  "results": [{"provider": "gmail", "placement": "pending"}],
  "fleet": {"status": "observing", "results": [
    {"provider": "yahoo", "placement": "pending"},
    {"provider": "outlook", "placement": "pending"}
  ]}
}

200 OK

{
  "status": "complete",
  "results": [{"provider": "gmail", "placement": "primary"}],
  "fleet": {"status": "finished", "results": [
    {"provider": "yahoo", "placement": "inbox"},
    {"provider": "outlook", "placement": "spam"}
  ]}
}

请求

# no email needed, one GET

$ curl -s '.../api/v1/infra/check?domain=example.com'

# compare with your last run

$ curl -s '.../api/v1/infra/check?domain=example.com&diff=true' \ | jq '.diff'

响应

200 OK

{
  "domain": "example.com",
  "ok": false,
  "status": "fail",
  "score": 78,
  "coverage": {"answered": 7, "total": 8},
  "sections": {"ptr": {"status": "fail", "core": true}}
}

200 OK

{
  "changed": true,
  "worsened": true,
  "status_from": "pass",
  "score_from": 100,
  "changes": [{"path": "dkim.key.mail.sha256", "kind": "removed",
               "severity": "critical", "effect": "worsened"}]
}
本页内容

邮件测试

我们端到端检查一封真实邮件:内容、签名、邮件头以及发送它的服务器。你会得到一个评分、修复项列表,以及这些修复项背后的每项检查结果。

快速开始

三次调用。无需密钥、账户或注册。 两次请求和一封电子邮件。由于分析需要几秒钟,因此才需要第三次调用。

  1. 预留一个地址

    向收件箱端点发送 POST 请求。你会得到一个仅接收一封邮件且在一小时后过期的地址,以及其他所有内容所关联的标识符。

    请求

    # 1. reserve a single-use address
    curl -sX POST 'https://email-spam-tester.com/api/v1/inbox?lang=en'

    响应

    {
      "address": "test-<slug>@t.email-spam-tester.com",
      "slug": "<slug>",
      "expires_at": "2026-01-01T12:00:00Z"
    }
  2. 向该地址发送真实邮件

    通过 SMTP,从将要发送营销邮件的平台发送。一半的检查会读取发送平台添加的邮件头,因此手动编写的邮件测量的是错误的对象。

    请求

    # 2. send your message to that address, from your own platform
    To: test-<slug>@t.email-spam-tester.com
  3. 轮询状态,然后读取报告

    状态端点返回的数据只有几百字节,并会告诉你是否已经值得获取完整报告。报告本身有数千行。

    请求

    # 3. poll
    curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>/status'

    响应

    {
      "slug": "<slug>",
      "analysis_status": "checks_ready",
      "ai_status": "running",
      "checks_done": 42,
      "checks_total": 42
    }

    请求

    # 4. read the report once analysis_status is checks_ready
    curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>'

    响应

    {
      "report_url": "https://email-spam-tester.com/t/<slug>",
      "score_ours": 86.4,
      "score_compat": 9.2,
      "subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0, "compliance": 75.0},
      "complete": true,
      "checks": [
        {
          "id": "auth.dmarc",
          "status": "warn",
          "title": "DMARC result",
          "summary": "DMARC passes, but the policy is p=none.",
          "weight_ours": -4.0,
          "evidence": {"policy": "none", "aligned": "dkim"},
          "citations": {"standards": [{"title": "RFC 9989 §4.7", "quote": "..."}]}
        }
      ],
      "fixes": [
        {"id": "dmarc-enforce", "gain_ours": 4.0, "gain_compat": 0.0,
         "fix": {"title": "Move DMARC to quarantine", "severity": "medium"}}
      ]
    }

预留一个地址,发送你原本准备发给邮件列表的邮件,然后读取报告。页面显示的所有内容都包含在 JSON 中,包括评分、全部 42 项检查及其证据,以及每项发现所依据的标准章节。

前 100,000 份报告免费,无需密钥,也无需账户。如果你接入的是代理而不是脚本,MCP 服务器比轮询更合适。

端点

基地址为 https://email-spam-tester.com。所有响应均为 JSON。

POST/api/v1/inbox

预留一个一次性地址。两个参数均为可选参数。

lang修复方案和各项检查结果所使用的语言,以 ISO 代码表示。此时即确定语言,因为邮件会在几分钟后通过 SMTP 到达,并且不包含任何关于等待接收者的信息。未知代码会回退到英语。
utm_source, utm_medium, utm_campaign传递给我们的分析系统。如果你要衡量自己的集成效果,这些参数会很有用。

GET/api/v1/tests/{slug}/status

轮询成本低。仅返回两个状态字段和检查进度,不返回其他内容。

请轮询此端点,而不是报告端点。analysis_status 会先变为 checks_ready,AI 方案会在大约一分钟后出现在 ai_status 下,因此只需要确定性检查结果的调用方不必等待该方案。

GET/api/v1/tests/{slug}

完整报告。地址已预留但尚未收到任何内容时返回 202,收到后返回 200。

GET/api/v1/tests/{slug}/message

邮件被投递时的原始内容:按线路顺序排列的每个请求头、两种正文、附件列表和原始源代码。由于报告会被轮询,而这些内容的大小可能达到一兆字节,因此需要单独获取。

原始邮件按其自身的时限删除,早于报告。之后,此端点返回原因而不是邮件源文。

PUT/api/v1/tests/{slug}/locale

更改尚未使用的预留地址的语言。适用于已请求地址后才得知用户阅读哪种语言的代理。邮件到达后将拒绝更改,因为此时分析已在运行。

收件箱投递位置测试版

向一组测试收件箱发送一封邮件,查看它在 Gmail、Outlook、Yahoo 和其他提供商处进入了哪个文件夹:收件箱、推广邮件或垃圾邮件。

快速开始

  1. 创建测试

    向投递位置端点发出 POST 请求。你会收到一个标记和测试收件箱列表。

    请求

    # 1. create a test
    curl -sX POST 'https://email-spam-tester.com/api/v1/placement' \
      -H 'Content-Type: application/json' \
      -d '{"public_results_accepted":true}'

    响应

    {
      "slug": "<slug>",
      "marker": "est-3f9a1c7e2b4d6a80c5e1f2d3",
      "status": "waiting",
      "deadline": "2026-10-31T12:30:00Z",
      "poll_after_seconds": 60,
      "results": [
        {"address": "<seed>", "provider": "gmail", "kind": "Gmail",
         "placement": "pending", "observed_at": null}
      ],
      "fleet": {
        "status": "observing",
        "results": [
          {"address": "<mailbox>", "provider": "yahoo", "available": true,
           "placement": "pending", "coverage": "pending"}
        ]
      }
    }
  2. 向每个收件箱发送一封邮件

    将标记放入主题,并通过你常用的平台一次性发送到所有地址。

    请求

    # 2. one message to every address, with the marker in the subject
    Subject: October invoice est-3f9a1c7e2b4d6a80c5e1f2d3
    To: <seed>, <mailbox>, ...
  3. 轮询文件夹

    每个地址都会填入其提供商和文件夹。轮询直到状态不再是 waiting。

    请求

    # 3. poll for the folders
    curl -s 'https://email-spam-tester.com/api/v1/placement/<slug>'

    响应

    {
      "status": "complete",
      "received": 2,
      "total": 2,
      "results": [
        {"address": "<seed>", "provider": "gmail", "kind": "Gmail",
         "placement": "primary", "observed_at": "2026-10-31T12:04:11Z"},
        {"address": "<seed>", "provider": "gmail", "kind": "Google Workspace",
         "placement": "promotions", "observed_at": "2026-10-31T12:04:11Z"}
      ],
      "fleet": {
        "status": "finished",
        "results": [
          {"address": "<mailbox>", "provider": "yahoo", "available": true,
           "placement": "inbox", "coverage": "ok"},
          {"address": "<mailbox>", "provider": "outlook", "available": true,
           "placement": "spam", "coverage": "ok"}
        ]
      }
    }

端点

An optional test using public GMass seed inboxes and available project test mailboxes, alone or alongside the email score. Explain to the sender that GMass receives their email and publishes its subject, sender name and placement before creating a test. Use all test mailboxes for non-confidential test messages only.

GET /api/v1/placement/availability

Returns providers: the provider identifiers of currently healthy, admitted project mailboxes. No addresses or credentials are exposed. This read does not create a test or contact GMass. Actual recipients are allocated at creation and may differ as availability or capacity changes.

POST /api/v1/placement

Send JSON {"public_results_accepted":true}. Returns HTTP 201 with slug, marker, results (the seed addresses), deadline and expires_at. Limit: 20 tests per IP per UTC day.

For one-send combined testing, first reserve an email score address and include its score_slug in the placement creation JSON. Repeated creation for that score returns the same placement test. Send the marked email to the score address, every returned seed and every available fleet.results address; keep the main /t/<score_slug> report link. Creating a link after the score address was used or expired returns HTTP 409.

GET /api/v1/placement/by-score/{score_slug}

Read and refresh the placement run attached to the main email test. The response has the same format and polling limits as the standalone endpoint below. HTTP 404 means placement was not included or its stored results have been removed.

GET /api/v1/placement/{slug}

Use poll_after_seconds (normally 60 seconds) while the page is open. Upstream errors trigger a shared cooldown. Add the marker to the subject and send through the sender's normal platform to every seed. Observations are saved for 30 days. Collection ends after 30 minutes or when all seeds have results.

status: waiting, complete or timed_out. Each result has an address, provider, kind, placement and observed_at. Placement is primary, promotions, inbox, updates, social, forums, spam, unknown, pending or not_observed. Missing results do not mean Spam; Promotions is an inbox category. provider_error indicates an upstream outage without discarding saved observations. HTTP 404 means unknown, 410 expired, 429 quota exhausted, and 503 no test inboxes available at creation.

The optional fleet object contains independently collected project mailbox results, with status observing, settling or finished. Refresh every 30 seconds until it finishes, even when Gmail has completed. Each fleet result includes address, provider, available, placement, category and coverage. Exclude unavailable addresses from new sends; retain their saved observations. Category data may be unavailable even when the physical folder is known.

If GMass is unavailable at creation but project mailboxes can be allocated, provider is fleet and the top-level seed results are empty. Use fleet.results; do not interpret an empty Gmail list as successful delivery. Existing runs never gain new recipient addresses silently.

基础设施检查

一次 GET 请求即可检查域名的邮件设置,无需发送任何内容;它会保留结果,并告诉你自上次运行以来发生了哪些变化。无需密钥。在 cron 中,当域名损坏或其设置发生重要变化时,下面这行命令会以非零状态退出。

快速开始

  1. 发起一次 GET 请求

    传入域名。ip 添加你的发件地址,selector 指定要读取的 DKIM 选择器。

    请求

    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true'
  2. 读取判定结果

    ok 是供脚本使用的结果,sections 显示哪个部分失败。

    响应

    {
      "id": "ir_01JB8Y4T2M6K9QZ7H3V5N1XWDA",
      "domain": "example.com",
      "checked_at": "2026-10-31T12:00:00Z",
      "ok": false,
      "status": "fail",
      "score": 78,
      "coverage": {"answered": 7, "total": 8},
      "ips": [{"ip": "203.0.113.5", "sources": ["mx", "spf"], "managed": false}],
      "sections": {
        "dkim": {"status": "pass", "core": true, "findings": [], "data": {}},
        "ptr": {"status": "fail", "core": true, "findings": [], "data": {}}
      },
      "not_checked": [
        {"check": "dkim_signature", "reason": "needs_a_message"},
        {"check": "alignment", "reason": "needs_a_message"}
      ],
      "diff": {
        "baseline": {"id": "ir_01JB2...", "checked_at": "2026-10-24T12:00:00Z"},
        "first_run": false,
        "changed": true,
        "worsened": true,
        "status_from": "pass",
        "score_from": 100,
        "changes": [
          {"path": "dkim.key.mail.sha256", "section": "dkim", "kind": "removed",
           "severity": "critical", "effect": "worsened", "from": "9f2c...", "to": null}
        ],
        "not_compared": [
          {"path": "blocklist_ip.203.0.113.5.bl.spamcop.net.listed", "reason": "lookup_failed"}
        ]
      }
    }
  3. 将它加入 cron

    使用 diff=true 时,每次运行都会与你的上一次运行进行比较,jq 会将结果转换为退出码。

    请求

    # exits non-zero if the domain is broken or its setup changed
    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true' \
      | jq -e '.ok and (.diff.changed | not)'
domain必填。接受与工具相同的内容:域名、URL 或电子邮件地址。
ip你的发信地址。如需传入更多地址,可重复此参数,最多 6 个。
selectorDKIM 选择器。如需传入更多选择器,可重复此参数,最多 10 个。你传入的每个选择器都必须存在,否则 DKIM 部分失败。
helo你的服务器在 HELO 中提供的名称,并将其与服务器的 PTR 进行比较。
account请求所针对的账户。使用服务于多人的密钥时为必填项。
checks要运行的部分,以逗号分隔。默认运行全部部分。
difftrue 会将本次运行与该域名的上一次运行进行比较。
since7d、12h 或 ISO 8601 日期。与 12 小时范围内最接近该时刻的运行进行比较,否则与该时刻之前的最后一次运行进行比较。启用 diff。
baseline要用于比较的某次运行的 id。启用 diff。
freshtrue 会跳过 60 秒缓存。

读取响应

完成的检查会返回 200,判定结果位于正文中。status 是必需部分中的最差状态:spf、dkim、dmarc、ptr、blocklist_ip、blocklist_domain、mx 和 smtp。必需部分中的 unknown 计为 warn。当 status 为 pass 或 warn 时,ok 为 true。score 根据已返回结果的必需部分计算,范围为 0 到 100;当 error 和 unknown 导致有结果的适用权重不足一半时,score 为 null。mta_sts、tls_rpt、bimi、dnssec、dane、ns 和 registration 会被报告和比较,但不影响 ok 或 score。

一个部分可以是 pass、warn、fail、error(我们无法检查)、unknown(信息不足)或 skipped(不适用)。skipped 不影响结果,原因位于 not_checked 中。dkim_signature 和 alignment 始终存在,因为它们需要真实邮件。

ip 和 selector 会改变什么

PTR 和黑名单与地址有关,因此一次运行需要一些地址。它使用你传入的 ip 值。如果没有传入,则从你的 MX 主机以及根 SPF 记录中仅包含单个地址的 ip4: 和 ip6: 项中最多获取四个地址。已知邮件提供商的地址会被列为 managed 并不进行检查,如果没有剩余地址,ptr 和 blocklist_ip 会返回 skipped。无法从 DNS 读取 selector,因此一次运行会尝试你提供的 selector、你之前的运行找到的 selector,以及常用名称列表。什么也找不到并不能证明什么,dkim 会返回 unknown。如果你从自己的服务器发送邮件,请同时传入这两项。

更改了什么

diff.changes 中的每个条目都有一个 path、一个 kind(added、removed、changed)、一个 severity(critical、warning、info)和一个 effect(worsened、improved、neutral)。只有 critical 和 warning 会设置 diff.changed,因此轮换为相同长度的 DKIM 密钥、新增 MX 地址或续期证书不会导致 cron 行失败。diff.worsened 取决于任一变更的 effect。首次运行时没有可供比较的内容,diff.first_run 会对此进行说明。

基线始终是你自己的某次运行,因此其他人在你的两次运行之间检查该域名不会隐藏任何内容。本次无法读取的任何内容都会进入 diff.not_compared,并保留其上次已知值,这意味着在中断期间发生的更改会在查询恢复正常后显示。使用不同 ip 或 selector 的运行仍属于同一序列,而该运行未请求检查的内容也不会进行比较。

为什么定时检查应使用密钥

如果没有密钥,你的历史记录归属于你 IP 地址的带密钥哈希,因此地址更改后历史记录就会中断,而且同一地址后的用户会共享历史记录:同事的运行会移动你的基线。在 Authorization: Bearer 中使用个人 API 密钥后,历史记录会跟随该密钥。带密钥的运行会保留 365 天,并且只能使用该密钥打开。不带密钥的运行会保留 30 天,任何拥有其 id 的人都可以打开。

每个 IP 每分钟 6 个请求、每天 50 个请求,或每个密钥每分钟 30 个请求、每天 500 个请求。超过限制时,响应为 429,并包含 Retry-After。60 秒内的相同请求会来自缓存,标记为 cached: true,不写入运行记录,也不计入限制。读取已存储的运行时,每个客户端每分钟允许 120 个请求。包含 Retry-After 的 503 表示正在运行的检查过多,或者在读取已存储的运行时表示存储不可用。401 表示密钥错误。422 包含 detail.code:invalid_domain、invalid_ip、invalid_selector、invalid_check、invalid_since、unknown_baseline 或 account_required。

端点

GET/api/v1/infra/check

运行检查。参数见上表。

GET/api/v1/infra/runs/{public_id}

一个完整的已存储运行。如果不存在或属于其他密钥,则返回 404。

GET/api/v1/infra/domains/{domain}/runs

你对某个域名的运行记录,按时间从新到旧排列:id、时间、状态、分数和变更数量。接受 limit(1 到 100,默认为 30)和 before(一个运行 id)参数。

GET/api/v1/infra/diff

对两个已存储运行进行相同比较,?from=<id>&to=<id>。你需要拥有两者的访问权限。

GET/api/v1/infra/checks

每个部分及其权重、评分版本和限制。

单项检查

每次调用只回答一个问题,不保留历史记录。除邮件头工具外,每个工具都会独立运行基础设施检查的一部分;邮件头工具会读取你已经收到的邮件。

快速开始

  1. 选择检查项

    从下面的列表中选择工具,并传入其要求的域名、地址或 IP。

    请求

    curl -s 'https://email-spam-tester.com/api/v1/tools/spf?domain=example.com'
  2. 查看状态和检查结果

    每个工具都会返回状态及其检查结果。后续字段取决于具体工具。

    响应

    {
      "tool": "spf",
      "query": {"domain": "example.com"},
      "checked_at": "2026-10-31T12:00:00Z",
      "duration_ms": 412,
      "status": "fail",
      "findings": [
        {"code": "spf.too_many_lookups", "level": "fail",
         "params": {"limit": 10, "count": 12},
         "message": "RFC 7208 §4.6.4 allows at most 10 DNS lookups, and this record needs 12, so receivers return permerror."}
      ],
      "record": "v=spf1 include:_spf.example.net ~all",
      "lookups": {"count": 12, "limit": 10, "void": 0}
    }

端点

所有工具都会返回 200,其中包含一个状态和一个发现项列表,每个发现项都有代码及其参数。状态为 pass、warn、fail 或 error,与基础设施检查共用的工具还可以返回 unknown 或 skipped。超时的查询或拒绝查询的列表绝不会计为 pass。所有工具合计每个 IP 每分钟 30 个请求、每天 300 个请求;超过限制时返回 429,并带有 Retry-After。

GET/api/v1/tools/spf

域名的 SPF 记录:其语法、跟踪的每个 include 和 redirect,以及整个树的 DNS 查询次数是否超过十次的限制。传入 ?domain=example.com。

GET/api/v1/tools/dmarc

域名的 DMARC 记录,或者当该域名没有记录时其组织域的 DMARC 记录:标签、策略,以及每个外部报告地址是否已同意接收报告。传入 ?domain=example.com。

GET/api/v1/tools/dkim

为选择器发布的 DKIM 密钥:是否存在且可解码、其类型和大小,以及撤销和测试标志。传入 ?domain=example.com&selector=s1。

GET/api/v1/tools/blocklist

根据报告所使用的 DNS 阻止列表检查 IPv4 地址、IPv6 地址或域名,并提供每个列表的结果。传入 ?target=203.0.113.5。

GET/api/v1/tools/mx

域名的 MX 记录,按发件方尝试的顺序排列,并列出每台主机的 IPv4 和 IPv6 地址。系统会报告空 MX、没有 MX 的域名、属于 IP 地址或 CNAME 的主机以及无法解析的主机,也会报告 MTA-STS 和 TLS-RPT 记录。传入 ?domain=example.com。

GET/api/v1/tools/bimi

分四步检查域名的 BIMI 配置:BIMI 所要求的 DMARC 策略、default._bimi 处的记录、依据 Tiny PS 配置文件检查的 SVG 徽标,以及标记证书及其类型、域名和到期时间。传入 ?domain=example.com;要使用 default 以外的选择器,还需传入 &selector=。

GET/api/v1/tools/ptr

某个地址的 PTR 记录,以及其中是否有任何名称可解析回该地址。查询失败时状态为 error;缺少记录时状态为 fail。传入 ?ip=8.8.8.8。

GET/api/v1/tools/mta-sts

域名的 MTA-STS 记录及其指向的策略文件:模式、列出的主机,以及策略遗漏的任何 MX 主机。传入 ?domain=example.com。

GET/api/v1/tools/tls-rpt

域名的 TLS-RPT 记录,以及接收其报告的地址。传入 ?domain=example.com。

GET/api/v1/tools/dnssec

根据域名区域的 DNSKEY 和 DS 记录,判断该区域已签名、未签名还是已损坏。错误签名会与解析器故障区分开来。传入 ?domain=example.com。

GET/api/v1/tools/dane

MX 主机的 TLSA 记录,并在能够读取主机提供的证书时与该证书进行比较。传入 ?domain=example.com。

GET/api/v1/tools/smtp

前两个 MX 主机上的 STARTTLS 和证书:TLS 版本、签发者、到期日期,以及证书链和名称是否有效。我们只连接到你所查询域名下的主机并跳过邮件服务提供商,而且每个地址的结果会共享 6 小时。不会发送邮件。传入 ?domain=example.com。

GET/api/v1/tools/ns

域名的名称服务器,以及其区域是否有 SOA 记录。只有一个名称服务器会触发 warn。传入 ?domain=example.com。

GET/api/v1/tools/registration

根据 RDAP 获取域名注册的到期时间。剩余时间少于 30 天会触发 warn。没有 RDAP 服务的区域返回 skipped。传入 ?domain=example.com。

POST/api/v1/tools/header

已接收邮件的标头,以 JSON {"headers": "..."} 或 text/plain 形式发送:逐跳路由及延迟、TLS 和时钟偏差、接收方自身的 Authentication-Results、From、DKIM d= 和 Return-Path 域名的对齐情况,以及 DKIM、ARC、退订和垃圾邮件过滤器标头。首个空行之后的所有内容都会在不读取的情况下丢弃。标头仅在内存中处理,不会存储、缓存或记录。

每晚检查域名。
邮件发出前先测试。

所有产品共用

访问方式、密钥、报告格式、状态、错误,以及供机器使用的 OpenAPI 和 llms.txt。

身份验证

没有身份验证。无需申请密钥,无需设置请求头,也无需创建账户。返回的 slug 就是访问凭证:持有它的任何人都可以读取该报告,其他人无法猜出它。

这也意味着应像对待密码一样对待 slug。任何持有链接的人都可以通过报告查看主题行、发件人、退信地址和邮件的完整源代码。

个人 API 密钥

Everything above works without a key. A key is for automation platforms such as Zapier, where every user's calls come from the platform's servers and per-IP limits would be shared by all of them. With a key, limits count per key (50 tests a day, 3 with placement, 5 permanent mailboxes), the key's tests form a history, and the key can keep permanent mailboxes whose reports only it can read. Send the key as Authorization: Bearer est_live_… on any call on this page. The routes below also take account, a short name of your choosing ([A-Za-z0-9_-], up to 64 characters) that keeps separate lists under one key. GET /api/v1/installations/tests requires it; pass the same one on POST /api/v1/inbox so the test shows up there. The Zapier integration uses zapier.

POST /api/v1/keys

Send JSON {"email":"you@example.com"}. Returns HTTP 201 with key and email. The key is shown once; only its hash is kept. Asking again gives a new key and leaves the earlier ones working. Limit: 5 keys per IP per UTC day. The form on /zapier/ calls this.

GET /api/v1/keys/me

Returns email, key_prefix and created_at of the key in the header, or HTTP 401. Use it to check a key.

GET /api/v1/installations/tests

The key's tests, newest first: ?account=…&limit=50 (up to 100), and before=<slug> for the next page. Each item has slug, created_at, analysis_status (waiting or expired before an email arrived), score_ours, score_compat, placement and changes, the checks that moved since the previous test of the same sending domain. Read the full report at /api/v1/tests/{slug}.

POST /api/v1/installations/mailboxes

Send JSON {"domain":"example.com","account":"…"}. Returns the permanent mailbox of that sending domain: id, address, domain, state, daily_cap and created. HTTP 201 when it is new, 200 when it already existed, 409 when the key keeps as many mailboxes as it may. Subscribe the address to a newsletter or a sequence and every email that arrives is checked. GET on the same path with ?account=… lists them, and DELETE /api/v1/installations/mailboxes/{mailbox_id} stops one.

GET /api/v1/installations/mailboxes/{mailbox_id}/letters

The emails that arrived, oldest first, paged with after_id and next_after_id. settled=true ends the page before the first email still being checked, so paging never skips one. newest=true turns the order round, for a quick look at the latest; settled does nothing with it. Each has test_id, slug, received_at, analysis_status, score_ours, score_compat, subject, from_addr and kind.

GET /api/v1/installations/letters/{slug}

The report of one email in a permanent mailbox, the same JSON as /api/v1/tests/{slug} with report_url null: there is no public page for it. HTTP 410 once the report has expired.

阅读报告

包含结果的字段,按你可能需要的顺序排列。

score_ours0 到 100。我们的模型。身份验证和基础设施占据大部分权重,因为它们会在过滤器读取邮件正文中的任何文字之前决定邮件能否送达。
score_compat0 到 10。复现人们已用于比较的 SpamAssassin 风格分数,使报告能够与其他地方看到的结果进行比较。
subscores每个部分采用相同的 0 到 100 分制:auth、infra_spam、content、compliance。
checks[]全部 42 项,每项都包含状态、单行结论、作为判断依据的证据,以及对两个分数的影响。
checks[].citations发现依据:RFC 中的对应章节、逐字引用的原文,以及 Google 声明其自身要求的页面。这些内容是人工整理而非自动生成,因此可以信赖。
fixes[]按顺序列出需要更改的内容,以及每项更改对应的分值。收益通过对报告重新评分计算得出,而非估算。
complete当某项检查无法运行时为 False。未检查的项目绝不会被视为通过,因此在该值变为 true 之前,应将分数视为乐观估计。
report_url供人阅读的页面。应将它交给相关人员,而不是给他们一大段 JSON。

状态

检查有五种状态,其中两种状态之间的差异比看起来更重要。

pass检查已运行,且未发现任何问题。
warn值得修复。会扣分。
fail会影响邮件送达。扣除更多分数。
skip不适用。没有要扫描的附件,也没有要评估的 HTML 部分。不算通过。
error我们无法确定。将其排除在评分之外并标记,而不是计为通过。

analysis_status 依次为 received、analyzing、checks_ready、failed。ai_status 依次为 pending、running、ready、fallback、error。确定性报告在 checks_ready 时即为最终结果;ai_status 只会添加方案。

可能返回的内容

202该地址已被保留,且尚未收到邮件。响应正文包含地址、到期时间和语言,因此即使调用方并未创建该保留,也仍可显示这些信息。
404不存在此 slug。它从未存在,或者该保留已被遗忘。
410该地址在收到邮件前已过期。
409你尝试在邮件已经到达后更改语言。
429你的地址已达到免费测试限额。目前此服务没有每人限额;如果以后设置了限额,响应正文会说明限额何时重置。

值得了解的四件事

每个地址仅限一封邮件

第二封会被拒收。你之前的报告保持不变,这正是这样设计的目的。

一小时内使用

地址会过期;报告不会。报告链接是永久的,因此粘贴到工单中的链接会一直有效。

从平台发送

从个人账户测试营销活动,衡量的是该账户。身份验证部分的几乎所有内容都与发送基础设施有关,而不是文本。

修复后重新测试

预期提升是每次针对一项修复计算的,不能叠加。第二份报告中的数字才是真实结果。

面向机器

GET/api/health

存活性。无需身份验证,无副作用。

先手动试一次

大约需要一分钟,并会准确展示 JSON 所描述的内容。

获取测试地址

沙盒。

每个端点都配有一个按钮,可针对实时服务运行。这里无需密钥,因此你从此页面发出的请求是真实请求:它会预留一个真实地址,并计入使用量。

在沙盒中试用