Skip to content

Conversation

@YashK2005
Copy link
Collaborator

@YashK2005 YashK2005 commented Dec 19, 2025

TLDR: Added the remaining email templates + the translations for the french versions. All of the emails are now sent at the right places EXCEPT we need to finish the flow for when a volunteer accepts a time proposed by the participant and send an email to the volunteer and to the participant here. Each email template is 200+ lines of html which is why its so long :(

Screenshot 2025-12-19 at 4 44 06 PM

Summary

This PR implements a complete bilingual email system with automated sending at key points in the user workflow. The system supports both English and French, with automatic language detection from user preferences and timezone-aware scheduling notifications.

Changes

1. Bilingual Email Template System (Commit 1)

Template Infrastructure:

  • Reorganized email templates into structured folders: base/, source/, compiled/, text/
  • Created Jinja2-based template system with base templates for EN and FR
  • Added custom PreservingUndefined class to preserve {{}} syntax for AWS SES variable replacement
  • Updated update_ses_templates.py to compile .j2 source files to HTML

Email Templates (7 types × 2 languages = 14 templates):

  • Email verification (EN/FR)
  • Password reset (EN/FR)
  • Intake form confirmation (EN/FR)
  • Matches available (EN/FR)
  • Call scheduled (EN/FR)
  • Participant requested new times (EN/FR)
  • Volunteer accepted new times (EN/FR)

Email Service Updates:

  • Updated SESEmailService to support language parameter for all email methods
  • Added separate source email addresses for EN ([email protected]) and FR ([email protected])
  • Implemented dynamic subject lines and personalized greetings

2. Automated Email Sending (Commit 2)

Email Triggers Implemented:

  1. Intake Form Confirmation (intake.py:273-286)

    • Sent immediately after intake form submission
  2. Password Reset (auth_service.py:50-102)

    • Enhanced with language detection from user database
    • Retrieves user's first name from DB with Firebase fallback
  3. Matches Available - Volunteer (match_service.py:99-121)

    • Sent when admin creates new matches
  4. Matches Available - Participant (match_service.py:556-575)

    • Sent when volunteer accepts match and sends availability
  5. Call Scheduled - Both Users (match_service.py:284-356)

    • Sent to both participant and volunteer after call is scheduled
    • Timezone conversion: Each user receives time in their own timezone (EST, PST, etc.)
    • Uses get_timezone_from_abbreviation() utility to convert Canadian timezone abbreviations
  6. Participant Requested New Times (match_service.py:417-444)

    • Sent to volunteer when participant requests alternative meeting times

Technical Implementation:

  • Language detection: Retrieves user's language from database (Language enum: "en" or "fr"), defaults to English
  • Timezone handling: Converts UTC times to user's local timezone using stored timezone abbreviations (NST, AST, EST, CST, MST, PST)
  • Error handling: All email sends wrapped in try/except to log errors without failing main operations
  • Package structure: Added missing __init__.py files to app/utilities/ and app/utilities/ses/ for proper IDE import resolution

Testing Considerations

  • All emails default to English if user language is not set
  • Timezone defaults to EST (America/Toronto) if user timezone is not set
  • Email send failures are logged but don't interrupt workflow (form submissions, match creation, scheduling)
  • URLs currently hardcoded to http://localhost:3000 (production URLs to be configured via environment variables later)

Future Work

  • Implement "Volunteer accepted new times" email (endpoint doesn't exist yet)
  • Replace hardcoded URLs with FRONTEND_URL environment variable for production deployment
  • Consider retry mechanism for failed email sends

Notion ticket link

Ticket Name

Implementation description

Steps to test

What should reviewers focus on?

Checklist

  • My PR name is descriptive and in imperative tense
  • My commit messages are descriptive and in imperative tense. My commits are atomic and trivial commits are squashed or fixup'd into non-trivial commits
  • I have run the appropriate linter(s)
  • I have requested a review from the PL, as well as other devs who have background knowledge on this PR or who will be building on top of this PR

YashK2005 and others added 2 commits December 19, 2025 00:45
- Reorganized email templates into structured folders (base/, source/, compiled/, text/)
- Created Jinja2-based template system with base templates for EN and FR
- Implemented 7 email types in both English and French (14 total):
  * Email verification
  * Password reset
  * Intake form confirmation
  * Matches available
  * Call scheduled
  * Participant requested new times (volunteer-only)
  * Volunteer accepted new times (participant-only)
- Added dynamic parameters to email subjects and bodies
- Updated SES email service to support language parameter for all email methods
- Updated auth service to retrieve user's first name from database (with Firebase fallback) for personalized password reset emails
- Created custom Jinja2 PreservingUndefined class to preserve {{}} syntax for AWS SES variable replacement
- Updated update_ses_templates.py script to compile .j2 source files to HTML
- Fixed logo URLs to use PNG format for Gmail compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Add intake form confirmation email on form submission
- Add password reset email with language detection from user DB
- Send matches available email to volunteer when admin creates match
- Send matches available email to participant when volunteer sends availability
- Send call scheduled email to both users with timezone conversion
- Send participant requested new times email to volunteer
- Add missing __init__.py files for proper package structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@YashK2005 YashK2005 marked this pull request as ready for review December 19, 2025 21:47
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +108 to +110
first_name = volunteer.first_name if volunteer.first_name else None
matches_url = "http://localhost:3000/volunteer/dashboard"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Externalize dashboard URLs in match notifications

The match-creation notification email embeds a hardcoded http://localhost:3000/volunteer/dashboard link (and the later scheduled-call/match-acceptance emails in this file use the same localhost base). In any deployed environment these emails will direct volunteers/participants to a non-existent local server, so recipients cannot navigate from the email. Pull the frontend base URL from configuration instead of baking in localhost.

Useful? React with 👍 / 👎.

@YashK2005 YashK2005 merged commit d80d9a1 into main Dec 19, 2025
5 checks passed
@YashK2005 YashK2005 deleted the yash/email-templates-bilingual branch December 19, 2025 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant