Unsubscribes and suppression
Extrovert adds unsubscribe headers to eligible outbound mail and checks recipient suppression before a
message enters review or is delivered. Do not add your own List-Unsubscribe or
List-Unsubscribe-Post headers. Extrovert removes those custom values and writes the managed
headers.
Automatic unsubscribe headers
Section titled “Automatic unsubscribe headers”| Message | Headers |
|---|---|
One To recipient with no cc or bcc | List-Unsubscribe with a recipient-bound token. List-Unsubscribe-Post is added only when one-click advertising is enabled. |
Several recipients across to, cc, or bcc | List-Unsubscribe with a preferences link. A one-click token is not used because it cannot identify which recipient clicked. |
The link resolves through the configured Extrovert API base URL. Its token is stateless and encrypted. No suppression row is written until the recipient acts.
One-click advertising is off by default
Section titled “One-click advertising is off by default”RFC 8058 requires the unsubscribe headers to be covered by a valid DKIM signature. The current delivery path does not sign that header set, so Extrovert does not advertise one-click support by default. The HTTPS unsubscribe link remains available. Deployments that sign the required headers can enable the implemented POST path.
Where an opt-out applies
Section titled “Where an opt-out applies”An opt-out applies to the recipient across the organization by default. It does not affect another tenant.
Two platform protections can broaden enforcement:
- Mail from a shared sending domain can suppress the recipient across tenants that use that domain.
- Opt-outs from three or more distinct organizations within 90 days can create a platform-wide backstop.
Only authenticated recipient actions count toward broader enforcement. Cross-tenant and platform rows are not exposed through an organization’s API.
The recipient_suppressed error
Section titled “The recipient_suppressed error”If any recipient is suppressed, the whole send fails:
{ "type": "https://extrovert.dev/problems/recipient_suppressed", "title": "Recipient Suppressed", "status": 422, "detail": "one or more recipients have opted out", "code": "recipient_suppressed", "request_id": "req_8Tz4kP", "errors": [ { "field": "recipient", "code": "recipient_suppressed", "detail": "alice@example.com" } ]}Extrovert does not silently remove one address from a multi-recipient message. The errors array
identifies the blocked address so the caller can decide whether to create a different message.
Suppression is checked at submission and again at delivery. A blocked message never enters the human
review queue, and a new suppression can stop a message that is already waiting for approval.
Suppression is checked before the intent requirement, so the response is
422 recipient_suppressed, not 422 intent_required.
The error does not reveal whether the matching row belongs to the organization, a shared domain, or the platform backstop.
Check, list, and revoke
Section titled “Check, list, and revoke”The agent-plane suppression endpoints require read permission:
GET /v1/suppressions?recipient=<address>checks the organization’s visible suppression rows for an address.GET /v1/suppressionslists visible rows and acceptsrecipient,scope, andinclude_revokedfilters.POST /v1/suppressions/{id}/revokerevokes an organization-owned row. A reason is required.
The scope query value and row field are stable wire names. Public instructions describe where a row
applies.
Global and shared-domain rows can be changed only by a platform operator. The console provides the same organization-owned list, search, export, and reasoned revocation controls.
Opt-outs in replies
Section titled “Opt-outs in replies”Extrovert checks the new, unquoted text of incoming replies conservatively:
- A clear reply such as “stop,” “unsubscribe,” “remove me,” or “opt out” records an organization suppression.
- A phrase inside a longer, qualified request records a review flag instead of making the choice automatically.
- A phrase found only in quoted text does nothing.
Every accepted opt-out produces the same unsubscribe.received event, audit row, and configured
webhook regardless of whether it came from a link, mailto:, preference page, or reply.