Discourse-Version: 2026.5.0-latest.1
Kontext
Wenn ein externer Nutzer eine E-Mail an den eingehenden Mail-Handler mit einer Gmail-„Punkt“-Variante (z. B. user.name@gmail.com) sendet, sein registrierter Forenaccount jedoch die nicht mit Punkten versehene Primärversion ist (username@gmail.com), stürzt der eingehende Mail-Handler mit einer nicht behandelten Ausnahme ab: ActiveRecord::RecordInvalid (Validation failed: Primary email has already been taken).
Darüber hinaus schlägt der Versuch fehl, diese Variante mit Punkten als sekundäre E-Mail-Adresse zum Benutzerprofil hinzuzufügen – entweder über die Benutzeroberfläche oder die Model-Schicht der Rails-Konsole mittels UserEmail.create! – mit dem exakt gleichen Validierungsschleifenfehler. Der einzige Workaround ist eine rohe SQL-Injection in die Datenbank, die ActiveRecord umgeht.
Schritte zur Reproduktion
-
Erstellen Sie einen Benutzeraccount auf Discourse mit der Primäre-Mail-Adresse
username@gmail.com. -
Lassen Sie diesen Benutzer eine eingehende E-Mail an eine Kategorie-/Antwortadresse von
user.name@gmail.comsenden. -
Beobachten Sie die Ablehnung in den Protokollen für eingehende E-Mails aufgrund von
ActiveRecord::RecordInvalid. -
Versuchen Sie,
user.name@gmail.comals sekundäre E-Mail-Adresse für den Accountusername@gmail.comüber die Rails-Konsole hinzuzufügen:UserEmail.create!(user_id: target_id, email: 'user.name@gmail.com', primary: false) -
Beobachten Sie den Absturz der Modellvalidierung.
Erwartetes Verhalten
Discourse sollte die Gmail-Normalisierung sauber handhaben. Es sollte entweder:
-
Die eingehende Gmail-Variante mit Punkten nahtlos als zum Primäraccount gehörend erkennen, während der Verarbeitung eingehender E-Mails.
-
Oder zumindest einem Administrator erlauben, die Variante mit Punkten als sekundäre E-Mail-Adresse zum Hauptaccount hinzuzufügen, ohne einen „Primäre-Mail-Adresse bereits vergeben“-Anwendungsblock auszulösen, da sie zum selben Benutzer gehört und explizit auf
primary: falsegesetzt ist.
Tatsächliches Verhalten
Die Anwendungsschicht gerät in eine Logikschleife:
-
Sie erkennt
user.name@gmail.comals neuen String und versucht daher, darauf zu reagieren (einen gestaffelten Benutzer erstellen oder eine sekundäre E-Mail-Adresse anhängen). -
Während der Validierungsphase führt das
UserEmail-Modell seine Gmail-Normalisierungslogik aus, entfernt die Punkte, stellt fest, dassusername@gmail.combereits der Primäre-Mail-Index für dieseuser_idist, und blockiert seine eigene Ausführung unter der falschen Annahme, dass ein Konflikt durch doppelte Datensätze vorliegt.
Verwendeter Workaround zur Freigabe
Der einzige Weg, dies zu lösen, bestand darin, per SSH in den Container zu gehen und rohes SQL auszuführen, um die ActiveRecord-Validierungen vollständig zu umgehen:
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)
Sobald dies per rohem SQL erzwungen wurde, funktioniert die Verfolgung eingehender E-Mails einwandfrei. Der Validierungscode sollte aktualisiert werden, um diesen Sonderfall zu berücksichtigen.
Vielen Dank!