Versão do Discourse: 2026.5.0-latest.1
Contexto
Quando um usuário externo envia um e-mail ao gerenciador de e-mails recebidos usando uma variante com “ponto” do Gmail (por exemplo, user.name@gmail.com), mas sua conta registrada no fórum é a versão primária sem pontos (username@gmail.com), o gerenciador de e-mails recebidos falha com uma exceção não tratada: ActiveRecord::RecordInvalid (Validation failed: Primary email has already been taken).
Além disso, tentar resolver isso adicionando a variante com ponto como um e-mail secundário ao perfil do usuário — seja pela interface do usuário ou pela camada de modelo do Rails Console usando UserEmail.create! — falha com o mesmo erro de loop de validação. A única solução alternativa é uma injeção SQL direta no banco de dados, contornando o ActiveRecord.
Passos para Reproduzir
-
Crie uma conta de usuário no Discourse com o e-mail primário
username@gmail.com. -
Peça que esse usuário envie um e-mail recebido para um endereço de categoria/resposta a partir de
user.name@gmail.com. -
Observe a rejeição nos logs de e-mails recebidos devido ao erro
ActiveRecord::RecordInvalid. -
Tente adicionar
user.name@gmail.comcomo um e-mail secundário à contausername@gmail.comvia console do Rails:UserEmail.create!(user_id: target_id, email: 'user.name@gmail.com', primary: false) -
Observe a falha na validação do modelo.
Comportamento Esperado
O Discourse deve lidar com a normalização do Gmail de forma adequada. Ele deveria:
-
Reconhecer a variante do Gmail com ponto recebida como pertencente à conta primária de forma transparente durante o processamento de e-mails recebidos.
-
Ou, pelo menos, permitir que um administrador adicione a variante com ponto como um e-mail secundário à conta principal sem disparar um bloqueio de aplicação de “E-mail primário já utilizado”, já que pertence ao mesmo usuário e está explicitamente definido como
primary: false.
Comportamento Atual
A camada de aplicação fica presa em um loop lógico:
-
Ela vê
user.name@gmail.comcomo uma string “nova”, então tenta agir sobre ela (criar um usuário em estágio ou adicionar um e-mail secundário). -
Durante a fase de validação, o modelo
UserEmailexecuta sua lógica de normalização do Gmail, remove os pontos, verifica queusername@gmail.comjá é o índice de e-mail primário para aqueleuser_ide bloqueia sua própria execução sob a falsa premissa de que está ocorrendo um conflito de registro duplicado.
Solução Alternativa Utilizada para Desbloquear
A única maneira de resolver isso foi fazer SSH no contêiner e executar SQL direto para contornar completamente as validações do 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)
Uma vez forçado via SQL direto, o rastreamento de e-mails recebidos funciona perfeitamente. O código de validação deve ser atualizado para levar em conta esse caso limite.
Obrigado!