Skip to content

Story #2282: Implements Mailman mailing list subscription#2444

Open
herzog0 wants to merge 4 commits into
developfrom
teo/2282-mailing-list
Open

Story #2282: Implements Mailman mailing list subscription#2444
herzog0 wants to merge 4 commits into
developfrom
teo/2282-mailing-list

Conversation

@herzog0
Copy link
Copy Markdown
Collaborator

@herzog0 herzog0 commented May 15, 2026

Issue: #2282

Summary & Context

Implements the mailing list subscribe/unsubscribe flow backed by the Mailman REST API. Users (authenticated or anonymous) can subscribe to Boost mailing lists via a V3 card component; subscription state is tracked in Django and confirmed via a signed email link before Mailman is called.

Changes

  • Mailman API client (mailing_list/client.py) - thin wrapper around the Mailman REST API exposing subscribe, unsubscribe, is_confirmed, and _discard_pending; all pre_* flags are set to True because Django owns the confirmation step
  • UserMailingListSubscription model + migration - new model tracking per-user subscription state (pending / active) keyed on (user, list_id) with a corresponding migration
  • Three new views (mailing_list/views.py):
    • QuickSubscribeView - HTMX-driven single-list subscribe for both authenticated and anonymous users; re-renders the card partial in-place
    • SubscribeView - multi-list subscribe/unsubscribe for authenticated users (used in the demo page; will be reused for the profile modal)
    • ConfirmSubscriptionView - handles the signed confirmation link, calls Mailman, and upgrades the DB record to active; renders success/invalid pages
  • MailingListCardMixin (mailing_list/mixins.py) - injects card context into any CBV; wired into CommunityView and available for future pages
  • V3 templates - updated _mailing_list_card.html with state-aware rendering (default / pending / active / error) and HTMX swap; new confirm_success.html, confirm_invalid.html, _subscribe_result.html, _subscribe_success_card.html, and plain-text confirmation email template
  • V3 CSS - new mailing-list-card.css (spinner, badge, form loading states) and mailing-list-confirm.css (full-page success/error confirmation layout)
  • Docker + env - mailman-core and mailman-web services enabled in docker-compose.yml; MAILMAN_REST_API_URL, MAILMAN_DEV_API_URL, and MAILMAN_LISTS added to env.template
  • Dev helper script (scripts/dev-mailman-helpers) - shell script for seeding local Mailman lists and inspecting subscription state during development

Risks & Considerations

  • The confirmation token uses django.core.signing with a 7-day TTL and a fixed salt embedded in the source. The salt is not a secret (signing is not encryption), but rotating it invalidates all outstanding tokens.
  • QuickSubscribeView is stateless for anonymous users - there is no server-side record until confirmation. If the email is already subscribed, a live Mailman API check is made; if the API is unreachable the duplicate-check is skipped silently and Mailman will return 409 on confirm (handled as a no-op).
  • SubscribeView is currently only wired to the demo page - it will need to be adapted when the multi-selection profile modal is built.
  • mailman-core and mailman-web Docker services now start by default. Teams that don't need Mailman locally can comment them out or use docker compose up web db redis.

Screenshots

image image image image

Peer-review testing steps

  1. Copy env.template values for MAILMAN_REST_API_URL, MAILMAN_DEV_API_URL, and MAILMAN_LISTS into your .env
  2. docker compose up - verify mailman-core starts on port 8001
  3. Run scripts/dev-mailman-helpers to seed the three Boost lists in the local Mailman instance (choose create lists)
  4. Open your Maildev inbox at http://localhost:1080/#/
  5. Log out
  6. Visit /community/ and test the mailing list card as an anonymous user - enter an email and verify a confirmation email is sent to maildev
  7. Copy and paste the confirmation link in another tab - verify the success page shows the correct list name
  8. Go back to the community page, refresh it. You'll notice the card goes back to the default state, because we aren't storing any information about the subscription state for logged out users
  9. Try entering the same email, you should get an error message in the card
  10. Now log in
  11. Navigate to http://localhost:8000/v3/demo/components/#mailing-list-subscribe-live
  12. Write down the same email and uncheck all the boxes. Hit save. This will unsubscribe you from the list (you can fully test subscriptions in multiple lists in this component btw)
  13. Go back to the community page and repeat steps 6 and 7 (while logged in this time)
  14. Right after submitting the form in step 6 you should see the card transition to "pending" state
  15. Copy and paste the confirmation link in another tab - verify the success page shows the correct list name
  16. Go back to the community page, refresh it. You'll notice the card now transitions to the "subscribed" state

Self-review Checklist

  • Tag at least one team member from each team to review this PR
  • Link this PR to the related GitHub Project ticket

Frontend

  • UI implementation matches Figma design
  • Tested in light and dark mode
  • Responsive / mobile verified
  • Accessibility checked (keyboard navigation, etc.)
  • Ensure design tokens are used for colors, spacing, typography, etc. – No hardcoded values
  • Test without JavaScript (if applicable)
  • No console errors or warnings

@herzog0 herzog0 requested review from jlchilders11 and julhoang May 18, 2026 15:26
@herzog0 herzog0 marked this pull request as ready for review May 18, 2026 15:27
@herzog0 herzog0 linked an issue May 18, 2026 that may be closed by this pull request
@herzog0 herzog0 force-pushed the teo/2282-mailing-list branch from 8e50367 to 1a44f32 Compare May 20, 2026 20:28
herzog0 added 4 commits May 20, 2026 20:47
feat: add Mailman REST API client and config settings

feat: add UserMailingListSubscription model

feat: add mailing list subscribe/unsubscribe view and route

feat: add subscribe result HTMX fragment and styles

chore: add mailing list subscribe demo to component demo view
chore: add mailman-members dev helper script

fix: mailing list name

chore: rename script

feat: improve test script

fix: hostname

feat: wire up mailing list card
feat: show success susbcribe card

chore: request email verification

feat: discard pending subscriptions when user unsub before verification

feat: add email field to subscription model

feat: add status field to subscription model

feat: add pending logs to demo component

feat: improve dev mm script

feat: add boost owned email validation flow

feat: Allow anonymous subscriptions and enhance pending state UI

fix: csrf token injection

fix: styles

chore: improve subscription confirmation pages styles

feat: improve subscription confirmation styles

fix: centralize _CONFIRM_MAX_AGE value

feat: improve email templates

fix: font size

fix: change doc

chore: remove unused login url

chore: add dev note to mailing list example card
@herzog0 herzog0 force-pushed the teo/2282-mailing-list branch from 1a44f32 to 18ed3a0 Compare May 20, 2026 23:47
@herzog0 herzog0 requested review from julioest and ycanales May 21, 2026 00:05
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.

[Backend Integration] Mailing List Auto Subscription

1 participant