Vai al contenuto principale

Diario di bordo · Fase 0 · 4/7

La conferma via email per la lista d'attesa di aubia.dev

Il form di aubia.dev registra una richiesta prima della conferma via email. Correzioni di battitura, protezione dagli abusi e gestione degli indirizzi che restano in attesa.

Pubblicato il 3 agosto 2026Aggiornato il 13 settembre 20268 min di lettura
  • waitlist
  • react
  • security
  • gdpr

Può digitare l'indirizzo email di un'altra persona in un form. Il fatto che l'indirizzo superi la validazione non permette di sapere chi l'abbia inviato, né se il destinatario desideri ricevere un invito.

Su aubia.dev chiedo quindi una conferma via email. Il form crea un'iscrizione in attesa su aubia.cloud, poi un link ricevuto via email permette al destinatario di confermarla. Questo double opt-in aggiunge un passaggio al percorso, con la possibilità che il messaggio non venga mai aperto.

Il sito trasmette la richiesta senza conservare le iscrizioni in un database locale. L'articolo sull'assenza di database descrive questa separazione tra sito e cloud.

Il percorso animato dell'iscrizione: invio del form ad aubia.dev, richiesta firmata con HMAC ad api.aubia.cloud, email contenente un token e conferma entro 48 ore.

Correggere un errore di battitura prima dell'invio

Un indirizzo digitato male può essere valido e non ricevere mai il messaggio previsto. Il form suggerisce una correzione quando il dominio somiglia a quello di un servizio di posta noto: gmial.com può diventare gmail.com.

Il confronto usa la distanza di Levenshtein, che conta le modifiche necessarie per trasformare una stringa in un'altra. Esamina il dominio, poi il suffisso se non ha trovato una correzione per il dominio, confrontandoli con elenchi limitati. Non interroga la casella di posta e non corregge la parte prima della @.

Il suggerimento appare quando lascia il campo. Viene ricalcolato anche all'invio, perché l'invio da tastiera non richiede necessariamente di spostare il focus fuori dal campo. Se viene rilevato un probabile errore, il primo invio viene sospeso per lasciarle il tempo di rileggere l'indirizzo.

Può applicare la correzione o mantenere quanto ha digitato. Entrambi i pulsanti riportano il focus sul campo senza inviare il form. Può inviare una seconda volta lo stesso indirizzo anche senza scegliere una delle due opzioni: la somiglianza con un dominio noto non basta a bloccare un indirizzo che sa essere corretto.

La label è associata al campo, gli errori usano aria-invalid e role="alert", e aria-describedby collega il suggerimento al campo di input. Il messaggio di correzione deve essere leggibile anche senza distinguere un cambiamento di colore.

Un riscontro immediato, ancora provvisorio

Il componente React invia il form tramite Inertia, senza ricaricare l'intera pagina. Appena inizia l'invio, attiva una notifica globale gestita con useOptimistic. Il riscontro visivo appare prima della risposta del server.

Questa visualizzazione anticipa un esito positivo. Prima della risposta del server, il browser non sa ancora se il cloud abbia registrato la richiesta né se l'email potrà essere recapitata. La risposta effettiva sostituisce la notifica con il messaggio appropriato, oppure annulla lo stato provvisorio in caso di errore.

Il cloud distingue quattro esiti per una richiesta accettata:

Esito Gestione della richiesta
confirmation_sent Viene creata un'iscrizione in attesa e l'invio dell'email di conferma viene messo in coda.
confirmation_resent Viene preparato un nuovo link per un'iscrizione in attesa, trascorso l'intervallo che consente un nuovo invio.
already_pending Esiste già una richiesta recente; non viene avviato l'invio di un'altra email.
already_confirmed L'indirizzo è già confermato; non c'è un'iscrizione da ricominciare.

Ogni esito ha un messaggio tradotto nelle sei lingue del sito. Preferisco indicare che un indirizzo è già confermato piuttosto che lasciare il destinatario in attesa di un'email che non verrà inviata.

Il proxy controlla anche il codice di stato HTTP. Gli errori di validazione, di limitazione delle richieste e di servizio hanno la precedenza su un eventuale stato di successo nel corpo della risposta. Il codice HTTP 409 accompagnato esattamente da already_confirmed viene riconosciuto come iscrizione già confermata. Gli altri conflitti non vengono trattati come successi.

Un indirizzo rifiutato e un limite di richieste superato hanno ciascuno il proprio messaggio. Una firma rifiutata o un servizio cloud non disponibile producono un messaggio di indisponibilità temporanea; i dettagli tecnici servono alla diagnosi lato server.

Neppure confirmation_sent dimostra che l'email sia stata recapitata. L'invio è affidato a un job in coda: il server ne ha richiesto l'esecuzione, ma l'invio può ancora fallire o il servizio di posta del destinatario può filtrare il messaggio.

Limitare gli abusi senza captcha

Non aggiungo un captcha al form. Imporrebbe un'ulteriore verifica al visitatore senza rendere impossibili gli invii automatizzati. Il sito combina controlli che non richiedono altre interazioni.

Un honeypot, un campo nascosto alla vista ed escluso dalla navigazione da tastiera, deve restare vuoto. Permette di respingere gli invii dei bot che compilano i campi senza distinzione. Una trappola temporale confronta il timestamp fornito dal browser con l'istante dell'invio e rifiuta gli invii troppo rapidi.

Il server verifica questi valori, ma provengono dal client. Un programma può lasciare vuoto l'honeypot e fornire un timestamp accettabile. Queste trappole filtrano comportamenti semplici; non dimostrano che il form sia stato compilato da una persona.

Un rate limiter interviene in parallelo per indirizzo IP, per indirizzo email e sul volume complessivo delle richieste. Il limite per email riduce le richieste ripetute rivolte allo stesso destinatario. Il limite globale contiene il numero di richieste anche quando provengono da più IP, con il rischio di rifiutare anche iscrizioni legittime durante un picco di traffico.

La validazione dell'indirizzo ne controlla il formato e, in produzione, il DNS del dominio. Il DNS può aiutare a escludere un dominio inadatto a ricevere posta, ma non stabilisce se la specifica casella esista.

Una volta accettata dal sito, la richiesta viene firmata con HMAC prima di essere trasmessa al cloud. I due server condividono un segreto che permette di verificare la firma del corpo ricevuto. Questa protezione riguarda la richiesta di iscrizione tra server: impedisce di sostituire il proxy con una chiamata non firmata a quell'endpoint. Non tutte le altre route dell'API richiedono questa firma, in particolare quelle che usano i token di conferma o di cancellazione dell'iscrizione.

Il link ricevuto via email

Il cloud registra l'indirizzo con lo stato PENDING prima di preparare l'email. Il link contiene un token casuale, di cui viene conservato soltanto l'hash nel record dell'iscrizione. È valido per 48 ore a partire dalla data di invio registrata dall'applicazione, prima dell'esecuzione del job di posta.

Il pulsante di conferma apre una pagina di aubia.dev nella lingua usata per l'iscrizione. Dopo il caricamento, la pagina legge il token nell'URL e interroga direttamente l'API cloud. Mostra il risultato: confermato, già confermato, link non valido, non trovato o scaduto.

La conferma aggiorna lo stato e la relativa data una sola volta. Due richieste concorrenti non devono generare due conferme. Un altro clic sullo stesso link riconosciuto restituisce "già confermato", anche dopo il periodo di validità iniziale, perché l'iscrizione è già stata completata.

Per un indirizzo ancora in attesa, un nuovo invio sostituisce l'hash del token e fa ripartire il periodo di validità. Il link precedente non permette quindi più di trovare l'iscrizione. Il nuovo invio invalida il vecchio link già al momento della preparazione, anche se la nuova email non è ancora arrivata.

Le pagine di conferma e di cancellazione dell'iscrizione dichiarano noindex. Questa direttiva chiede ai motori di ricerca di non indicizzarle; non ne limita l'accesso. I link del selettore di lingua vengono ricostruiti senza la query string, per evitare di copiare il token negli altri cinque URL. Cambiare lingua non permette quindi di proseguire la conferma con quel token.

Anche un programma capace di seguire il link e completare questo percorso può confermare. Il double opt-in verifica l'uso di un link inviato all'indirizzo fornito, senza certificare l'identità o la presenza umana di chi lo usa. Il timestamp di conferma aiuta a tenere traccia dell'iscrizione; da solo non basta a dimostrare la piena conformità del trattamento al GDPR.

Gli indirizzi che restano in attesa

La scadenza del token non elimina il record. Un'attività giornaliera elimina le iscrizioni ancora PENDING la cui data di iscrizione iniziale risale a più di 30 giorni prima. Un nuovo invio della conferma non azzera questo periodo di conservazione.

La cancellazione dell'iscrizione segue un processo diverso. La pagina dedicata trasmette il token al cloud, che anonimizza il record: l'indirizzo email viene sostituito, i token e i dati di attribuzione vengono eliminati e lo stato diventa PURGED. Il record rimane, insieme alle sue date.

Il pulsante di conferma nel corpo dell'email è distinto dalle intestazioni List-Unsubscribe e List-Unsubscribe-Post. Queste intestazioni forniscono ai client di posta le istruzioni per proporre la cancellazione dell'iscrizione. La loro presenza non garantisce che ogni client mostri il comando o lo gestisca allo stesso modo.

Che cosa misura il contatore

Il contatore della pagina iniziale chiede al cloud il numero di iscrizioni con stato CONFIRMED. Gli indirizzi in attesa sono esclusi. Vengono contati anche gli inviti amministrativi registrati direttamente come confermati: il totale non corrisponde quindi esclusivamente ai clic sui link provenienti dal form pubblico.

Il valore arriva dopo il rendering iniziale tramite una richiesta differita, con una cache lato server. Può essere in ritardo rispetto a una conferma e viene visualizzato solo oltre una soglia. L'articolo su Octane e Inertia SSR descrive il meccanismo di caricamento.

Per misurare quante richieste dal form arrivano alla conferma, devo distinguerle dagli inviti amministrativi.

Questo cantiere si racconta qui, articolo dopo articolo. Ciò che viene dopo dipende da ciò che lei ne dirà.

Si iscriva alla lista d'attesa