diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index e96c2fc35ca..fc0e8529f3d 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,3 +1,4 @@ +# rubocop:disable Metrics/ClassLength class UserMailer < ActionMailer::Base include Mailable include LocaleHelper @@ -122,4 +123,10 @@ def email_added(email) def email_deleted(email) mail(to: email, subject: t('user_mailer.email_deleted.subject')) end + + def add_email_associated_with_another_account(email) + @root_url = root_url(locale: locale_url_param) + mail(to: email, subject: t('mailer.email_reuse_notice.subject')) + end end +# rubocop:enable Metrics/ClassLength diff --git a/app/services/send_add_email_confirmation.rb b/app/services/send_add_email_confirmation.rb index 8bf94ed7f36..6d4975f3b0e 100644 --- a/app/services/send_add_email_confirmation.rb +++ b/app/services/send_add_email_confirmation.rb @@ -8,7 +8,7 @@ def initialize(user) def call(email_address) @email_address = email_address update_email_address_record - send_confirmation_email + send_email end private @@ -30,6 +30,28 @@ def update_email_address_record ) end + def already_confirmed_by_another_user? + EmailAddress.where( + email_fingerprint: Pii::Fingerprinter.fingerprint(email_address.email), + ).where.not(confirmed_at: nil). + where.not(user_id: email_address.user_id). + first + end + + def send_email + if already_confirmed_by_another_user? + send_email_associated_with_another_account_email + else + send_confirmation_email + end + end + + def send_email_associated_with_another_account_email + UserMailer.add_email_associated_with_another_account( + email_address.email, + ).deliver_later + end + def send_confirmation_email UserMailer.add_email( user, diff --git a/app/views/user_mailer/add_email_associated_with_another_account.html.slim b/app/views/user_mailer/add_email_associated_with_another_account.html.slim new file mode 100644 index 00000000000..285bd180d71 --- /dev/null +++ b/app/views/user_mailer/add_email_associated_with_another_account.html.slim @@ -0,0 +1,35 @@ +p.lead == t('.intro', app: link_to(APP_NAME, Figaro.env.mailer_domain_name, class: 'gray')) + +table.button.expanded.large.radius + tbody + tr + td + table + tbody + tr + td + center + = link_to t('.link_text', app: APP_NAME), + @root_url, target: '_blank', + class: 'float-center', align: 'center' + td.expander + +p = link_to @root_url, @root_url, target: '_blank' + +table.spacer + tbody + tr + td.s10 height="10px" + |   +table.hr + tr + th + |   + +p == t('.reset_password', + app: link_to(APP_NAME, Figaro.env.mailer_domain_name, class: 'gray')) + +p == t('.help', + app: link_to(APP_NAME, Figaro.env.mailer_domain_name, class: 'gray'), + help_link: link_to(t('user_mailer.help_link_text'), MarketingSite.help_url), + contact_link: link_to(t('user_mailer.contact_link_text'), MarketingSite.contact_url)) diff --git a/config/locales/user_mailer/en.yml b/config/locales/user_mailer/en.yml index c3a9db354dd..b5a7a1d9cad 100644 --- a/config/locales/user_mailer/en.yml +++ b/config/locales/user_mailer/en.yml @@ -42,6 +42,16 @@ en: header: Thanks for adding an email. Please click the link below or copy and paste the entire link into your browser. subject: Confirm your email + add_email_associated_with_another_account: + help: If you did not request a new email or suspect an error, please visit the + %{app} %{help_link} or %{contact_link}. + intro: This email address is already associated with a %{app} account, so we + can’t add it to another account. You must first delete or remove it from the + account it is associated with. To do this, follow the link below and sign + in with this email address. If you are not trying to add this email address + to an account, you can ignore this message. + link_text: Go to %{app} + reset_password: If you can't remember your password, go to %{app} to reset it. contact_link_text: contact us doc_auth_link: message: You've requested to verify your identity on a desktop computer. Please diff --git a/config/locales/user_mailer/es.yml b/config/locales/user_mailer/es.yml index 9cd3a6bf47b..cd5839f3af8 100644 --- a/config/locales/user_mailer/es.yml +++ b/config/locales/user_mailer/es.yml @@ -43,6 +43,17 @@ es: header: Gracias por agregar un email. Haga clic en el enlace de abajo o copie y pegue el enlace completo en su navegador. subject: Confirme su email + add_email_associated_with_another_account: + help: Si no solicitó un nuevo correo electrónico o sospecha de un error, visite + %{app} %{help_link} o %{contact_link}. + intro: Esta dirección de correo electrónico ya está asociada con una cuenta + %{app}, por lo que no podemos agregarla a otra cuenta. Primero debe eliminarlo + o eliminarlo de la cuenta con la que está asociado. Para hacer esto, siga + el enlace de abajo e inicie sesión con esta dirección de correo electrónico. + Si no está intentando agregar esta dirección de correo electrónico a una cuenta, + puede ignorar este mensaje. + link_text: Ir a %{app} + reset_password: Si no recuerda su contraseña, vaya a %{app} para restablecerla. contact_link_text: Contáctenos doc_auth_link: message: You've requested to verify your identity on a desktop computer. Please diff --git a/config/locales/user_mailer/fr.yml b/config/locales/user_mailer/fr.yml index d5750884593..35ec65f734b 100644 --- a/config/locales/user_mailer/fr.yml +++ b/config/locales/user_mailer/fr.yml @@ -43,6 +43,18 @@ fr: header: Merci d'avoir ajouté un email. S'il vous plaît cliquez sur le lien ci-dessous ou copiez et collez le lien en entier dans votre navigateur. subject: Confirmez votre email + add_email_associated_with_another_account: + help: Si vous n'avez pas demandé de nouvel email ou que vous suspectez une erreur, + veuillez visiter le %{app} %{help_link} ou %{contact_link}. + intro: Cette adresse électronique est déjà associée à un compte %{app}, nous + ne pouvons donc pas l’ajouter à un autre compte. Vous devez d'abord le supprimer + ou le supprimer du compte auquel il est associé. Pour ce faire, suivez le + lien ci-dessous et connectez-vous avec cette adresse e-mail. Si vous n'essayez + pas d'ajouter cette adresse électronique à un compte, vous pouvez ignorer + ce message. + link_text: Allez à %{app} + reset_password: Si vous ne vous souvenez plus de votre mot de passe, allez à + %{app} pour le réinitialiser. contact_link_text: communiquez avec nous doc_auth_link: message: You've requested to verify your identity on a desktop computer. Please diff --git a/spec/features/multiple_emails/add_email_spec.rb b/spec/features/multiple_emails/add_email_spec.rb index 13b13e84d45..5f94e361dcf 100644 --- a/spec/features/multiple_emails/add_email_spec.rb +++ b/spec/features/multiple_emails/add_email_spec.rb @@ -59,13 +59,12 @@ expect(page).to have_content(t('devise.confirmations.already_confirmed', action: nil).strip) end - it 'notifies user they are already confirmed on another account' do - create(:user, :signed_up, email: email) - + it 'notifies user they are already confirmed on another account after clicking on link' do user = create(:user, :signed_up) sign_in_user_and_add_email(user) email_to_click_on = last_email_sent + create(:user, :signed_up, email: email) click_on_link_in_confirmation_email(email_to_click_on) expect(page).to have_current_path(account_path) @@ -74,6 +73,17 @@ ) end + it 'notifies user they are already confirmed on another account via email' do + create(:user, :signed_up, email: email) + + user = create(:user, :signed_up) + sign_in_user_and_add_email(user, false) + + expect(last_email_sent.default_part_body.to_s).to have_content( + t('user_mailer.add_email_associated_with_another_account.intro', app: APP_NAME), + ) + end + it 'routes to root with a bad confirmation token' do visit add_email_confirmation_url(confirmation_token: 'foo') @@ -157,7 +167,7 @@ end end - def sign_in_user_and_add_email(user) + def sign_in_user_and_add_email(user, add_email = true) sign_in_and_2fa_user(user) visit account_path @@ -165,8 +175,13 @@ def sign_in_user_and_add_email(user) expect(page).to have_current_path(add_email_path) - expect(UserMailer).to receive(:add_email). - with(user, anything, anything).and_call_original + if add_email + expect(UserMailer).to receive(:add_email). + with(user, anything, anything).and_call_original + else + expect(UserMailer).to receive(:add_email_associated_with_another_account). + with(email).and_call_original + end fill_in 'Email', with: email click_button t('forms.buttons.submit.default')