Email Spam Tester

L’API

Trois appels. Sans clé, sans compte, sans inscription.

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 41 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.

Essayer dans le 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.

La boucle

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.

  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.

  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.

# 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. send your message to that address, then poll
curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>/status'

{
  "slug": "<slug>",
  "analysis_status": "checks_ready",
  "ai_status": "running",
  "checks_done": 39,
  "checks_total": 39
}
# 3. 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"}}
  ]
}

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.

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.

GET/api/health

Disponibilité. Aucune authentification, aucun effet secondaire.

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 41 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

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