From 4303dc32fc689f8b51ff12c7aebafb6d39dd0c93 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 19 May 2026 13:43:01 +0530 Subject: [PATCH] fix: allow free email providers during installation onboarding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Installation onboarding creates the first super-admin via AccountBuilder, which routes through SignUpEmailValidationService. Without an opt-out, a self-hoster setting up Chatwoot with a gmail/outlook admin email would be rejected at install time — a regression for a flow that has nothing to do with public abuse signals. Adds an allow_free_email_provider keyword to the service and plumbs it through AccountBuilder. The public signup paths (api/v1/accounts and the omniauth callback) continue to enforce the check by default; only the onboarding controller opts out. --- app/builders/account_builder.rb | 5 +++-- app/controllers/installation/onboarding_controller.rb | 3 ++- .../account/sign_up_email_validation_service.rb | 5 +++-- spec/builders/account_builder_spec.rb | 2 +- .../account/sign_up_email_validation_service_spec.rb | 11 +++++++++++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/app/builders/account_builder.rb b/app/builders/account_builder.rb index 5127ea612..91404a84f 100644 --- a/app/builders/account_builder.rb +++ b/app/builders/account_builder.rb @@ -2,7 +2,8 @@ class AccountBuilder include CustomExceptions::Account - pattr_initialize [:account_name, :email!, :confirmed, :user, :user_full_name, :user_password, :super_admin, :locale] + pattr_initialize [:account_name, :email!, :confirmed, :user, :user_full_name, :user_password, :super_admin, :locale, + :allow_free_email_provider] def perform if @user.nil? @@ -32,7 +33,7 @@ class AccountBuilder end def validate_email - Account::SignUpEmailValidationService.new(@email).perform + Account::SignUpEmailValidationService.new(@email, allow_free_email_provider: @allow_free_email_provider).perform end def validate_user diff --git a/app/controllers/installation/onboarding_controller.rb b/app/controllers/installation/onboarding_controller.rb index 272b4e5eb..e54f0b6ba 100644 --- a/app/controllers/installation/onboarding_controller.rb +++ b/app/controllers/installation/onboarding_controller.rb @@ -11,7 +11,8 @@ class Installation::OnboardingController < ApplicationController email: onboarding_params.dig(:user, :email), user_password: params.dig(:user, :password), super_admin: true, - confirmed: true + confirmed: true, + allow_free_email_provider: true ).perform rescue StandardError => e redirect_to '/', flash: { error: e.message } and return diff --git a/app/services/account/sign_up_email_validation_service.rb b/app/services/account/sign_up_email_validation_service.rb index f354377ba..881b3b6a0 100644 --- a/app/services/account/sign_up_email_validation_service.rb +++ b/app/services/account/sign_up_email_validation_service.rb @@ -4,8 +4,9 @@ class Account::SignUpEmailValidationService include CustomExceptions::Account attr_reader :email - def initialize(email) + def initialize(email, allow_free_email_provider: false) @email = email + @allow_free_email_provider = allow_free_email_provider end def perform @@ -17,7 +18,7 @@ class Account::SignUpEmailValidationService raise InvalidEmail.new({ valid: true, disposable: true }) if address.disposable? - raise InvalidEmail.new({ free_email_provider: true }) if address.deny_listed? + raise InvalidEmail.new({ free_email_provider: true }) if !@allow_free_email_provider && address.deny_listed? true end diff --git a/spec/builders/account_builder_spec.rb b/spec/builders/account_builder_spec.rb index 550e12e0a..70b1f3928 100644 --- a/spec/builders/account_builder_spec.rb +++ b/spec/builders/account_builder_spec.rb @@ -20,7 +20,7 @@ RSpec.describe AccountBuilder do # Mock the email validation service before do - allow(Account::SignUpEmailValidationService).to receive(:new).with(email).and_return(validation_service) + allow(Account::SignUpEmailValidationService).to receive(:new).with(email, allow_free_email_provider: anything).and_return(validation_service) end describe '#perform' do diff --git a/spec/services/account/sign_up_email_validation_service_spec.rb b/spec/services/account/sign_up_email_validation_service_spec.rb index 7bf9f7b24..6f6f49163 100644 --- a/spec/services/account/sign_up_email_validation_service_spec.rb +++ b/spec/services/account/sign_up_email_validation_service_spec.rb @@ -121,5 +121,16 @@ RSpec.describe Account::SignUpEmailValidationService, type: :service do expect(error.message).to eq(I18n.t('errors.signup.disposable_email')) end end + + it 'allows free email providers when allow_free_email_provider is true' do + expect(described_class.new('admin@gmail.com', allow_free_email_provider: true).perform).to be(true) + end + + it 'still rejects disposable emails even when allow_free_email_provider is true' do + expect { described_class.new('user@mailinator.com', allow_free_email_provider: true).perform }.to raise_error do |error| + expect(error.class.name).to eq('CustomExceptions::Account::InvalidEmail') + expect(error.message).to eq(I18n.t('errors.signup.disposable_email')) + end + end end end