Email Spam Tester

API kiểm tra spam cho email,
hộp thư đến và tên miền

Gửi cho chúng tôi một thư thực tế hoặc chỉ cung cấp một tên miền. Mọi kết quả đều được trả về dưới dạng JSON.

Không cần khóa, không cần tài khoản.

Yêu cầu

# 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'

Phản hồi

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}]
}

Yêu cầu

# 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'

Phản hồi

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"}
  ]}
}

Yêu cầu

# 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'

Phản hồi

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"}]
}
Trên trang này

Kiểm tra email

Chúng tôi đọc toàn bộ một thư thực tế: nội dung, chữ ký, tiêu đề và máy chủ đã gửi thư. Bạn nhận được điểm số, danh sách các mục cần sửa và mọi kết quả kiểm tra làm căn cứ cho các mục đó.

Bắt đầu nhanh

Ba lệnh gọi. Không cần khóa, không cần tài khoản, không cần đăng ký. Hai yêu cầu và một email. Lệnh gọi thứ ba chỉ cần thiết vì quá trình phân tích mất vài giây.

  1. Đặt trước một địa chỉ

    Gửi POST đến endpoint hộp thư đến. Bạn nhận lại một địa chỉ chỉ chấp nhận đúng một thư và hết hạn sau một giờ, cùng với slug dùng để định danh mọi thứ còn lại.

    Yêu cầu

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

    Phản hồi

    {
      "address": "test-<slug>@t.email-spam-tester.com",
      "slug": "<slug>",
      "expires_at": "2026-01-01T12:00:00Z"
    }
  2. Gửi thư thực tế đến địa chỉ đó

    Qua SMTP, từ nền tảng sẽ gửi chiến dịch. Một nửa số lượt kiểm tra đọc các header do nền tảng gửi của bạn thêm vào, vì vậy thư được soạn thủ công sẽ đo không đúng đối tượng.

    Yêu cầu

    # 2. send your message to that address, from your own platform
    To: test-<slug>@t.email-spam-tester.com
  3. Polling trạng thái, sau đó đọc báo cáo

    Endpoint trạng thái chỉ có kích thước vài trăm byte và cho bạn biết liệu đã nên tải báo cáo đầy đủ hay chưa. Bản thân báo cáo dài đến vài nghìn dòng.

    Yêu cầu

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

    Phản hồi

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

    Yêu cầu

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

    Phản hồi

    {
      "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"}}
      ]
    }

Đặt trước một địa chỉ, gửi thư mà bạn sắp gửi đến danh sách của mình, đọc báo cáo. Mọi thứ hiển thị trên trang đều có trong JSON, bao gồm điểm số, toàn bộ 42 lượt kiểm tra kèm bằng chứng và phần của tiêu chuẩn làm căn cứ cho từng kết quả.

100.000 báo cáo đầu tiên được miễn phí, không cần khóa và không cần tài khoản. Nếu bạn đang tích hợp một tác nhân thay vì một tập lệnh, máy chủ MCP phù hợp hơn so với việc thăm dò.

Endpoint

Địa chỉ cơ sở https://email-spam-tester.com. Mọi phản hồi đều ở dạng JSON.

POST/api/v1/inbox

Giữ trước một địa chỉ dùng một lần. Cả hai tham số đều là tùy chọn.

langNgôn ngữ dùng để viết kế hoạch khắc phục và kết quả của từng kiểm tra, dưới dạng mã ISO. Được quyết định ngay lúc này vì thư đến qua SMTP vài phút sau và không chứa dấu hiệu nào về người đang chờ nó. Mã không xác định sẽ mặc định dùng tiếng Anh.
utm_source, utm_medium, utm_campaignĐược chuyển tiếp đến hệ thống phân tích của chúng tôi. Hữu ích nếu bạn đang đo lường tích hợp của mình.

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

Ít tốn tài nguyên khi thăm dò. Trả về hai trường trạng thái và tiến độ của các kiểm tra, ngoài ra không có gì khác.

Hãy thăm dò endpoint này thay vì báo cáo. analysis_status đạt checks_ready trước, và kế hoạch AI xuất hiện trong ai_status khoảng một phút sau, vì vậy bên gọi chỉ cần các kiểm tra tất định không phải chờ kế hoạch.

GET/api/v1/tests/{slug}

Toàn bộ báo cáo. Phản hồi 202 khi địa chỉ đã được giữ trước và chưa có thư nào đến, phản hồi 200 sau khi thư đến.

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

Thư chính xác như khi được gửi đến: mọi header theo thứ tự truyền trên đường dây, cả hai phần nội dung, danh sách tệp đính kèm và mã nguồn thô. Được truy xuất riêng vì báo cáo được thăm dò còn dữ liệu này có thể lên đến một megabyte.

Thư thô được xóa theo lịch riêng, sớm hơn báo cáo. Sau đó, điểm cuối này trả về lý do thay vì nội dung nguồn.

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

Thay đổi ngôn ngữ của một lượt đặt chỗ chưa được sử dụng. Dành cho tác nhân biết được người dùng đọc ngôn ngữ nào sau khi tác nhân đã yêu cầu địa chỉ. Yêu cầu bị từ chối sau khi thư đã đến, vì lúc đó quá trình phân tích đang chạy.

Vị trí trong hộp thư đếnBeta

Gửi một thư đến danh sách hộp thư đến dùng để kiểm tra và xem thư đó đến thư mục nào tại Gmail, Outlook, Yahoo và các nhà cung cấp khác: Hộp thư đến, Quảng cáo hoặc Thư rác.

Bắt đầu nhanh

  1. Tạo một bài kiểm tra

    Gửi yêu cầu POST đến điểm cuối placement. Bạn sẽ nhận lại một mã đánh dấu và các hộp thư kiểm tra.

    Yêu cầu

    # 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}'

    Phản hồi

    {
      "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. Gửi một thư đến mọi hộp thư

    Đặt mã đánh dấu vào tiêu đề và gửi từ nền tảng thông thường của bạn đến tất cả các địa chỉ trong một lần.

    Yêu cầu

    # 2. one message to every address, with the marker in the subject
    Subject: October invoice est-3f9a1c7e2b4d6a80c5e1f2d3
    To: <seed>, <mailbox>, ...
  3. Thăm dò các thư mục

    Mỗi địa chỉ sẽ được điền nhà cung cấp và thư mục tương ứng. Thăm dò cho đến khi trạng thái không còn là waiting.

    Yêu cầu

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

    Phản hồi

    {
      "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"}
        ]
      }
    }

Endpoint

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.

Kiểm tra hạ tầng

Một yêu cầu GET kiểm tra cấu hình thư của một tên miền mà không gửi bất kỳ nội dung nào, lưu kết quả và cho bạn biết những gì đã thay đổi kể từ lần chạy gần nhất. Không cần khóa. Trong cron, dòng bên dưới thoát với mã khác 0 khi tên miền bị lỗi hoặc cấu hình của tên miền thay đổi theo cách đáng kể.

Bắt đầu nhanh

  1. Thực hiện một GET

    Truyền miền. ip thêm các địa chỉ gửi của bạn, và selector chỉ định các DKIM selector cần đọc.

    Yêu cầu

    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true'
  2. Đọc kết luận

    ok là câu trả lời cho tập lệnh, và sections cho biết phần nào không đạt.

    Phản hồi

    {
      "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. Đưa vào cron

    Với diff=true, mỗi lần chạy được so sánh với lần chạy gần nhất của bạn, và jq chuyển câu trả lời thành mã thoát.

    Yêu cầu

    # 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)'
domainBắt buộc. Nhận cùng loại dữ liệu đầu vào như các công cụ: tên miền, URL hoặc địa chỉ email.
ipĐịa chỉ gửi của bạn. Lặp lại tham số này để thêm địa chỉ, tối đa 6 địa chỉ.
selectorMột selector DKIM. Lặp lại tham số này để thêm selector, tối đa 10 selector. Mọi selector bạn truyền đều phải tồn tại, nếu không phần dkim sẽ không đạt.
heloTên mà máy chủ của bạn cung cấp trong HELO, được so sánh với PTR của máy chủ.
accountNgười mà yêu cầu này dành cho. Bắt buộc khi dùng khóa phục vụ nhiều người.
checksCác phần cần chạy, phân tách bằng dấu phẩy. Mặc định là tất cả các phần.
difftrue so sánh lần chạy này với lần chạy gần nhất của miền.
since7d, 12h hoặc một ngày theo ISO 8601. So sánh với lần chạy của bạn gần thời điểm đó nhất trong phạm vi 12 giờ, nếu không thì với lần chạy cuối cùng trước thời điểm đó. Bật diff.
baselineid của một trong các lần chạy của bạn để dùng làm đối tượng so sánh. Bật diff.
freshtrue bỏ qua bộ nhớ đệm 60 giây.

Đọc kết quả

Một lần kiểm tra đã hoàn tất sẽ trả về 200, và kết luận nằm trong phần thân. status là trạng thái xấu nhất trong các phần bắt buộc: spf, dkim, dmarc, ptr, blocklist_ip, blocklist_domain, mx và smtp. unknown trong một phần bắt buộc được tính là warn. ok là true khi status là pass hoặc warn. score nằm trong khoảng từ 0 đến 100 trên các phần bắt buộc đã có kết quả, và là null khi error và unknown khiến phần trọng số áp dụng còn lại chưa đến một nửa. mta_sts, tls_rpt, bimi, dnssec, dane, ns và registration được báo cáo và so sánh, nhưng không ảnh hưởng đến ok hoặc score.

Một phần có thể là pass, warn, fail, error (chúng tôi không thể kiểm tra), unknown (có quá ít thông tin để kết luận) hoặc skipped (không áp dụng). skipped không ảnh hưởng đến kết quả, và lý do nằm trong not_checked. dkim_signature và alignment luôn có mặt, vì chúng cần một thư thực tế.

ip và selector thay đổi điều gì

PTR và các blocklist áp dụng cho địa chỉ, vì vậy một lượt chạy cần có một số địa chỉ. Lượt chạy sử dụng các giá trị ip bạn cung cấp. Nếu không có, lượt chạy lấy tối đa bốn địa chỉ từ các máy chủ MX của bạn và từ các mục ip4: và ip6: chỉ có một địa chỉ trong bản ghi SPF gốc. Địa chỉ của một nhà cung cấp thư đã biết được liệt kê là managed và không được kiểm tra, và nếu không còn địa chỉ nào thì ptr và blocklist_ip trả về skipped. Không thể đọc selector từ DNS, vì vậy một lượt chạy sẽ thử selector của bạn, các selector mà những lượt chạy trước của bạn đã tìm thấy và một danh sách tên phổ biến. Không tìm thấy gì không chứng minh được điều gì, và dkim trả về unknown. Nếu bạn gửi từ máy chủ của riêng mình, hãy cung cấp cả hai.

Những gì đã thay đổi

Mỗi mục trong diff.changes có một path, một kind (added, removed, changed), một severity (critical, warning, info) và một effect (worsened, improved, neutral). Chỉ critical và warning mới đặt diff.changed, vì vậy việc xoay vòng khóa DKIM có cùng độ dài, một địa chỉ MX mới hoặc một chứng chỉ được gia hạn sẽ không làm dòng cron thất bại. diff.worsened phản ánh effect của bất kỳ thay đổi nào. Trong lần chạy đầu tiên, không có gì để so sánh, và diff.first_run cho biết điều đó.

Baseline luôn là một lượt chạy của chính bạn, vì vậy việc người khác kiểm tra miền giữa hai lượt chạy của bạn không che giấu điều gì. Bất kỳ dữ liệu nào chúng tôi không thể đọc lần này sẽ được đưa vào diff.not_compared và giữ lại giá trị đã biết gần nhất, nghĩa là một thay đổi được thực hiện trong thời gian gián đoạn sẽ xuất hiện khi truy vấn hoạt động trở lại. Một lượt chạy có ip hoặc selector khác vẫn nằm trong cùng một chuỗi, và những gì lượt chạy đó không yêu cầu kiểm tra cũng không được so sánh.

Tại sao kiểm tra theo lịch nên dùng khóa

Nếu không có khóa, lịch sử của bạn thuộc về một giá trị băm có khóa từ địa chỉ IP của bạn, vì vậy lịch sử sẽ kết thúc khi địa chỉ thay đổi, và những người dùng chung một địa chỉ sẽ chia sẻ lịch sử đó: lượt chạy của một đồng nghiệp sẽ thay đổi baseline của bạn. Khi có khóa API cá nhân trong Authorization: Bearer, lịch sử đi theo khóa. Các lượt chạy có khóa được lưu giữ trong 365 ngày và chỉ có thể mở bằng khóa đó. Các lượt chạy không có khóa được lưu giữ trong 30 ngày và bất kỳ ai có id của chúng đều có thể mở.

6 yêu cầu mỗi phút và 50 yêu cầu mỗi ngày cho mỗi IP, hoặc 30 và 500 cho mỗi khóa. Vượt quá giới hạn đó, kết quả trả về là 429 kèm Retry-After. Một yêu cầu giống hệt trong vòng 60 giây được lấy từ bộ nhớ đệm, được đánh dấu cached: true, không ghi lượt chạy và không được tính vào giới hạn. Việc đọc các lượt chạy đã lưu cho phép 120 yêu cầu mỗi phút cho mỗi máy khách. 503 kèm Retry-After có nghĩa là có quá nhiều lượt kiểm tra đang chạy, hoặc khi đọc các lượt chạy đã lưu, kho lưu trữ không khả dụng. 401 là khóa không đúng. 422 chứa detail.code: invalid_domain, invalid_ip, invalid_selector, invalid_check, invalid_since, unknown_baseline hoặc account_required.

Endpoint

GET/api/v1/infra/check

Chạy kiểm tra. Các tham số nằm trong bảng ở trên.

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

Một lần chạy đã lưu, toàn bộ. Trả về 404 nếu lần chạy không tồn tại hoặc thuộc về một khóa khác.

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

Các lần chạy của bạn đối với một tên miền, mới nhất trước: id, thời gian, trạng thái, điểm và số lượng thay đổi. Nhận limit (từ 1 đến 100, mặc định là 30) và before, một id lần chạy.

GET/api/v1/infra/diff

Cùng phép so sánh giữa hai lần chạy đã lưu, ?from=<id>&to=<id>. Bạn cần có quyền truy cập vào cả hai.

GET/api/v1/infra/checks

Mọi phần cùng với trọng số, phiên bản tính điểm và các giới hạn.

Kiểm tra riêng lẻ

Mỗi lệnh gọi trả lời một câu hỏi và không lưu lịch sử. Một công cụ tự chạy một phần của quy trình kiểm tra hạ tầng, ngoại trừ công cụ header, công cụ này đọc thư bạn đã nhận.

Bắt đầu nhanh

  1. Chọn một kiểm tra

    Chọn công cụ từ danh sách bên dưới và truyền tên miền, địa chỉ hoặc IP mà công cụ yêu cầu.

    Yêu cầu

    curl -s 'https://email-spam-tester.com/api/v1/tools/spf?domain=example.com'
  2. Đọc trạng thái và các phát hiện

    Mỗi công cụ trả về một trạng thái và các phát hiện. Các trường sau đó phụ thuộc vào công cụ.

    Phản hồi

    {
      "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}
    }

Endpoint

Tất cả các công cụ đều trả về 200 với một trạng thái và danh sách các phát hiện, mỗi phát hiện có một mã và các tham số tương ứng. Trạng thái là pass, warn, fail hoặc error, và một công cụ dùng chung với kiểm tra hạ tầng cũng có thể trả về unknown hoặc skipped. Một lần tra cứu hết thời gian chờ hoặc một danh sách từ chối truy vấn không bao giờ được tính là pass. Giới hạn là 30 yêu cầu mỗi phút và 300 yêu cầu mỗi ngày cho mỗi IP trên tất cả các công cụ; vượt quá giới hạn này, phản hồi là 429 kèm Retry-After.

GET/api/v1/tools/spf

Bản ghi SPF của một tên miền: cú pháp, mọi include và redirect được lần theo, cùng số lượt tra cứu DNS mà toàn bộ cây sử dụng so với giới hạn mười lượt. Truyền ?domain=example.com.

GET/api/v1/tools/dmarc

Bản ghi DMARC của một tên miền, hoặc của tên miền tổ chức khi tên miền đó không có bản ghi: các thẻ, chính sách và việc từng địa chỉ nhận báo cáo bên ngoài đã đồng ý nhận báo cáo hay chưa. Truyền ?domain=example.com.

GET/api/v1/tools/dkim

Khóa DKIM được công bố cho một selector: khóa có tồn tại và giải mã được hay không, loại và kích thước của khóa, cùng các cờ thu hồi và kiểm thử. Truyền ?domain=example.com&selector=s1.

GET/api/v1/tools/blocklist

Một địa chỉ IPv4, một địa chỉ IPv6 hoặc một tên miền được kiểm tra đối chiếu với các danh sách chặn DNS mà báo cáo sử dụng, kèm theo câu trả lời của từng danh sách. Truyền ?target=203.0.113.5.

GET/api/v1/tools/mx

Các bản ghi MX của một miền theo thứ tự mà bên gửi thử dùng, cùng với địa chỉ IPv4 và IPv6 của từng máy chủ. Null MX, miền không có MX, máy chủ là địa chỉ IP hoặc CNAME và máy chủ không phân giải được đều được báo cáo, cũng như các bản ghi MTA-STS và TLS-RPT. Truyền ?domain=example.com.

GET/api/v1/tools/bimi

Thiết lập BIMI của một miền qua bốn bước: chính sách DMARC mà BIMI yêu cầu, bản ghi tại default._bimi, logo SVG được kiểm tra theo hồ sơ Tiny PS, và chứng chỉ nhãn hiệu cùng loại, các miền và ngày hết hạn của chứng chỉ. Truyền ?domain=example.com và &selector= cho một bộ chọn khác default.

GET/api/v1/tools/ptr

Các bản ghi PTR của một địa chỉ và việc có tên nào trong số đó phân giải ngược về địa chỉ này hay không. Một truy vấn không thực hiện được sẽ trả về trạng thái error; bản ghi không tồn tại sẽ trả về trạng thái fail. Truyền ?ip=8.8.8.8.

GET/api/v1/tools/mta-sts

Bản ghi MTA-STS của một tên miền và tệp chính sách mà bản ghi đó trỏ đến: chế độ, các máy chủ được liệt kê và mọi máy chủ MX bị chính sách bỏ sót. Truyền ?domain=example.com.

GET/api/v1/tools/tls-rpt

Bản ghi TLS-RPT của một tên miền và các địa chỉ nhận báo cáo của bản ghi đó. Truyền ?domain=example.com.

GET/api/v1/tools/dnssec

Liệu vùng của một tên miền được ký, không được ký hay bị lỗi, dựa trên các bản ghi DNSKEY và DS của vùng đó. Chữ ký không hợp lệ được phân biệt với sự cố của trình phân giải. Truyền ?domain=example.com.

GET/api/v1/tools/dane

Các bản ghi TLSA của các máy chủ MX, được so sánh với chứng chỉ mà một máy chủ cung cấp khi có thể đọc được chứng chỉ đó. Truyền ?domain=example.com.

GET/api/v1/tools/smtp

STARTTLS và chứng chỉ trên hai máy chủ MX đầu tiên: phiên bản TLS, tổ chức phát hành, ngày hết hạn và liệu chuỗi chứng chỉ cùng tên có hợp lệ hay không. Chúng tôi chỉ kết nối đến các máy chủ thuộc tên miền mà bạn yêu cầu và bỏ qua các nhà cung cấp dịch vụ thư, đồng thời một kết quả cho mỗi địa chỉ được dùng chung trong 6 giờ. Không có thư nào được gửi. Truyền ?domain=example.com.

GET/api/v1/tools/ns

Các máy chủ tên của một tên miền và liệu vùng của tên miền đó có bản ghi SOA hay không. Chỉ có một máy chủ tên là warn. Truyền ?domain=example.com.

GET/api/v1/tools/registration

Thời điểm đăng ký của một tên miền hết hạn, lấy từ RDAP. Còn dưới 30 ngày là warn. Một vùng không có dịch vụ RDAP trả về skipped. Truyền ?domain=example.com.

POST/api/v1/tools/header

Các tiêu đề của thư đã nhận, được gửi dưới dạng JSON {"headers": "..."} hoặc text/plain: lộ trình qua từng chặng cùng độ trễ, TLS và độ lệch đồng hồ, Authentication-Results của chính bên nhận, sự căn chỉnh giữa các miền From, DKIM d= và Return-Path, cùng các tiêu đề DKIM, ARC, hủy đăng ký và bộ lọc thư rác. Mọi nội dung sau dòng trống đầu tiên đều bị loại bỏ mà không được đọc. Các tiêu đề được xử lý trong bộ nhớ và không được lưu trữ, lưu vào bộ nhớ đệm hoặc ghi nhật ký.

Kiểm tra miền mỗi đêm.
Kiểm tra email trước khi gửi.

Dùng chung cho mọi sản phẩm

Quyền truy cập, khóa, định dạng báo cáo, trạng thái, lỗi, cùng với OpenAPI và llms.txt dành cho máy.

Xác thực

Không có. Không cần yêu cầu khóa, không cần thiết lập header, không cần tạo tài khoản. Slug bạn nhận được chính là quyền truy cập: bất kỳ ai nắm giữ nó đều có thể đọc báo cáo đó, và không ai khác có thể đoán được nó.

Điều đó cũng có nghĩa là cần coi slug như mật khẩu. Báo cáo hiển thị dòng tiêu đề, người gửi, địa chỉ nhận thư trả lại và toàn bộ mã nguồn của thư cho bất kỳ ai nắm giữ liên kết.

Khóa API cá nhân

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.

Đọc báo cáo

Các trường chứa kết quả, theo thứ tự mà bạn có thể cần đến.

score_oursTừ 0 đến 100. Mô hình của chúng tôi. Xác thực và hạ tầng chiếm phần lớn trọng số, vì chúng quyết định khả năng gửi đến trước khi bộ lọc đọc nội dung thư.
score_compatTừ 0 đến 10. Tái tạo con số theo kiểu SpamAssassin mà mọi người đã quen dùng để so sánh, nhờ đó báo cáo có thể được đối chiếu với những gì họ thấy ở nơi khác.
subscoresCùng thang điểm từ 0 đến 100 cho từng phần: auth, infra_spam, content, compliance.
checks[]Tất cả 42 mục, mỗi mục có trạng thái, kết luận trong một dòng, bằng chứng dùng để đưa ra kết luận và mức ảnh hưởng đến hai điểm số.
checks[].citationsNguồn của phát hiện: phần tương ứng trong RFC, được trích dẫn nguyên văn, và trang nơi Google nêu yêu cầu riêng. Được tuyển chọn thủ công thay vì tạo tự động, nên có thể tin cậy.
fixes[]Những nội dung cần thay đổi, theo thứ tự, cùng số điểm đạt được từ mỗi thay đổi. Mức tăng được tính bằng cách chấm lại báo cáo, không phải ước tính.
completeFalse khi một lượt kiểm tra không thể chạy. Một mục chưa được kiểm tra không bao giờ được coi là đạt, vì vậy hãy xem điểm số là lạc quan cho đến khi giá trị này là true.
report_urlTrang dành cho người đọc. Hãy gửi trang đó cho người dùng thay vì một mớ JSON.

Trạng thái

Một lượt kiểm tra có một trong năm trạng thái, và sự khác biệt giữa hai trạng thái trong số đó quan trọng hơn vẻ bề ngoài.

passLượt kiểm tra đã chạy và không phát hiện vấn đề nào.
warnĐáng để khắc phục. Bị trừ điểm.
failSẽ làm giảm khả năng gửi thành công. Bị trừ nhiều điểm hơn.
bỏ quaKhông áp dụng. Không có tệp đính kèm để quét, không có phần HTML để đánh giá. Không được tính là đạt.
lỗiChúng tôi không thể xác định. Bị loại khỏi điểm số và được gắn cờ, thay vì được tính là đạt.

analysis_status lần lượt là received, analyzing, checks_ready, failed. ai_status lần lượt là pending, running, ready, fallback, error. Báo cáo xác định là báo cáo cuối cùng tại checks_ready; ai_status chỉ bổ sung kế hoạch.

Những gì có thể được trả về

202Địa chỉ đã được giữ trước và chưa có thư nào đến. Phần nội dung chứa địa chỉ, thời điểm hết hạn và ngôn ngữ, vì vậy bên gọi không tạo yêu cầu giữ trước vẫn có thể hiển thị thông tin đó.
404Không có slug đó. Slug này chưa từng tồn tại hoặc yêu cầu giữ trước đã bị quên.
410Địa chỉ đã hết hạn trước khi có thư đến.
409Bạn đã cố thay đổi ngôn ngữ sau khi thư đã đến.
429Giới hạn kiểm thử miễn phí cho địa chỉ của bạn. Hiện tại dịch vụ này không có giới hạn theo từng người; nếu giới hạn đó được thiết lập, phần nội dung sẽ cho biết khi nào giới hạn được đặt lại.

Bốn điều cần biết

Mỗi địa chỉ một thư

Thư thứ hai sẽ bị từ chối. Báo cáo trước đó của bạn vẫn nguyên vẹn, đó chính là mục đích.

Một giờ để sử dụng

Địa chỉ hết hạn; báo cáo thì không. Liên kết báo cáo là vĩnh viễn, vì vậy liên kết được dán vào phiếu hỗ trợ vẫn tiếp tục hoạt động.

Gửi từ nền tảng

Kiểm tra một chiến dịch từ tài khoản cá nhân sẽ đo lường tài khoản đó. Hầu hết mọi nội dung trong phần xác thực đều liên quan đến hạ tầng gửi, không phải văn bản.

Kiểm tra lại sau khi sửa

Mức cải thiện dự kiến được tính riêng cho từng bản sửa lỗi và không cộng dồn. Báo cáo thứ hai mới là con số trung thực.

Dành cho máy

GET/api/health

Kiểm tra trạng thái hoạt động. Không xác thực, không có tác dụng phụ.

Trước tiên, hãy thử thủ công một lần

Quá trình này mất khoảng một phút và cho bạn thấy chính xác những gì JSON mô tả.

Lấy địa chỉ kiểm tra

Sandbox.

Mọi endpoint đều có một nút để chạy endpoint đó trên dịch vụ trực tiếp. Không có thao tác nào ở đây cần khóa, vì vậy yêu cầu bạn gửi từ trang này là yêu cầu thực: yêu cầu đó giữ chỗ một địa chỉ thực và được tính.

Thử trong sandbox