Repository navigation
Newsletter sign-up in the footer (double opt-in, topics) - #51
Merged
Merged
Conversation
The structured data keeps info@stabrise.com: it describes StabRise as the operator and has to match what pdf-redaction.com publishes.
…ooter A footer form takes an email and any of three topics. The list lives in a new `apps/newsletter/` app; sending the actual updates is not built yet. - Double opt-in: `POST /newsletter/subscriptions` stores the address as `pending` and mails a confirmation link (7 days). Only the click, on `/newsletter/confirm`, makes it `active` and sends a welcome email with an unsubscribe link and a `List-Unsubscribe` header. - Subscribing answers 204 whatever the address's state, so the form cannot reveal who is on the list. An active address keeps its topics until its owner confirms new ones: the topics ride in the token, not the row. - Confirm and unsubscribe links are `django.core.signing` tokens, so nothing secret is stored. Email tasks take the row and topics, never a link, because django-q keeps task arguments in the database. - Both landing pages act on a button, never on load, since mail scanners open links before people do. - `NEWSLETTER_SUBSCRIBE_RATE` (10/hour per IP) limits sign-ups; staff see the list and its consent trail in the admin. - `send_templated_email` takes optional headers. The footer's top row is now two columns so the form sits beside the links. - DEVELOPMENT.md and CLAUDE.md describe the flow.
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.
Readers can now subscribe from the footer to any of three topics: Reviews, New tools and Benchmarks. Addresses are stored in a new
apps/newsletter/app. Sending the actual updates is not built yet; this adds the list, the consent trail and the unsubscribe path.Flow
POST /api/v1/newsletter/subscriptions. The address is stored aspendingand gets a confirmation link, valid for 7 days./newsletter/confirmhas a Confirm button that calls/confirmations. The row becomesactiveand a welcome email goes out with an unsubscribe link and aList-Unsubscribeheader./newsletter/unsubscribehas an Unsubscribe button that calls/unsubscriptions. The row becomesunsubscribed.Notes for review
django.core.signingtokens, so nothing secret is stored. RotatingSECRET_KEYinvalidates every outstanding link.NEWSLETTER_SUBSCRIBE_RATE(default 10/hour per IP) limits sign-ups.send_templated_emailgains an optionalheaders=argument.info@redaction-tools.com. The JSON-LD operator entity keepsinfo@stabrise.comso it still matches pdf-redaction.com.Testing
make backend-test: 744 passed.make frontend-test: 927 passed.make lintis clean.backend/tests/test_newsletter.py(15 tests); frontend tests for the form and both landing pages.unsubscribedwith both timestamps set.