diff --git a/app/controllers/idv/by_mail/enter_code_controller.rb b/app/controllers/idv/by_mail/enter_code_controller.rb index 76f0654177b..d49b3fe4dd7 100644 --- a/app/controllers/idv/by_mail/enter_code_controller.rb +++ b/app/controllers/idv/by_mail/enter_code_controller.rb @@ -55,6 +55,8 @@ def create result = @gpo_verify_form.submit(resolved_authn_context_result.enhanced_ipp?) analytics.idv_verify_by_mail_enter_code_submitted(**result) + send_please_call_email_if_necessary(result:) + if !result.success? if rate_limiter.limited? redirect_to idv_enter_code_rate_limited_url @@ -120,6 +122,19 @@ def rate_limiter ) end + # @param [FormResponse] result GpoVerifyForm result + def send_please_call_email_if_necessary(result:) + return if !result.success? + + return if result.extra[:pending_in_person_enrollment] + + return if !result.extra[:fraud_check_failed] + + return if !FeatureManagement.proofing_device_profiling_decisioning_enabled? + + current_user.send_email_to_all_addresses(:idv_please_call) + end + def build_gpo_verify_form GpoVerifyForm.new( user: current_user, diff --git a/app/controllers/idv/enter_password_controller.rb b/app/controllers/idv/enter_password_controller.rb index af6da96312f..dc5bdfaa327 100644 --- a/app/controllers/idv/enter_password_controller.rb +++ b/app/controllers/idv/enter_password_controller.rb @@ -143,6 +143,10 @@ def init_profile log_letter_enqueued_analytics(resend: false) end + if profile.fraud_review_pending? && !profile.in_person_verification_pending? + current_user.send_email_to_all_addresses(:idv_please_call) + end + if profile.active? create_user_event(:account_verified) UserAlerts::AlertUserAboutAccountVerified.call( diff --git a/app/jobs/get_usps_proofing_results_job.rb b/app/jobs/get_usps_proofing_results_job.rb index 78ad7a08c5b..ebb16537316 100644 --- a/app/jobs/get_usps_proofing_results_job.rb +++ b/app/jobs/get_usps_proofing_results_job.rb @@ -610,7 +610,7 @@ def send_failed_fraud_email(enrollment:, visited_location_name:) def send_please_call_email(enrollment:, visited_location_name:) enrollment.user.confirmed_email_addresses.each do |email_address| # rubocop:disable IdentityIdp/MailLaterLinter - UserMailer.with(user: enrollment.user, email_address: email_address).in_person_please_call( + UserMailer.with(user: enrollment.user, email_address: email_address).idv_please_call( enrollment: enrollment, visited_location_name: visited_location_name, ).deliver_later(**notification_delivery_params(enrollment)) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 46e480dab2a..eb623771eed 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -249,6 +249,9 @@ def account_verified(profile:) end def idv_please_call(**) + attachments.inline['phone_icon.png'] = + Rails.root.join('app/assets/images/email/phone_icon.png').read + with_user_locale(user) do @hide_title = true diff --git a/app/views/user_mailer/idv_please_call.html.erb b/app/views/user_mailer/idv_please_call.html.erb index 54f4a89ba9f..989409d1602 100644 --- a/app/views/user_mailer/idv_please_call.html.erb +++ b/app/views/user_mailer/idv_please_call.html.erb @@ -1,5 +1,5 @@ <%= image_tag( - asset_url('email/phone_icon.png'), + attachments['phone_icon.png'].url, alt: t('image_description.phone_icon'), width: 88, height: 88, diff --git a/spec/controllers/idv/by_mail/enter_code_controller_spec.rb b/spec/controllers/idv/by_mail/enter_code_controller_spec.rb index 5e0a8581413..e9f5ef0f835 100644 --- a/spec/controllers/idv/by_mail/enter_code_controller_spec.rb +++ b/spec/controllers/idv/by_mail/enter_code_controller_spec.rb @@ -285,6 +285,14 @@ expect(event_count).to eq 1 expect(response).to redirect_to(idv_personal_key_url) end + + it 'does not send the "Please Call" email' do + action + expect_email_not_delivered( + to: user.confirmed_email_addresses.first.email, + subject: t('user_mailer.idv_please_call.subject', app_name: APP_NAME), + ) + end end end @@ -323,6 +331,14 @@ expect(UserAlerts::AlertUserAboutAccountVerified).not_to have_received(:call) end + + it 'sends the "Please Call" email' do + action + expect_delivered_email( + to: user.confirmed_email_addresses.first.email, + subject: t('user_mailer.idv_please_call.subject', app_name: APP_NAME), + ) + end end context 'with threatmetrix status of "review"' do diff --git a/spec/controllers/idv/enter_password_controller_spec.rb b/spec/controllers/idv/enter_password_controller_spec.rb index fcb3b8b8e70..a96a19998d4 100644 --- a/spec/controllers/idv/enter_password_controller_spec.rb +++ b/spec/controllers/idv/enter_password_controller_spec.rb @@ -13,6 +13,8 @@ end let(:applicant) { Idp::Constants::MOCK_IDV_APPLICANT_WITH_PHONE } let(:use_gpo) { false } + let(:threatmetrix_enabled) { true } + let(:threatmetrix_result) { 'pass' } let(:idv_session) do subject.idv_session end @@ -28,6 +30,7 @@ subject.idv_session.pii_from_doc = Pii::StateId.new(**Idp::Constants::MOCK_IDV_APPLICANT) subject.idv_session.ssn = Idp::Constants::MOCK_IDV_APPLICANT_WITH_PHONE[:ssn] subject.idv_session.threatmetrix_session_id = 'random-session-id' + subject.idv_session.threatmetrix_review_status = threatmetrix_result subject.idv_session.resolution_successful = true subject.idv_session.applicant = Idp::Constants::MOCK_IDV_APPLICANT_WITH_PHONE subject.idv_session.resolution_successful = true @@ -43,6 +46,9 @@ end subject.idv_session.applicant = applicant.with_indifferent_access + + allow(IdentityConfig.store).to receive(:proofing_device_profiling) + .and_return(threatmetrix_enabled ? :enabled : :disabled) end describe '#step_info' do @@ -404,6 +410,41 @@ def show expect(events_count).to eq 1 end + context 'user was flagged by ThreatMetrix' do + let(:threatmetrix_result) { 'reject' } + + it 'sends the idv_please_call email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_delivered_email( + to: user.confirmed_email_addresses.first.email, + subject: t('user_mailer.idv_please_call.subject', app_name: APP_NAME), + ) + end + + it 'does not send the account_verified email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_email_not_delivered( + subject: t('user_mailer.account_verified.subject', app_name: APP_NAME), + ) + end + + context 'but ThreatMetrix disabled' do + let(:threatmetrix_enabled) { false } + it 'does not send the idv_please_call email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_email_not_delivered( + subject: t('user_mailer.idv_please_call.subject'), + ) + end + it 'sends the account_verified email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_delivered_email( + subject: t('user_mailer.account_verified.subject', app_name: APP_NAME), + ) + end + end + end + context 'with in person profile' do let!(:enrollment) do create(:in_person_enrollment, :establishing, user: user, profile: nil) @@ -472,6 +513,17 @@ def show ) end + context 'user was flagged by ThreatMetrix' do + let(:threatmetrix_result) { 'reject' } + + it 'does not send the idv_please_call email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_email_not_delivered( + subject: t('user_mailer.idv_please_call.subject'), + ) + end + end + context 'when there is a 4xx error' do before do stub_request_enroll_bad_request_response @@ -965,6 +1017,27 @@ def show expect(user.reload.gpo_verification_pending_profile).to be_nil end end + + context 'user was flagged by ThreatMetrix' do + let(:threatmetrix_review_status) { 'reject' } + + it 'does not send the idv_please_call email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_email_not_delivered( + subject: t('user_mailer.idv_please_call.subject'), + ) + end + + context 'but ThreatMetrix disabled' do + let(:threatmetrix_enabled) { false } + it 'does not send the idv_please_call email' do + put :create, params: { user: { password: ControllerHelper::VALID_PASSWORD } } + expect_email_not_delivered( + subject: t('user_mailer.idv_please_call.subject'), + ) + end + end + end end context 'user is going through enhanced ipp' do diff --git a/spec/jobs/get_usps_proofing_results_job_spec.rb b/spec/jobs/get_usps_proofing_results_job_spec.rb index 99ff7bfaa0a..5ea9d8b9131 100644 --- a/spec/jobs/get_usps_proofing_results_job_spec.rb +++ b/spec/jobs/get_usps_proofing_results_job_spec.rb @@ -1490,7 +1490,7 @@ allow(analytics).to receive( :idv_in_person_usps_proofing_results_job_please_call_email_initiated, ) - allow(user_mailer).to receive(:in_person_please_call).and_return(mail_deliverer) + allow(user_mailer).to receive(:idv_please_call).and_return(mail_deliverer) subject.perform(current_time) end @@ -1545,7 +1545,7 @@ end it 'sends the please call email' do - expect(user_mailer).to have_received(:in_person_please_call).with( + expect(user_mailer).to have_received(:idv_please_call).with( enrollment: enrollment, visited_location_name: visited_location_name, ) diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 5ac90eb4ebf..c33ece27391 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -814,6 +814,13 @@ def expect_email_body_to_have_help_and_contact_links mail.deliver_later end + + it 'attaches the icon inline' do + icon_part = mail.attachments['phone_icon.png'] + expect(icon_part).not_to be(nil) + expect(icon_part.inline?).to eql(true) + expect(icon_part.url).to start_with('cid:') + end end context 'in person emails' do diff --git a/spec/services/user_alerts/alert_user_about_account_verified_spec.rb b/spec/services/user_alerts/alert_user_about_account_verified_spec.rb index 47dd8f362fa..c956abd7ba1 100644 --- a/spec/services/user_alerts/alert_user_about_account_verified_spec.rb +++ b/spec/services/user_alerts/alert_user_about_account_verified_spec.rb @@ -38,7 +38,9 @@ expect_delivered_email( to: [user.confirmed_email_addresses.first.email], subject: t('user_mailer.account_verified.subject', app_name: APP_NAME), - body: ['