Convalida non riuscita: l'email principale è già stata presa quando si tentava di gestire le varianti con punto di Gmail o aggiungere email secondarie

Versione di Discourse: 2026.5.0-latest.1

Contesto

Quando un utente esterno invia un’e-mail al gestore della posta in arrivo utilizzando una variante con “punto” di Gmail (ad esempio, user.name@gmail.com), ma il suo account forum registrato è la versione primaria senza punti (username@gmail.com), il gestore della posta in arrivo si arresta con un’eccezione non gestita: ActiveRecord::RecordInvalid (Validation failed: Primary email has already been taken).

Inoltre, tentare di risolvere il problema aggiungendo la variante con punti come e-mail secondaria al profilo utente — sia tramite l’interfaccia utente che a livello del modello Rails Console utilizzando UserEmail.create! — fallisce con lo stesso errore di loop di convalida. L’unica soluzione è un’iniezione SQL diretta nel database, aggirando ActiveRecord.

Passaggi per la Riproduzione

  1. Crea un account utente su Discourse con l’e-mail primaria username@gmail.com.

  2. Fai sì che quell’utente invii un’e-mail in arrivo a un indirizzo di categoria/risposta da user.name@gmail.com.

  3. Osserva il rifiuto nei registri della posta in arrivo a causa di ActiveRecord::RecordInvalid.

  4. Prova ad aggiungere user.name@gmail.com come e-mail secondaria all’account username@gmail.com tramite la console Rails:

    UserEmail.create!(user_id: target_id, email: 'user.name@gmail.com', primary: false)
    
    
  5. Osserva il crash della convalida del modello.

Comportamento Atteso

Discourse gestisce la normalizzazione di Gmail in modo pulito. Dovrebbe:

  1. Riconoscere la variante di Gmail con punti in arrivo come appartenente all’account principale in modo trasparente durante la fase di gestione della posta in arrivo.

  2. Almeno, permettere a un amministratore di aggiungere la variante con punti come e-mail secondaria all’account principale senza attivare un blocco dell’applicazione per «E-mail primaria già presa», dato che appartiene allo stesso utente ed è esplicitamente impostata su primary: false.

Comportamento Effettivo

Il livello dell’applicazione rimane bloccato in un loop logico:

  • Rileva user.name@gmail.com come una stringa «nuova», quindi tenta di agire su di essa (creare un utente in fase di stesura o aggiungere un’e-mail secondaria).

  • Durante la fase di convalida, il modello UserEmail esegue la sua logica di normalizzazione di Gmail, rimuove i punti, rileva che username@gmail.com è già l’indice dell’e-mail primaria per quel user_id e blocca la propria esecuzione sotto la falsa ipotesi che si stia verificando un conflitto di record duplicati.

Soluzione Utilizzata per Sbloccare la Situazione

L’unico modo per risolvere il problema è stato accedere via SSH al contenitore ed eseguire SQL diretto per aggirare completamente le convalide di ActiveRecord:

sql = "INSERT INTO user_emails (user_id, email, \"primary\", created_at, updated_at) VALUES (X, 'user.name@gmail.com', false, NOW(), NOW())"
ActiveRecord::Base.connection.execute(sql)

Una volta forzato tramite SQL diretto, il tracciamento della posta in arrivo funziona perfettamente. Il codice di convalida dovrebbe essere aggiornato per tenere conto di questo caso limite.

Grazie!

2 Mi Piace