LG-9564: Notify users when verify by mail codes expire 📣 #9475
LG-9564: Notify users when verify by mail codes expire 📣 #9475
Conversation
Since we've moved away from deactivation_reason, _any_ value there should be disqualifying
We look at codes in a sliding 48 hr window in which all codes are _definitely_ expired.
…ers by email when their verify by mail code has expired
Use the date the code was requested, not just the date the user's profile went GPO pending (since they could request a second code).
| end | ||
|
|
||
| def send_email_to_all_addresses(user_mailer_template) | ||
| def send_email_to_all_addresses(user_mailer_template, **args) |
There was a problem hiding this comment.
Minor change here to support forwarding args to UserMailer
| add_column :usps_confirmation_codes, :expiration_notice_sent_at, :datetime, precision: nil | ||
| add_index :usps_confirmation_codes, :expiration_notice_sent_at, algorithm: :concurrently |
There was a problem hiding this comment.
Migration to add an indexed column to usps_confirmation_codes to track the date/time we sent an expiration notice for a single code.
And name the methods like the thing they are doing!
Co-authored-by: Zach Margolis <zachmargolis@users.noreply.github.com>
soniaconnolly
left a comment
There was a problem hiding this comment.
Lots of positive comments, couple minor suggestions. Will run it locally according to your detailed test plan, and approve if all goes well.
| codes_to_send_notifications_for.find_each do |code| | ||
| user = code.profile.user | ||
|
|
||
| user.send_email_to_all_addresses(:gpo_code_expired, code_sent_at: code.code_sent_at) |
There was a problem hiding this comment.
As I commented on the ticket, we are assuming here that the config value max_mail_events_window_in_days, currently set to 30, will always be less than the code expiration, currently set to 31. I still think that we should check that assumption somewhere so we're not accidentally sending users emails inviting them to restart IdV if they're rate limited in the future when someone changes the config value.
There was a problem hiding this comment.
You might want to merge in main to sync up schemas. When I did a make update on this branch it left me with an edited schema.rb that looked like it deleted the index you had added. 🤷
Followed your test plan, and everything went as expected except that when I clicked on the email link to Verify my Identity, it took me to the Enter Code page. Even when I signed out and back in. Maybe because my user's gpo_verification_pending_at was not updated to match the edits to the GpoConfirmationCodes. Not sure if there's anything that needs to change for that.
Checked the email in all three languages, looks good.
Want to run this manually initially for testing purposes.
In case the configs covering expiration and rate limiting are not in sync
|
Closing this for now, as there has been a little scope creep. I'm going to follow up with smaller PRs. |
🎫 Ticket
LG-9564
🛠 Summary of changes
This PR adds a new cron job,
SendGpoCodeExpirationNoticesJob, that sends emails to users who have requested a Verify by mail code but never entered it within the 30 day validity window.Ultimately, this job will run daily, but for now we're not enabling it so we can run it more intentionally at first.
There is a lot to consider when picking users to email! We don’t email anyone who:
✨ Date math ✨
The ticket says:
Confirmation codes expire 30 days after the
code_sent_attimestamp onGpoConfirmationCode.When this job runs, it will look for any confirmation codes eligible for notification within a small window of about 31 days ago. This is to:
To determine the window, we first take the timestamp when the job is running and remove the time component (in prod this will be midnight UTC, but your time zone may vary). Call this
T.The upper bound of the window (the highest value for
code_sent_atfor which we will consider sending a notification) isT - 30 days.The lower bound of the window (the lowest value for
code_sent_atfor which we will consider sending a notification) isT - 32 days.That is, the window is 48 hours, running from midnight UTC - midnight UTC.
The job is meant to run daily, meaning that there will likely be overlap of these windows on subsequent days. But since we update the
expiration_notice_sent_atafter sending, we can filter out codes for which we've sent notifications and avoid sending duplicate notifications.📜 Testing Plan
SendGpoCodeExpirationNoticesJob.new.performSendGpoCodeExpirationNoticesJob.new.performSendGpoCodeExpirationNoticesJob.new.perform(There are a number of edge cases that I tried to capture in the spec file as well.)
If you have not yet received your GFE time machine
It's not ideal, but you can simulate the required increase in entropy if you must. First you should probably tweak your application.yml to make your life easier:
Then, in the Rails console:
👀 Screenshots
English
French
Spanish