Email Spam Tester

API de test antispam : e-mail,
boîte de réception et domaine

Envoyez-nous un message réel, ou indiquez-nous seulement un domaine. Tout est renvoyé en JSON.

Aucune clé, aucun compte.

Requête

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

Réponse

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

Requête

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

Réponse

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

Requête

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

Réponse

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"}]
}
Sur cette page

Test d’e-mail

Nous analysons un message réel de bout en bout : le contenu, la signature, les en-têtes et le serveur qui l'a envoyé. Vous obtenez un score, une liste de corrections et toutes les vérifications qui les justifient.

Démarrage rapide

Trois appels. Sans clé, sans compte, sans inscription. Deux requêtes et un e-mail. Le troisième appel n’est nécessaire que parce que l’analyse prend quelques secondes.

  1. Réserver une adresse

    Envoyez une requête POST au point de terminaison de la boîte de réception. Vous recevez une adresse qui accepte exactement un message et expire au bout d’une heure, ainsi que le slug servant de clé pour tout le reste.

    Requête

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

    Réponse

    {
      "address": "test-<slug>@t.email-spam-tester.com",
      "slug": "<slug>",
      "expires_at": "2026-01-01T12:00:00Z"
    }
  2. Lui envoyer le message réel

    Via SMTP, depuis la plateforme qui enverra la campagne. La moitié des contrôles lisent les en-têtes ajoutés par votre plateforme d’envoi, donc un message composé à la main mesure autre chose.

    Requête

    # 2. send your message to that address, from your own platform
    To: test-<slug>@t.email-spam-tester.com
  3. Interroger le statut, puis consulter le rapport

    Le point de terminaison de statut ne représente que quelques centaines d’octets et vous indique si le rapport complet peut déjà être récupéré. Le rapport lui-même compte plusieurs milliers de lignes.

    Requête

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

    Réponse

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

    Requête

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

    Réponse

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

Réservez une adresse, envoyez le message que vous étiez sur le point d’envoyer à votre liste, puis consultez le rapport. Tout ce que la page affiche se trouve dans le JSON, y compris le score, les 42 contrôles avec leurs éléments de preuve et la section de la norme sur laquelle repose chaque constat.

Les 100 000 premiers rapports sont gratuits, sans clé ni compte. Si vous connectez un agent plutôt qu’un script, le serveur MCP est plus adapté que l’interrogation périodique.

Points de terminaison

Adresse de base https://email-spam-tester.com. Toutes les réponses sont au format JSON.

POST/api/v1/inbox

Réserve une adresse à usage unique. Les deux paramètres sont facultatifs.

langLangue dans laquelle le plan de correction et les résultats de chaque contrôle seront rédigés, sous forme de code ISO. Elle est déterminée maintenant, car le message arrive via SMTP quelques minutes plus tard et ne contient aucune indication sur la personne qui l’attend. Un code inconnu utilise l’anglais par défaut.
utm_source, utm_medium, utm_campaignTransmis à notre système d’analyse. Utile si vous mesurez votre propre intégration.

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

Peu coûteux à interroger. Renvoie les deux champs d’état et la progression des contrôles, et rien d’autre.

Interrogez ce point de terminaison plutôt que le rapport. analysis_status atteint d’abord checks_ready, et le plan de l’IA arrive dans ai_status environ une minute plus tard, afin qu’un appelant qui souhaite uniquement les contrôles déterministes n’ait pas à attendre le plan.

GET/api/v1/tests/{slug}

Le rapport complet. Répond avec le code 202 tant que l’adresse est réservée et qu’aucun message n’est encore arrivé, puis avec le code 200 une fois le message reçu.

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

Le message exactement tel qu’il a été distribué : chaque en-tête dans l’ordre de transmission, les deux corps, la liste des pièces jointes et la source brute. Récupéré séparément, car le rapport est interrogé régulièrement et le message peut atteindre un mégaoctet.

Le message brut est supprimé selon son propre délai, avant le rapport. Ensuite, ce point de terminaison répond avec la raison plutôt qu'avec la source.

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

Change la langue d'une réservation qui n'a pas encore été utilisée. Pour un agent qui apprend quelle langue son utilisateur lit après avoir déjà demandé l'adresse. Refusé une fois le message arrivé, car à ce stade l'analyse est en cours.

Placement en boîte de réceptionBêta

Envoyez un message à une liste de boîtes de réception de test et voyez où il est arrivé chez Gmail, Outlook, Yahoo et d'autres fournisseurs : Boîte de réception, Promotions ou Spam.

Démarrage rapide

  1. Créez un test

    Envoyez une requête POST au point de terminaison de placement. Vous obtenez un marqueur et les boîtes de réception de test.

    Requête

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

    Réponse

    {
      "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. Envoyez un message à chaque boîte

    Placez le marqueur dans l’objet et envoyez le message depuis votre plateforme habituelle, à toutes les adresses en une seule fois.

    Requête

    # 2. one message to every address, with the marker in the subject
    Subject: October invoice est-3f9a1c7e2b4d6a80c5e1f2d3
    To: <seed>, <mailbox>, ...
  3. Interrogez les dossiers

    Chaque adresse est renseignée avec son fournisseur et son dossier. Interrogez jusqu’à ce que le statut ne soit plus waiting.

    Requête

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

    Réponse

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

Points de terminaison

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.

Vérification de l’infrastructure

Une requête GET vérifie la configuration de messagerie d’un domaine sans rien envoyer, conserve le résultat et vous indique ce qui a changé depuis votre dernière exécution. Aucune clé n’est nécessaire. Dans cron, la ligne ci-dessous se termine avec un code différent de zéro lorsque le domaine est défectueux ou que sa configuration a changé de manière significative.

Démarrage rapide

  1. Effectuez une requête GET

    Indiquez le domaine. ip ajoute vos adresses d’envoi, et selector indique les sélecteurs DKIM à lire.

    Requête

    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true'
  2. Lisez le verdict

    ok est la réponse destinée à un script, et sections indique quelle partie a échoué.

    Réponse

    {
      "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. Ajoutez-la à cron

    Avec diff=true, chaque exécution est comparée à la précédente, et jq transforme la réponse en code de sortie.

    Requête

    # 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)'
domainObligatoire. Accepte ce qu’acceptent les outils : un domaine, une URL, une adresse e-mail.
ipVotre adresse d’envoi. Répétez ce paramètre pour en fournir plusieurs, jusqu’à 6.
selectorUn sélecteur DKIM. Répétez ce paramètre pour en fournir plusieurs, jusqu’à 10. Chaque sélecteur que vous fournissez doit exister, sinon la section dkim échoue.
heloLe nom que votre serveur fournit dans HELO, comparé à son PTR.
accountLa personne concernée par la requête. Obligatoire avec une clé utilisée pour plusieurs personnes.
checksSections à exécuter, séparées par des virgules. Toutes par défaut.
difftrue compare cette exécution à votre dernière exécution du domaine.
since7d, 12h ou une date ISO 8601. Compare avec votre exécution la plus proche de ce moment dans un intervalle de 12 heures, sinon avec la dernière qui le précède. Active diff.
baselineL’identifiant de l’une de vos exécutions avec laquelle effectuer la comparaison. Active diff.
freshtrue ignore le cache de 60 secondes.

Lecture de la réponse

Une vérification terminée renvoie 200, et le verdict se trouve dans le corps. status est le pire état des sections requises : spf, dkim, dmarc, ptr, blocklist_ip, blocklist_domain, mx et smtp. unknown dans une section requise compte comme warn. ok vaut true lorsque status est pass ou warn. score va de 0 à 100 pour les sections requises ayant répondu, et vaut null lorsque les erreurs et les états unknown laissent moins de la moitié de la pondération applicable. mta_sts, tls_rpt, bimi, dnssec, dane, ns et registration sont indiqués et comparés, mais n’ont aucun effet sur ok ou score.

Une section peut être pass, warn, fail, error (nous n’avons pas pu effectuer la vérification), unknown (trop peu d’informations pour conclure) ou skipped (ne s’applique pas). skipped n’a aucun effet sur le résultat, et la raison se trouve dans not_checked. dkim_signature et alignment sont toujours présents, car ils nécessitent un message réel.

Ce que changent ip et selector

PTR et les listes de blocage concernent les adresses, une exécution en a donc besoin. Elle utilise les valeurs ip que vous transmettez. S’il n’y en a aucune, elle en prend jusqu’à quatre depuis vos hôtes MX et depuis les termes ip4: et ip6: à adresse unique de l’enregistrement SPF racine. Les adresses d’un fournisseur de messagerie connu sont indiquées comme managed et ne sont pas vérifiées, et s’il ne reste rien, ptr et blocklist_ip répondent skipped. Un selector ne peut pas être lu depuis DNS, une exécution essaie donc le vôtre, ceux trouvés par vos exécutions précédentes et une liste de noms courants. Ne rien trouver ne prouve rien, et dkim répond unknown. Si vous envoyez depuis votre propre serveur, transmettez les deux.

Ce qui a changé

Chaque entrée de diff.changes comporte path, kind (added, removed, changed), severity (critical, warning, info) et effect (worsened, improved, neutral). Seuls critical et warning définissent diff.changed, de sorte qu’une clé DKIM remplacée par rotation et de même longueur, une nouvelle adresse MX ou un certificat renouvelé ne fait pas échouer la ligne cron. diff.worsened suit l’effet de toute modification. Lors d’une première exécution, il n’y a rien à comparer, et diff.first_run l’indique.

Une référence est toujours l’une de vos propres exécutions, donc la vérification du domaine par quelqu’un d’autre entre deux de vos exécutions ne masque rien. Tout ce que nous n’avons pas pu lire cette fois-ci est placé dans diff.not_compared avec sa dernière valeur connue conservée, ce qui signifie qu’une modification effectuée pendant une indisponibilité apparaît dès que la recherche fonctionne à nouveau. Une exécution avec un ip ou un selector différent reste dans la même série, et ce qu’elle n’a pas demandé n’est pas comparé non plus.

Pourquoi une vérification planifiée doit utiliser une clé

Sans clé, votre historique appartient à un hachage avec clé de votre adresse IP, il prend donc fin lorsque l’adresse change, et les personnes derrière une même adresse le partagent : l’exécution d’un collègue déplace votre référence. Avec une clé API personnelle dans Authorization: Bearer, l’historique suit la clé. Les exécutions avec une clé sont conservées pendant 365 jours et ne sont accessibles qu’avec cette clé. Les exécutions sans clé sont conservées pendant 30 jours et sont accessibles à toute personne possédant leur id.

6 requêtes par minute et 50 par jour par IP, ou 30 et 500 par clé. Au-delà, la réponse est 429 avec Retry-After. Une requête identique dans un délai de 60 secondes provient d’un cache, porte la mention cached: true, n’enregistre aucune exécution et n’est pas comptabilisée. La lecture des exécutions stockées autorise 120 requêtes par minute et par client. 503 avec Retry-After signifie que trop de vérifications sont en cours ou, lors de la lecture des exécutions stockées, que le stockage est indisponible. 401 indique une clé incorrecte. 422 contient detail.code: invalid_domain, invalid_ip, invalid_selector, invalid_check, invalid_since, unknown_baseline ou account_required.

Points de terminaison

GET/api/v1/infra/check

Exécute la vérification. Les paramètres figurent dans le tableau ci-dessus.

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

Une exécution enregistrée, complète. 404 si elle n’existe pas ou appartient à une autre clé.

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

Vos exécutions pour un domaine, de la plus récente à la plus ancienne : id, heure, statut, score et nombre de modifications. Accepte limit (de 1 à 100, 30 par défaut) et before, un id d’exécution.

GET/api/v1/infra/diff

La même comparaison entre deux exécutions enregistrées, ?from=<id>&to=<id>. Vous devez avoir accès aux deux.

GET/api/v1/infra/checks

Chaque section avec son poids, la version du score et les limites.

Vérifications individuelles

Chaque appel répond à une question et ne conserve aucun historique. Un outil exécute seul une partie de la vérification de l’infrastructure, à l’exception de l’outil d’en-tête, qui lit un message que vous avez déjà reçu.

Démarrage rapide

  1. Choisir une vérification

    Choisissez l’outil dans la liste ci-dessous et transmettez-lui le domaine, l’adresse ou l’IP qu’il demande.

    Requête

    curl -s 'https://email-spam-tester.com/api/v1/tools/spf?domain=example.com'
  2. Lire le statut et les résultats

    Chaque outil renvoie un statut et ses résultats. Les champs suivants dépendent de l’outil.

    Réponse

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

Points de terminaison

Tous répondent avec le code 200, un statut et une liste de constatations, chacune avec un code et ses paramètres. Le statut est pass, warn, fail ou error, et un outil partagé avec la vérification de l’infrastructure peut également répondre unknown ou skipped. Une recherche qui a expiré ou une liste qui a refusé la requête ne compte jamais comme un pass. 30 requêtes par minute et 300 par jour et par IP pour l’ensemble des outils ; au-delà, la réponse est 429 avec Retry-After.

GET/api/v1/tools/spf

L’enregistrement SPF d’un domaine : sa syntaxe, chaque include et redirect suivi, et le nombre de recherches DNS que l’ensemble de l’arborescence consomme sur la limite de dix. Indiquez ?domain=example.com.

GET/api/v1/tools/dmarc

L’enregistrement DMARC d’un domaine, ou de son domaine organisationnel lorsqu’il n’en a pas : les balises, la politique et si chaque adresse externe de rapports a accepté de recevoir des rapports. Indiquez ?domain=example.com.

GET/api/v1/tools/dkim

La clé DKIM publiée pour un sélecteur : si elle existe et peut être décodée, son type et sa taille, ainsi que les indicateurs de révocation et de test. Indiquez ?domain=example.com&selector=s1.

GET/api/v1/tools/blocklist

Une adresse IPv4, une adresse IPv6 ou un domaine vérifié dans les listes de blocage DNS utilisées par le rapport, avec la réponse de chaque liste. Indiquez ?target=203.0.113.5.

GET/api/v1/tools/mx

Les enregistrements MX d’un domaine dans l’ordre où les expéditeurs les essaient, avec les adresses IPv4 et IPv6 de chaque hôte. Null MX, un domaine sans MX, les hôtes qui sont des adresses IP ou des CNAME et les hôtes qui ne sont pas résolus sont signalés, tout comme les enregistrements MTA-STS et TLS-RPT. Indiquez ?domain=example.com.

GET/api/v1/tools/bimi

La configuration BIMI d’un domaine en quatre étapes : la politique DMARC requise par BIMI, l’enregistrement à default._bimi, le logo SVG vérifié par rapport au profil Tiny PS et le certificat de marque avec son type, ses domaines et sa date d’expiration. Indiquez ?domain=example.com, et &selector= pour un sélecteur autre que default.

GET/api/v1/tools/ptr

Les enregistrements PTR d’une adresse et si l’un de ces noms se résout à nouveau vers celle-ci. Une recherche qui a échoué donne l’état error ; un enregistrement manquant donne l’état fail. Passez ?ip=8.8.8.8.

GET/api/v1/tools/mta-sts

L’enregistrement MTA-STS d’un domaine et le fichier de politique vers lequel il pointe : le mode, les hôtes répertoriés et tout hôte MX que la politique omet. Passez ?domain=example.com.

GET/api/v1/tools/tls-rpt

L’enregistrement TLS-RPT d’un domaine et les adresses qui reçoivent ses rapports. Passez ?domain=example.com.

GET/api/v1/tools/dnssec

Si la zone d’un domaine est signée, non signée ou défectueuse, d’après ses enregistrements DNSKEY et DS. Une signature incorrecte est distinguée d’une panne du résolveur. Passez ?domain=example.com.

GET/api/v1/tools/dane

Les enregistrements TLSA des hôtes MX, comparés au certificat présenté par un hôte lorsque ce certificat a pu être lu. Passez ?domain=example.com.

GET/api/v1/tools/smtp

STARTTLS et le certificat sur les deux premiers hôtes MX : version de TLS, émetteur, date d’expiration et validité de la chaîne et du nom. Nous nous connectons uniquement aux hôtes appartenant au domaine que vous avez demandé et ignorons les fournisseurs de messagerie, et un résultat par adresse est partagé pendant 6 heures. Aucun e-mail n’est envoyé. Passez ?domain=example.com.

GET/api/v1/tools/ns

Les serveurs de noms d’un domaine et si sa zone possède un enregistrement SOA. Un seul serveur de noms déclenche un avertissement. Passez ?domain=example.com.

GET/api/v1/tools/registration

La date d’expiration de l’enregistrement d’un domaine, d’après RDAP. Moins de 30 jours restants déclenche un avertissement. Une zone sans service RDAP renvoie skipped. Passez ?domain=example.com.

POST/api/v1/tools/header

Les en-têtes d’un message reçu, envoyés au format JSON {"headers": "..."} ou text/plain : le trajet saut par saut avec les délais, TLS et le décalage d’horloge, les propres Authentication-Results du destinataire, l’alignement des domaines From, DKIM d= et Return-Path, ainsi que les en-têtes DKIM, ARC, de désinscription et des filtres antispam. Tout ce qui suit la première ligne vide est ignoré sans être lu. Les en-têtes sont traités en mémoire et ne sont ni stockés, ni mis en cache, ni journalisés.

Vérifiez le domaine chaque nuit.
Testez l’e-mail avant son envoi.

Commun à tous les produits

Accès, clés, format du rapport, statuts, erreurs, ainsi qu’OpenAPI et llms.txt pour les machines.

Authentification

Il n’y en a aucune. Aucune clé à demander, aucun en-tête à définir, aucun compte à créer. Le slug que vous recevez constitue la capacité d’accès : quiconque le détient peut lire ce rapport, et personne d’autre ne peut le deviner.

Cela signifie également qu’un slug doit être traité comme un mot de passe. Un rapport affiche l’objet, l’expéditeur, l’adresse de retour des erreurs et la source complète du message à toute personne détenant le lien.

Clés API personnelles

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.

Lecture du rapport

Les champs qui contiennent la réponse, dans l'ordre où vous en aurez probablement besoin.

score_oursDe 0 à 100. Notre modèle. L'authentification et l'infrastructure ont le plus de poids, car elles déterminent la livraison avant qu'un filtre ne lise un seul mot du contenu.
score_compatDe 0 à 10. Reproduit le score de type SpamAssassin que les utilisateurs comparent déjà, afin que le rapport soit comparable à ce que quelqu'un a vu ailleurs.
subscoresLa même échelle de 0 à 100 par section : auth, infra_spam, content, compliance.
checks[]Les 42 contrôles, chacun avec un statut, un constat d'une ligne, les éléments sur lesquels la décision a été prise et son impact sur les deux scores.
checks[].citationsOrigine du constat : la section du RFC, citée mot pour mot, et la page où Google indique sa propre exigence. Sélectionnées manuellement plutôt que générées, ces sources sont donc fiables.
correctifs[]Ce qu’il faut modifier, dans l’ordre, avec le nombre de points que rapporte chaque modification. Les gains sont calculés en réévaluant le rapport, et non estimés.
completFaux lorsqu’une vérification n’a pas pu être exécutée. Un élément non vérifié n’est jamais une réussite, considérez donc le score comme optimiste jusqu’à ce que cette valeur soit vraie.
URL_du_rapportLa page lisible par une personne. Transmettez-la à quelqu’un plutôt qu’un mur de JSON.

Statuts

Une vérification peut avoir l’un de cinq états, et la différence entre deux d’entre eux est plus importante qu’il n’y paraît.

réussiteLa vérification a été exécutée et n’a détecté aucun problème.
avertissementMérite d’être corrigé. Coûte des points.
échecNuira à la délivrabilité. Coûte davantage de points.
ignoréNe s’appliquait pas. Aucune pièce jointe à analyser, aucune partie HTML à pondérer. Ce n’est pas une réussite.
erreurNous n’avons pas pu le déterminer. Exclu du score et signalé, plutôt que compté comme une réussite.

analysis_status prend les valeurs received, analyzing, checks_ready, failed. ai_status prend les valeurs pending, running, ready, fallback, error. Le rapport déterministe est définitif à checks_ready ; ai_status ajoute uniquement le plan.

Ce qui peut être renvoyé

202L’adresse est réservée et aucun message n’est arrivé. Le corps contient l’adresse, l’expiration et la langue, de sorte qu’un appelant qui n’a pas créé la réservation peut tout de même l’afficher.
404Ce slug n’existe pas. Il n’a jamais existé, ou la réservation a été oubliée.
410L’adresse a expiré avant l’arrivée d’un message.
409Vous avez essayé de modifier la langue après l’arrivée du message.
429La limite de tests gratuits pour votre adresse. Ce service n’applique actuellement aucune limite par personne ; si une telle limite est un jour définie, le corps indique quand elle est réinitialisée.

Quatre choses à savoir

Un message par adresse

Le deuxième est refusé. Votre rapport précédent reste intact, ce qui est le but.

Une heure pour l’utiliser

L’adresse expire ; le rapport, non. Les liens vers les rapports sont permanents, donc un lien collé dans un ticket continue de fonctionner.

Envoyer depuis la plateforme

Tester une campagne depuis un compte personnel mesure ce compte. Presque tout ce qui figure dans la section sur l’authentification concerne l’infrastructure d’envoi, pas le texte.

Retester après correction

Les gains attendus sont calculés une correction à la fois et ne se cumulent pas. Le deuxième rapport donne le chiffre réel.

Pour les machines

GET/api/health

Disponibilité. Aucune authentification, aucun effet secondaire.

Essayez-en d’abord un manuellement

Cela prend environ une minute et vous montre exactement ce que décrit le JSON.

Obtenir une adresse de test

Bac à sable.

Chaque endpoint dispose d’un bouton qui l’exécute sur le service en production. Rien ici ne nécessite de clé, donc toute requête lancée depuis cette page est réelle : elle réserve une adresse réelle et elle est comptabilisée.

Essayer dans le bac à sable