Skip to content

feat(mail): add email notification preferences with global opt-out#550

Merged
tompscanlan merged 6 commits intomainfrom
feat/notification-preferences
Mar 5, 2026
Merged

feat(mail): add email notification preferences with global opt-out#550
tompscanlan merged 6 commits intomainfrom
feat/notification-preferences

Conversation

@tompscanlan
Copy link
Copy Markdown
Contributor

Summary

  • Add notifications.email boolean to user preferences JSONB column (opt-out model, default true)
  • Check preference before sending all non-transactional emails (event announcements, group notifications, admin messages, contact notifications)
  • Migrate 3 legacy HBS auth templates (activation, reset-password, confirm-new-email) to MJML+EJS
  • Delete default.hbs layout with broken /unsubscribe link
  • Fix misleading "opted to receive" email footer copy with factual text
  • Add "manage email settings" link to all notification email footers

Companion PR: OpenMeet-Team/openmeet-platform (feat/notification-preferences)
Closes: om-x5pt

Test plan

  • Unit tests for preference check in event announcement service (6 tests)
  • Unit tests for preference check in group/event mail services (8+ tests)
  • Unit tests for MJML template migration in mail.service and mailer.service
  • All 1898 unit tests passing
  • E2E: toggle preference off, trigger event announcement, verify no email in MailDev
  • E2E: toggle preference on, trigger event announcement, verify email arrives
  • Manual: verify new MJML auth emails render correctly in MailDev

@tompscanlan tompscanlan force-pushed the feat/notification-preferences branch from dfea0ef to 2fc39c6 Compare March 3, 2026 22:18
…ggle

- Add notifications.email to user preferences JSONB column
- Check preference before sending all non-transactional emails
  (event announcements, group notifications, admin messages, contact notifications)
- Migrate 3 legacy HBS auth templates to MJML (activation, reset-password, confirm-new-email)
- Delete default.hbs layout with broken /unsubscribe link
- Fix misleading "opted to receive" footer copy with factual text
- Add "manage email settings" link to all notification email footers
- Add preferences field to TypeORM select clauses for mail query methods
- Fix pre-existing bug: return→continue in group admin notification loop

Closes: om-x5pt
sendMjmlMail requires subject: string but i18n returns MaybeType<string>.
Add fallback strings for activation, reset-password, and confirm-new-email.
The html-to-text library wraps URLs in brackets: `Text [URL]`. The old
regex (\S+) captured the closing bracket, corrupting the JWT hash.
Changed to ([^\s\]]+) to exclude brackets.
… handlers

EventAnnouncementService used @Inject(REQUEST) making it request-scoped,
but its @onevent handlers fire asynchronously after the HTTP request scope
is destroyed. This caused handlers to silently fail in CI.

Apply the same ModuleRef + ContextIdFactory pattern from CalendarInviteListener
(commit fdf34f8) to dynamically resolve tenant context per handler invocation.
Also update event.deleted emitter to include tenantId.
…ement

The MJML template referenced `eventName` but the service passes
`eventTitle` in the context, causing a ReferenceError that silently
prevented update announcement emails from being sent.
@tompscanlan tompscanlan force-pushed the feat/notification-preferences branch from 49bb43a to f25885c Compare March 5, 2026 13:53
No production callers found via LSP incomingCalls — only the test referenced it.
@tompscanlan tompscanlan merged commit 426fb19 into main Mar 5, 2026
4 checks passed
tompscanlan added a commit that referenced this pull request Mar 5, 2026
CalendarInviteListener was the only email path missing the
preferences.notifications.email check added in PR #550. Users who
opted out of email notifications were still receiving calendar invite
emails when RSVPing to events.
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