Repository navigation
Conversation
Gmail and Yahoo require bulk senders to support one-click unsubscribe. - Campaign emails (and campaign test sends) carry List-Unsubscribe pointing at the unsubscribe link, plus List-Unsubscribe-Post: List-Unsubscribe=One-Click when that link is HTTPS. Every adapter sets them in its provider's format. - POST to the unsubscribe link unsubscribes straight away, recorded like the existing form (Manual by Subscriber). The route skips CSRF verification on Laravel 12 (VerifyCsrfToken) and 13 (PreventRequestForgery). - SES sends move to the SESv2 SendEmail operation, which can set headers and needs the same ses:SendEmail permission. The quota check stays on v1. - MailAdapterInterface::send() takes an optional $headers argument (breaking for custom adapters). - Test sends use a well-formed placeholder hash, so their links 404 instead of erroring on Postgres. Amp-Thread-ID: https://ampcode.com/threads/T-01a14f00-30c9-7739-a0b3-15e53b5f9917
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gmail and Yahoo require bulk senders to support RFC 8058 one-click unsubscribe. SendPortal set no
List-Unsubscribeheader, and unsubscribing took two steps (GET page, then a PUT form).What changes
List-Unsubscribe: <https://…/subscriptions/unsubscribe/{hash}>, plusList-Unsubscribe-Post: List-Unsubscribe=One-Clickwhen that link is HTTPS (RFC 8058 doesn't allow one-click over plain HTTP, soAPP_URLmust behttps://). All 7 adapters set them in their provider's format: SESContent.Simple.Headers, PostmarkHeaders, SendGridheaders, Mailgunh:fields, MailjetHeaders, Postalheaders, SMTP MIME headers. Automation emails use the same dispatch path and get them too.POST subscriptions/unsubscribe/{messageHash}(the same URL as the page) unsubscribes straight away, using the same code as the existing form (MANUAL_BY_SUBSCRIBER). GET still only shows the page, so link scanners can't unsubscribe anyone. The route skips CSRF verification. Excluding the base class also covers its subclasses:VerifyCsrfTokenon Laravel 12,PreventRequestForgeryon Laravel 13.SendEmailoperation. The v1 operation can't set custom headers. v2 needs the sameses:SendEmailIAM permission, and AWS recommends it for one-click. The quota check stays on v1.abc123to an all-zero UUID becauseabc123made the unsubscribe and webview pages return 500 on Postgres, wherehashis auuidcolumn.Breaking:
MailAdapterInterface::send()takes a newarray $headers = []argument, so custom adapters must add it. This is noted in the CHANGELOG.Testing
tests/Unit/Adapters/ListUnsubscribeHeadersTest.phpchecks the request each adapter actually sends: HTTP bodies via mocked HTTP clients, the SendGrid payload, and the raw MIME message for SMTP. All 7 tests fail without the adapter changes.tests/Feature/Subscriptions/OneClickUnsubscribeTest.phpdispatches a real campaign message and POSTs to the URL from its header. It also covers HTTP URLs, test sends, and a POST with the CSRF check switched on. It fails if the CSRF exclusion or the header pass-through is removed.sp:campaigns:dispatchand a queue worker, comparing the base commit with this branch on MySQL and Postgres. The providers were fakes answering on their real hostnames, and SMTP went to Mailpit.List-Unsubscribe=One-ClickPOST went from 405 to 200, and the subscriber was unsubscribed.Existing issues noticed, not changed here
ThrottlesSendingcomparesSesException::getMessage()with'Maximum sending rate exceeded.', but the SDK wraps that text in a longer message, so the retry never fires. The SDK's own retries still handle throttling.SmtpAdapterleaves the DSN scheme empty unless encryption istls. An SMTP service saved without encryption fails withThe "" scheme is not supported.https://ampcode.com/threads/T-01a14f00-30c9-7739-a0b3-15e53b5f9917