Provalo nella sandbox → Ogni endpoint, con un pulsante che lo esegue sul servizio attivo. Qui non serve alcuna chiave, quindi una richiesta inviata da questa pagina è reale: riserva un indirizzo reale e viene conteggiata.
Il ciclo
Due richieste e un'email. La terza chiamata serve solo perché l'analisi richiede alcuni secondi.
Riserva un indirizzo
Invia una richiesta POST all'endpoint della casella di posta. Ricevi un indirizzo che accetta esattamente un messaggio e scade dopo un'ora, insieme allo slug su cui si basa tutto il resto.
Inviagli il messaggio reale
Tramite SMTP, dalla piattaforma che invierà la campagna. Metà dei controlli legge le intestazioni aggiunte dalla piattaforma di invio, quindi un messaggio composto a mano misura la cosa sbagliata.
Interroga lo stato, quindi leggi il report
L'endpoint di stato occupa poche centinaia di byte e indica se vale già la pena recuperare il report completo. Il report stesso si estende per diverse migliaia di righe.
# 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"}} ] }
Autenticazione
Non ce n'è. Nessuna chiave da richiedere, nessuna intestazione da impostare, nessun account da creare. Lo slug restituito è la capability: chiunque lo possieda può leggere quel report e nessun altro può indovinarlo.
Endpoint
Indirizzo base https://email-spam-tester.com. Tutto risponde in JSON.
POST/api/v1/inbox
Riserva un indirizzo monouso. Entrambi i parametri sono facoltativi.
| lang | Lingua in cui verranno scritti il piano di correzione e i risultati di ogni controllo, come codice ISO. Viene decisa ora perché il messaggio arriva tramite SMTP alcuni minuti dopo e non contiene alcuna indicazione su chi lo sta aspettando. Un codice sconosciuto usa l'inglese come fallback. |
| utm_source, utm_medium, utm_campaign | Inoltrati alle nostre analisi. Utile se stai misurando la tua integrazione. |
GET/api/v1/tests/{slug}/status
Economico da interrogare periodicamente. Restituisce i due campi di stato e l'avanzamento dei controlli, e nient'altro.
GET/api/v1/tests/{slug}
Il report completo. Risponde con 202 mentre l'indirizzo è riservato e non è ancora arrivato nulla, con 200 una volta ricevuto il messaggio.
GET/api/v1/tests/{slug}/message
Il messaggio esattamente come è stato recapitato: ogni intestazione nell'ordine di trasmissione, entrambi i corpi, l'elenco degli allegati e il sorgente grezzo. Viene recuperato separatamente perché il report viene interrogato periodicamente e questo può raggiungere un megabyte.
PUT/api/v1/tests/{slug}/locale
Cambia la lingua di una prenotazione che non è stata ancora utilizzata. Per un agente che apprende quale lingua legge il proprio utente dopo averne già richiesto l'indirizzo. La richiesta viene rifiutata una volta arrivato il messaggio, perché a quel punto l'analisi è in corso.
GET/api/health
Liveness. Nessuna autenticazione, nessun effetto collaterale.
Lettura del report
I campi che contengono la risposta, nell'ordine in cui probabilmente servono.
| score_ours | Da 0 a 100. Il nostro modello. L'autenticazione e l'infrastruttura hanno il peso maggiore, perché determinano la consegna prima che un filtro legga una parola del testo. |
| score_compat | Da 0 a 10. Riproduce il valore in stile SpamAssassin che gli utenti già confrontano, in modo che il report sia comparabile con quanto rilevato altrove. |
| subscores | La stessa scala da 0 a 100 per sezione: auth, infra_spam, content, compliance. |
| checks[] | Tutti e 41, ciascuno con uno stato, un esito di una riga, le evidenze su cui è stata basata la decisione e il relativo costo sui due punteggi. |
| checks[].citations | Da dove proviene il riscontro: la sezione della RFC, citata testualmente, e la pagina in cui Google dichiara il proprio requisito. Selezionati manualmente anziché generati, quindi sono affidabili. |
| fixes[] | Cosa modificare, in ordine, con i punti attribuiti a ciascuna modifica. I guadagni sono calcolati ricalcolando il punteggio del report, non stimati. |
| complete | Falso quando non è stato possibile eseguire un controllo. Un elemento non controllato non è mai un esito positivo, quindi considera il punteggio ottimistico finché non è vero. |
| report_url | La pagina leggibile da una persona. Fornisci quella a una persona anziché un muro di JSON. |
Stati
Un controllo può trovarsi in uno di cinque stati, e la differenza tra due di essi è più importante di quanto sembri.
| pass | Il controllo è stato eseguito e non ha rilevato problemi. |
| warn | Da correggere. Costa punti. |
| fail | Comprometterà la consegna. Costa più punti. |
| ignorato | Non applicabile. Nessun allegato da analizzare, nessuna parte HTML da valutare. Non è un esito positivo. |
| errore | Non è stato possibile determinarlo. Escluso dal punteggio e contrassegnato, anziché conteggiato come esito positivo. |
analysis_status assume i valori received, analyzing, checks_ready, failed. ai_status assume i valori pending, running, ready, fallback, error. Il report deterministico è definitivo a checks_ready; ai_status aggiunge sempre e solo il piano.
Cosa può essere restituito
| 202 | L'indirizzo è riservato e non è arrivato alcun messaggio. Il corpo contiene l'indirizzo, la scadenza e la lingua, quindi un chiamante che non ha creato la prenotazione può comunque mostrarla. |
| 404 | Nessuno slug corrispondente. Non è mai esistito oppure la prenotazione è stata dimenticata. |
| 410 | L'indirizzo è scaduto prima dell'arrivo di un messaggio. |
| 409 | Hai tentato di cambiare la lingua dopo che il messaggio era già arrivato. |
| 429 | Il limite di test gratuiti per il tuo indirizzo. Al momento non esiste alcun limite per persona su questo servizio; se ne verrà mai impostato uno, il corpo indicherà quando verrà reimpostato. |
Quattro cose da sapere
Un messaggio per indirizzo
Il secondo viene rifiutato. Il report precedente rimane intatto, ed è proprio questo lo scopo.
Un'ora per usarlo
L'indirizzo scade; il report no. I link ai report sono permanenti, quindi uno incollato in un ticket continua a funzionare.
Invia dalla piattaforma
Testare una campagna da un account personale misura quell'account. Quasi tutto nella sezione sull'autenticazione riguarda l'infrastruttura di invio, non il testo.
Ripeti il test dopo la correzione
I miglioramenti previsti vengono calcolati una correzione alla volta e non si sommano. Il secondo report fornisce il valore reale.
Per le macchine
- /api/openapi.json La descrizione OpenAPI, generata dallo stesso codice che serve l'API.
- /llms.txt, /llms-full.txt Una breve mappa di questo sito per i modelli linguistici, secondo la convenzione llms.txt, e una versione più lunga con l'intero ciclo e i campi del report in un unico file.
- /mcp Un server MCP con la stessa funzionalità e un'attesa bloccante, che è preferibile al polling dall'interno di un modello.
- For agents La pagina per gli agenti: quando ricorrere a questo strumento, come interpretare un controllo ignorato rispetto a uno superato e quali risultati sono record DNS che una persona deve modificare anziché testo che un agente può modificare.
Provane prima uno manualmente
Richiede circa un minuto e mostra esattamente ciò che descrive il JSON.