Skip to content

feat: feed url update email dispatch#1776

Open
Alessandro100 wants to merge 9 commits into
mainfrom
feat/1751-feed-url-update-email-dispatch
Open

feat: feed url update email dispatch#1776
Alessandro100 wants to merge 9 commits into
mainfrom
feat/1751-feed-url-update-email-dispatch

Conversation

@Alessandro100

@Alessandro100 Alessandro100 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary:

closes #1751

Implements email templates for the following notification events

  • producer url change
  • producer url redirect
  • notification admin summary (bonus)

Expected behavior:

When a producer url changes or redirects it should send an email to the users who are subscribed

Testing tips:

[Internal team]
For integrated tests, use DEV environment. As the notification endpoints are not implemented, notification-related entities need to be created via SQL.

  • Subscribe a user to a notification by inserting a row in notification_subscription table; replace with the target user id(REPLACE_ME_WITH_USER_ID)
 INSERT INTO notification_subscription (id, user_id, notification_type_id, cadence, digest, active, active_since)
 VALUES (gen_random_uuid()::text, REPLACE_ME_WITH_USER_ID, 'feed.url_updated',
'weekly', false, true, now() - interval '1 day');
  • Simulate a notification_event:
WITH ev AS ( INSERT INTO notification_event (id, notification_type_id, event_subtype, source, payload, created_at) VALUES (gen_random_uuid()::text, 'feed.url_updated', 'url_replaced', 'manual_test',
  '{"old_url":"https://old/feed.zip","new_url":"https://new/feed.zip"}'::jsonb, now()) RETURNING id)
 INSERT INTO notification_event_feed (id, notification_event_id, feed_stable_id, role)
 SELECT gen_random_uuid()::text, ev.id, 'mdb-10', 'subject' FROM ev;
  • Call the notifications_dispatch_plan task from retool(DEV)
  • Verify that the user receives a the appropriate email template

Notes

  • The manage notifications goes to account/notification (good)
  • The unsubscribe action in the footer needs to be revisited once the mechanisms and page is implemented

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Run the unit tests with ./scripts/api-tests.sh to make sure you didn't break anything
  • Add or update any needed documentation to the repo
  • Format the title like "feat: [new feature short description]". Title must follow the Conventional Commit Specification(https://www.conventionalcommits.org/en/v1.0.0/).
  • Linked all relevant issues
  • Include screenshot(s) showing how this pull request works and fixes the issue(s)
Screenshot 2026-07-24 at 09 53 48 Screenshot 2026-07-24 at 09 53 31

(bonus)
Screenshot 2026-07-24 at 08 46 08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements HTML email templates and fallback rendering for notification dispatch (notably feed.url_updated and an admin dispatch summary), and ensures Cloud Function builds include the new template assets.

Changes:

  • Added a shared Jinja2-based email layout (_base_email.html.j2) and new templates for feed URL updates (single + digest) and admin dispatch summaries.
  • Updated brevo_notification_sender to render HTML fallbacks via Jinja2 templates (instead of inline string concatenation) and to enrich event row context (feed page URLs, providers, etc.).
  • Updated Cloud Function build/deps to include .j2 templates in the build artifact and add Jinja2 to tasks_executor requirements.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/function-python-build.sh Includes .j2 template files when assembling function build artifacts.
functions-python/tasks_executor/requirements.txt Adds Jinja2 dependency needed for template rendering in notification dispatch.
api/tests/unittest/test_brevo_notification_sender.py Adds/updates unit tests for template loading and Jinja2 autoescape behavior.
api/src/shared/notifications/templates/feed_url_updated_single.html.j2 New single-event feed URL update email template (extends shared base).
api/src/shared/notifications/templates/feed_url_updated_digest.html.j2 New digest feed URL update email template (extends shared base).
api/src/shared/notifications/templates/change_tracker_email.html.j2 Refactors existing GTFS diff template to extend the shared base layout.
api/src/shared/notifications/templates/admin_event_summary.html.j2 New admin dispatch summary email template (extends shared base).
api/src/shared/notifications/templates/_base_email.html.j2 New shared base layout for notification emails (header/footer/styles/blocks).
api/src/shared/notifications/brevo_notification_sender.py Introduces Jinja2 environment, safe-link/thousands filters, and template-based HTML fallbacks.
Comments suppressed due to low confidence (1)

api/src/shared/notifications/templates/change_tracker_email.html.j2:103

  • In Jinja2, {% extends %} must appear before any executable template statements (macros, blocks, etc.). This template defines macros earlier in the file before the extends tag, which can raise a TemplateAssertionError or prevent inheritance from working. Move the extends tag to the top (after the initial {# ... #} comment block) and keep macro definitions after it (or extract macros into an imported template).

Comment thread api/src/shared/notifications/brevo_notification_sender.py
Comment on lines 370 to 372
if events[0].notification_type_id == NotificationTypeId.ADMIN_EVENT_SUMMARY:
# One run summary per event (most digests contain a single summary).
return "".join(build_admin_summary_html(e) for e in events)
@emmambd

emmambd commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

@Alessandro100 The feed ID won't be meaningful to users who subscribe. We should include the old producer URL, the new producer URL, and the transit provider name so users can understand the change.

We also talked about prompting users to subscribe to the new feed.

@Alessandro100

Copy link
Copy Markdown
Contributor Author

@emmambd I agree that adding the transit provider name would be more meaningful than just the stable id, but in the notification event we currently do not expose the transit provider name, that would be a larger change

For prompting the user, was the vision

  1. email button "Subscribe to new feed" -> go to mobilitydatabase feed page -> click subscribe button -> subscribe
  2. email button "Subscribe to new feed" -> go to mobilitydatabase feed page -> auto subscribes

For option 1, it's already in place
For option 2, I would need to do some work
Regardless I can change the text from "View new feed" to "Subscribe to new feed"

@emmambd

emmambd commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

@Alessandro100 Option 1 works here for sure.

In regards to not exposing the transit provider name, I think that's a larger change we have to do, otherwise the email notification will not be meaningful and users will be confused.

I can open a new issue for it - I assume it goes back to the backend logic in #1723? cc @davidgamez

@Alessandro100

Copy link
Copy Markdown
Contributor Author

@emmambd provider name was added

@emmambd

emmambd commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

@Alessandro100 Amazing! I'd use the transit provider name in the Subject Line and remove the id from the table column

@Alessandro100

Copy link
Copy Markdown
Contributor Author

@emmambd done
Screenshot 2026-07-24 at 11 07 31
image

@Alessandro100
Alessandro100 force-pushed the feat/1751-feed-url-update-email-dispatch branch from 8e26ba2 to 99f812f Compare July 24, 2026 15:15
@emmambd

emmambd commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

@Alessandro100 This is great! Thanks for these changes.

Maybe a broader comment: If the email will show as from Mobility Database, do we need [Mobility Database] in the subject line?

@Alessandro100

Copy link
Copy Markdown
Contributor Author

@emmambd Good point, the email sender will aways be MobilityData which gives context to the user to what this is

@@ -0,0 +1,295 @@
<!doctype html>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👍

@davidgamez davidgamez left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM(technical)

@emmambd

emmambd commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

LGTM to me now as well

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.

[notifications] Email template and dispatch integration — feed.url_updated

4 participants