Validierung fehlgeschlagen: Die primäre E-Mail-Adresse ist bereits vergeben beim Versuch, Gmail-Punkt-Varianten zu verarbeiten oder sekundäre E-Mails hinzuzufügen

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

  1. Erstellen Sie einen Benutzeraccount auf Discourse mit der Primäre-Mail-Adresse username@gmail.com.

  2. Lassen Sie diesen Benutzer eine eingehende E-Mail an eine Kategorie-/Antwortadresse von user.name@gmail.com senden.

  3. Beobachten Sie die Ablehnung in den Protokollen für eingehende E-Mails aufgrund von ActiveRecord::RecordInvalid.

  4. Versuchen Sie, user.name@gmail.com als sekundäre E-Mail-Adresse für den Account username@gmail.com über die Rails-Konsole hinzuzufügen:

    UserEmail.create!(user_id: target_id, email: 'user.name@gmail.com', primary: false)
    
    
  5. Beobachten Sie den Absturz der Modellvalidierung.

Erwartetes Verhalten

Discourse sollte die Gmail-Normalisierung sauber handhaben. Es sollte entweder:

  1. Die eingehende Gmail-Variante mit Punkten nahtlos als zum Primäraccount gehörend erkennen, während der Verarbeitung eingehender E-Mails.

  2. 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: false gesetzt ist.

Tatsächliches Verhalten

Die Anwendungsschicht gerät in eine Logikschleife:

  • Sie erkennt user.name@gmail.com als 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, dass username@gmail.com bereits der Primäre-Mail-Index für diese user_id ist, 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!

2 „Gefällt mir“