Skip to content

feat: capture email with project recipient suppression rules - #522

Open
raymatos wants to merge 2 commits into
useplunk:nextfrom
raymatos:feat/recipient-suppression
Open

raymatos wants to merge 2 commits into
useplunk:nextfrom
raymatos:feat/recipient-suppression

Conversation

@raymatos

@raymatos raymatos commented Oct 9, 2026

Copy link
Copy Markdown

Description

Add project-scoped recipient suppression rules so test messages retain their rendered content without being delivered externally. Rules support exact addresses, exact domains, literal local-part prefixes/suffixes, and bounded whole-address wildcards (* and ?). Settings provides create/edit/enable/disable controls and a saved-rule address preview.

Matching recipients are captured individually as SUPPRESSED; other recipients in the same request retain normal delivery. Decisions are snapshotted, rechecked by the worker, and remain suppressed across retries or later rule changes. Coverage includes transactional API, SMTP envelope recipients, workflow overrides, campaign delivery, and campaign test sends. Alternate recipient headers cannot introduce extra provider recipients.

Captured messages appear once in Activity with a Suppressed filter, rendered preview, and matched-rule details. Project-authorized capture endpoints and two read-only MCP tools expose stored content and existing stored attachments. Captures are excluded from delivery/reputation metrics and billing usage; normal project protections remain in force.

This is related to #258, but deliberately does not implement its automatic SES bounce/complaint list population, CSV import, or reason taxonomy. It adds manually managed capture rules rather than replacing existing bounce/complaint handling.

Migration and compatibility

Adds a rule table, nullable capture fields, an index, and the SUPPRESSED email status. Apply the migration and regenerate the Prisma client for API/worker deployments. Older clients that do not recognize the new enum cannot safely read captured rows; rollback requires a compatible client. Rendered bodies follow existing body retention. Arbitrary regular expressions are not supported.

Type of Change

  • feat: New feature (MINOR version bump)

Testing

Validation completed on this PR head (a36d0da):

  • API test suite: 1,364 tests passed across 55 files on the final full run. An earlier run hit an unchanged campaign pagination test's timestamp-tie flake; the unchanged full rerun passed.
  • Workspace lint: all 6 tasks passed, with existing warnings; API and dashboard type checks passed.
  • API/dashboard builds and self-hosted image build completed.
  • Automated coverage includes matching/invalid patterns, disabled rules, project authorization/isolation, mixed recipients with stubbed SES, rendered content and stored attachments, retry/concurrent-worker suppression, workflow overrides, campaign previews, recipient-header filtering, reputation exclusion, and capture/Activity pagination.
  • Browser checks covered rule creation/editing, invalid patterns, disabled rules, project switching, repeated actions, Activity filtering/pagination, and rendered previews.
  • Isolated API/SMTP fixtures used provider stubs. Suppressed-recipient tests assert zero provider calls. Self-hosted capture checks confirmed stored rendered content and no recorded SES message IDs or delivery timestamps. No real-recipient test sends were used for these checks.

Checklist

  • PR title follows conventional commits format
  • API/dashboard and deployment image build successfully
  • Tests pass locally
  • Documentation updated

Related Issues

Related to #258

@raymatos
raymatos marked this pull request as ready for review October 9, 2026 01:14
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