Skip to content

feat: add email campaign send pipeline (text + HTML)#362

Open
williamchiii wants to merge 22 commits into
devfrom
wchi/email_campaigns
Open

feat: add email campaign send pipeline (text + HTML)#362
williamchiii wants to merge 22 commits into
devfrom
wchi/email_campaigns

Conversation

@williamchiii

Copy link
Copy Markdown
Collaborator

Description

Final piece of the email campaigns feature: actually sending them. The CRUD
groundwork (migration, model, queries, repo, service, HTTP handlers, tests) landed
in earlier PRs (#350#358); this PR wires saved campaigns through to delivery so
admins can send to user groups without the tech team running scripts.

  • Resolve applicant recipient groups (accepted/rejected/waitlisted) to deduped
    contact emails (new SQL query + repo method)
  • Add raw-HTML task type + QueueSendRawHtmlEmail (campaign bodies are inline HTML,
    not file templates)
  • Add text/raw-HTML execute methods + worker handlers, and register all three task
    types
    in the email_worker mux (the existing textemail:send had no consumer)
  • SendCampaign service: guards sendable status, resolves + dedupes recipients,
    enqueues one email per recipient by format, drives status
    draft/scheduled → sending → sent/failed
  • Admin-gated POST /email/campaigns/{campaignId}/send endpoint; send-state errors
    mapped to 400

Type of Change

  • New feature (non-breaking change)

Checklist

  • My code follows the project's style guidelines
  • I have commented on complex parts of the code
  • I have updated documentation if necessary
  • I have updated or added tests to cover my changes
  • I have updated the OpenAPI YAML or other API schema files if applicable

Additional Notes

  • OpenAPI is generated by huma from the route definitions, so the new
    send-email-campaign operation is documented automatically.
  • No new migration — the email_campaigns schema shipped in Adds the sqlc query layer for email campaigns #350-Adds unit tests for the email campaign service’s validation and lifecycle rules. #358.
  • Tests: existing email-domain tests still pass; a dedicated SendCampaign test
    (mocking EmailService) is not yet added — follow-up.
  • Known limitations: only applicant groups resolve today (admins/staff/
    visitors/interest_subscribers return an "unsupported recipient type" error —
    admins is the planned next follow-up); "sent" means queued, not delivered;
    no partial-send rollback. Still to come: email_consent filtering, scheduled sends,
    delete endpoint, delivery/read stats.
  • Manual test: make backend, create a draft campaign targeting accepted_applicants,
    POST .../send, watch asynqmon + worker logs, confirm the row flips to sent.

williamchiii and others added 22 commits April 4, 2026 17:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…eries

Agent-Logs-Url: https://github.com/swamphacks/core/sessions/1e2e08e9-0737-47dd-8a01-bddead1ad570

Co-authored-by: williamchiii <188648862+williamchiii@users.noreply.github.com>
…tory

Agent-Logs-Url: https://github.com/swamphacks/core/sessions/5c4475ce-1d02-429a-80bf-15b48fefcd07

Co-authored-by: williamchiii <188648862+williamchiii@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Admins can now send saved campaigns to applicant groups via SES.

- Resolve recipient groups to deduped contact emails (accepted/rejected/waitlisted)
- Add raw-HTML task + queue method; send one email per recipient by format
- Add text/raw-HTML worker handlers and register all task types in the worker mux
- SendCampaign service: status transitions draft -> sending -> sent/failed
- Add admin-gated POST /email/campaigns/{id}/send endpoint with OpenAPI docs
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
core Ready Ready Preview, Comment Jun 30, 2026 9:41pm
xii-front-page Ready Ready Preview, Comment Jun 30, 2026 9:41pm

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.

2 participants