Mailjet
A cosa serve
Mailjet è il provider per il contratto Subscription Form a double opt-in
documentato come form ospitato embedded (iframe + script resizer), contatti e
consenso, Campaign Draft, scheduling e delivery email. Architecture Coffee
possiede lo shell di pagina, la copia circostante e una pagina di conferma
visuale; Mailjet resta autorità di DOI, markup del form di iscrizione e
lifecycle del contatto.
flowchart TB
publish["Pubblicazione Issue in D1"] --> public["Issue pubblicato"]
public -.->|"non avvia Mailjet"| intent["Intento scheduling esplicito"]
intent --> durable["D1: snapshot + job + outbox"]
durable --> queue["Queue: solo jobId"]
queue --> prepare["Executor durevole"]
prepare --> draft["Campaign Draft Mailjet"]
draft --> content["Upload contenuto esplicito"]
content --> schedule["Scheduling esplicito"]
schedule --> delivery["Delivery provider"]
reader["Lettore"] --> acShell["Shell pagina Architecture Coffee"]
acShell --> mailjetEmbed["Iframe Subscription Form Mailjet"]
mailjetEmbed --> confirmPage["Pagina conferma visuale AC"]
mailjetEmbed --> contacts["Contatti, consenso e suppression Mailjet"]
contacts --> delivery
Componenti che lo usano
Provider Campaign Draft, servizio Campaign Draft, consumer Queue dedicato, provider di delivery e superficie pubblica che incorpora l'embed Subscription Form Mailjet documentato.
Dati e artefatti scambiati
Architecture Coffee persiste prima uno snapshot immutabile con subject, HTML/testo, hash e revisione Issue. L'executor invia sempre quello snapshot, il target list referenziato e lo scheduling autorizzato. Mailjet restituisce identificatori e stati provider, conservati solo in forma necessaria e sanitizzata. Gli indirizzi destinatario restano in Mailjet. Identificatori e parametri dell'embed provider sono configurazione runtime non segreta e non espongono credenziali o PII.
Autenticazione e autorizzazione
Le credenziali Mailjet sono secret Worker e non raggiungono il browser. Access
autentica l'Admin; l'API applica permessi distinti
email:contacts:read/manage e
email:campaigns:read/prepare/content/schedule/deliver/reconcile, quindi
proietta soltanto target e azioni consentite. Il consenso destinatario pubblico
è gestito dall'embed Subscription Form e dal lifecycle Mailjet, non da un
endpoint pubblico Architecture Coffee di iscrizione. La disiscrizione pubblica
usa soltanto POST /newsletter/unsubscribe, che mappa a Mailjet unsub con
readback canonico senza esporre liste, payload provider o membership precedente.
Il public site può applicare solo la CSP allowlist minima richiesta dagli
origin documentati dell'embed Mailjet.
Cosa possiede il provider
Mailjet possiede markup del form di iscrizione embedded, submit e stati immediati in-frame, contatti, liste, double opt-in, unsubscribe, bounce, suppression, scheduling provider e stato di delivery destinatario.
Cosa possiede Architecture Coffee
D1 possiede Issue Content canonico, stato editoriale, intento Campaign Draft, aggregate, job, snapshot immutabile, outbox, lease, attempt e audit sanitizzato. La pubblicazione non possiede o modifica destinatari. La superficie pubblica può possedere solo lo shell di pagina, la copia circostante, l'accessibilità fuori dal frame e una pagina di conferma visuale, senza markup del form di iscrizione, token DOI, pending subscription, consenso o PII subscriber.
Operazioni automatiche, manuali e protette
La Queue può eseguire un job di scheduling già autorizzato e trasporta solo il
jobId. Il consumer possiede preparazione, upload, scheduling e recovery; il
dispatcher tecnico possiede solo redispatch e lease scadute. Anche
subscribe e unsubscribe individuali Admin/MCP sono comandi espliciti distinti e
usano solo la lista allowlisted; subscribe usa addnoforce come gestione
operatore dei contatti e non è il meccanismo DOI pubblico, né forza la
riattivazione di contatti unsubscribed o suppressed. Pubblicazione e
approvazione non chiamano Mailjet. La modalità live resta fail-closed se
disabilitata o incompleta.
Fallimenti e comportamento fail-closed
Configurazione target o live incompleta, risposta non conforme, timeout o
status ambiguo producono errore sanitizzato. Un timeout dopo l'inizio di una
mutazione porta prima a readback: correlation ID per la draft, confronto con
lo snapshot per il contenuto e confronto con scheduledFor per lo schedule.
Nessun POST ambiguo viene ritentato alla cieca. Gli indirizzi sono validati solo
nel boundary autorizzato e non vengono persistiti in D1, MCP audit o log.
Retry crea un attempt collegato
solo per una preparazione o un upload che il server classifica come
ritentabile. Lo scheduling non viene ritentato ciecamente: un esito ignoto
richiede riconciliazione. Mock/dry-run non provano delivery reale. Nessun
destinatario viene copiato in D1 come recovery. Configurazione embed pubblica
assente o non valida fallisce chiusa in stato non disponibile.
Verifiche operative
- modalità provider e azioni proiettate;
- target mostrato solo come alias e riferimento mascherato;
- attempt distinti per preparazione, contenuto e scheduling;
- riconciliazione dello stato Campaign Draft;
- finestra schedule da 15 minuti a 180 giorni, timezone IANA e offset/DST coerenti;
- idempotenza e rate limit D1-backed delle mutazioni contatto;
- delivery single-flight: accepted non equivale a delivered e unknown blocca retry ciechi;
- assenza di chiamate Mailjet durante pubblicazione;
- prova live soltanto da evidenza provider autorizzata.