MemberJunction / MemberJunction/MJ

Communication: no unsubscribe/suppression capability anywhere in the framework

Open
#2,820 0 comments 0 reactions 1 assignee Claimed by @SDesai-BC View on GitHub
enhancement
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
1d 8h
Merged PRs (30d)
308

Description

## What's missing

The Communication subsystem has zero unsubscribe/suppression support — no suppression entity, no pre-send check, no way to emit a `List-Unsubscribe` header, and the SendGrid provider *actively disables* SendGrid's hosted subscription-tracking footer (the one zero-effort unsubscribe mechanism). Recipients have no way to get onto a suppression list through anything MJ sends.

Nuance for accuracy: SendGrid's *account-level* suppression lists (bounces, spam reports, prior global unsubscribes) still apply server-side regardless. The hole is the consumer-facing half: no opt-out affordance in the messages, and no framework-level suppression honored at send time.

This is a CAN-SPAM/GDPR posture issue for every MJ consumer that sends anything marketing-shaped. (Found while building CDP's voice-invite emails, where batch/CSV sending makes volume one click away.)

## Proposed shape

Two parts, both framework-level:

1. **`List-Unsubscribe` / `List-Unsubscribe-Post` support** — falls out of Headers passthrough in MemberJunction/MJ#2817 (headers must pass verbatim, not `X-` prefixed).
2. **A suppression entity + engine check** — e.g. `Communication Suppressions` keyed by recipient address + channel (+ optional scope), consulted in the send path before dispatch; suppressed recipients reported per-row as `Suppressed` (needs the result-code field from MemberJunction/MJ#2818) rather than silently dropped or thrown. Plus a documented way for an unsubscribe landing endpoint to write suppression rows.

## Acceptance criteria

- [ ] A new suppression entity exists with CodeGen artifacts and a documented write path
- [ ] Engine consults suppressions pre-dispatch; suppressed rows return a distinct per-row result, batch continues
- [ ] Callers can emit a working `List-Unsubscribe` header through the engine
- [ ] Suppression check failures fail safe (configurable: block-on-unknown vs send-on-unknown) and are logged

## Blocked by

- MemberJunction/MJ#2817 (Headers passthrough for the header half)
- MemberJunction/MJ#2818 (result code for per-row Suppressed reporting)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.