fizzy icon indicating copy to clipboard operation
fizzy copied to clipboard

Mark users as "verified" and only send notifications to verified users

Open flavorjones opened this issue 3 weeks ago • 1 comments

Motivation

Today, spammers can add users to an account by consuming join codes; and those users will receive notification emails even if they never log in to confirm their identity. This enables spam delivery via notification emails, which we need to prevent.

Details

Add a verified_at timestamp to users that is set when they reedem a join link, by inserting a verification step into two flows:

  1. if they are already logged in with the identity that matches the email provided during join link redemption:
    • redeem a join link → verify → user join form
  2. otherwise:
    • redeem a join link → submit a valid magic link code → verify → user join form

The "verify" step above is implemented with a new controller, Users::VerificationsController.

The JoinCodesController will redirect the user to new_users_verification_url either directly or via session[:return_to_after_authenticating] and the Sesssions::MagicLinkController. The VerificationsController uses an auto-submit form so that a redirect can be converted into a POST action and write to the database.

Two notes:

  • Account owners are auto-verified on creation.
  • Backfilling "verified" status is nontrivial. A backfill script marks existing users as verified based on evidence of real activity (created cards, comments, reactions, etc.).

Finally, Fizzy will only send notification emails to users who have verified their email address.

Rollout

Ideally this would get rolled out in three steps:

  1. roll out the database migrations and code to set verified_at
  2. run the backfill script
  3. roll out enforcement of verification when emailing notifications

but we could do it all at once if we're careful not to overlap the process with invocation of the recurring job deliver_bundled_notifications.

flavorjones avatar Dec 05 '25 19:12 flavorjones

@jz the user profile will look like this if a user is unverified (which for a real human should only look like this during the magic link email turnaround time):

screenshot-2025-12-05_12-25-01

flavorjones avatar Dec 05 '25 19:12 flavorjones

Looks good in staging.

flavorjones avatar Dec 06 '25 03:12 flavorjones