Follow-up on the #411 header work (commit 8f23d8a) — reading the code, not something we've wired up yet, so apologies if I've misread.
The one-click List-Unsubscribe pair is gated on bodyHasListManagementLink, which only matches Plunk's own /unsubscribe/{id} | /manage/{id}. So a HEADLESS sender who ships their own opt-out URL gets the bulk trio (via isCampaign) but never the List-Unsubscribe pair — and the emitted value is hardcoded to DASHBOARD_URI regardless. That inverts what HEADLESS is for: bring-your-own list management gets you every header except the one that matters for one-click. Campaigns can't work around it either — no headers field like /v1/send has.
The part that seems off: you already ship detectUnsubscribeSignal (matches {{unsubscribeUrl}}/{{manageUrl}}, unsubscribe-keyword hrefs, anchor text) to tell HEADLESS authors they have an opt-out. But header emission uses the stricter bodyHasListManagementLink. So a template can pass the author-facing "you have an unsubscribe mechanism" check and still emit no List-Unsubscribe header — the two functions disagree on what counts as list management.
Would a per-send/per-campaign listUnsubscribe (https one-click + optional mailto:) that emits the pair pointing at the sender's own endpoint, independent of class and body detection, be in scope? Failing that, having the header path honor the same signal detectUnsubscribeSignal already recognizes would close most of the gap.
Follow-up on the #411 header work (commit
8f23d8a) — reading the code, not something we've wired up yet, so apologies if I've misread.The one-click
List-Unsubscribepair is gated onbodyHasListManagementLink, which only matches Plunk's own/unsubscribe/{id}|/manage/{id}. So aHEADLESSsender who ships their own opt-out URL gets the bulk trio (viaisCampaign) but never theList-Unsubscribepair — and the emitted value is hardcoded toDASHBOARD_URIregardless. That inverts whatHEADLESSis for: bring-your-own list management gets you every header except the one that matters for one-click. Campaigns can't work around it either — noheadersfield like/v1/sendhas.The part that seems off: you already ship
detectUnsubscribeSignal(matches{{unsubscribeUrl}}/{{manageUrl}}, unsubscribe-keyword hrefs, anchor text) to tellHEADLESSauthors they have an opt-out. But header emission uses the stricterbodyHasListManagementLink. So a template can pass the author-facing "you have an unsubscribe mechanism" check and still emit noList-Unsubscribeheader — the two functions disagree on what counts as list management.Would a per-send/per-campaign
listUnsubscribe(https one-click + optionalmailto:) that emits the pair pointing at the sender's own endpoint, independent of class and body detection, be in scope? Failing that, having the header path honor the same signaldetectUnsubscribeSignalalready recognizes would close most of the gap.