{"id":"69ee9eb0a9e1ef7e28f472eb","title":"2026 04 27","path":"how-to/committee/release-notes/2026-04-27","contentMarkdown":"# 27-Apr-2026 — Unsubscribes and blocked contacts [#18](https://github.com/nbarrett/ngx-ramblers/issues/18)\n## [run 624](https://github.com/nbarrett/ngx-ramblers/actions/runs/24969398442) — [commit 78478d7](https://github.com/nbarrett/ngx-ramblers/commit/78478d767f84746f2a075221d7a37dec78b7ab29)\n\n_____\n\n## What's new\n\n- **Mail Settings → Unsubscribes** lists everyone Brevo is not sending to: people who unsubscribed, admin blocks, hard bounces and spam flags.\n- That state is copied onto the matching member record, so Member Admin, re-imports and auto-subscribe all honour the latest opt-out.\n- The unsubscribe link in outgoing mail opens the group's own branded page, not Brevo's form. Recipients can optionally say why.\n\n\n## Two views\n\nOpen [Mail Settings → Unsubscribes](https://ngx-ramblers.org.uk/admin/mail-settings?tab=unsubscribes \"{{siteUrl}}\").\n\nThe toggle at the top right switches between:\n\n- **Unsubscribes**: someone left a specific mailing list, with the list name and any reason they gave.\n- **Blocks**: account-wide hard bounces, spam flags, admin blocks, and contacts who used the old global unsubscribe page.\n\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/ff557f7d-abd0-4aae-853a-7b5dd71df085.png)\n\n*Unsubscribes tab: member-level events, with reason badges and the originating list*\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/626857e4-32f9-4efd-bd18-a3f557aff765.png)\n\n*Blocks tab: hard bounces, spam flags and admin blocks*\n\nEach row shows the contact email (click to open in Brevo), sender, reason, matched member, lists, and date.\n\nSearch, reason, sender and the date-range slider filter the list. <strong>Clear filters</strong> resets them. The current filters sit in the URL, so you can share a view.\n\nOn a Blocks row, the bin icon removes that contact from Brevo's blocks after a confirm. It does not re-subscribe them: use the member's <strong>Brevo</strong> tab if they should receive mail again. <strong>Options → Clear all blocks</strong> is for staging and recovery. It does not delete members.\n\nOpening the page, and the two-hourly sync, write the same state onto the member: a warning on their <strong>Brevo</strong> tab, an audit row, and local subscriptions flipped to unsubscribed for the lists involved. Member Admin has a <strong>Blocked from receiving email</strong> filter.\n\n## What recipients see\n\nClicking unsubscribe in an email takes them to the group's own `/unsubscribe` page. The unsubscribe completes on load, for that list only. The reason form is optional. Gmail and Apple Mail one-click unsubscribe hits the same endpoint.\n\nHard bounces, spam and complaints still block the whole address.\n\n\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/9e3bda91-70cf-4f8a-8122-fcd5fe575fb1.png)\n\n## Keeping it in step\n\n- A job runs every two hours.\n- A Brevo webhook updates us as events happen.\n- If someone is no longer blocked in Brevo, the next full sync clears the local flag.\n- Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.\n- A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.\n\n## Also in this release\n\n- Admin tables use the lighter layout and collapse to cards on a phone.\n- Upload History filters sit on one line.\n- Member Raw Data JSON is hidden behind an eye toggle.\n- After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.\n\n\n\n\n\n## Keeping it in step\n\n- A job runs every two hours.\n- A Brevo webhook updates us as events happen.\n- If someone is no longer blocked in Brevo, the next full sync clears the local flag.\n- Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.\n- A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.\n\n## Also in this release\n\n- Admin tables use the lighter layout and collapse to cards on a phone.\n- Upload History filters sit on one line.\n- Member Raw Data JSON is hidden behind an eye toggle.\n- After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.\n\n\n\n\n\n## Keeping it in step\n\n- A job runs every two hours.\n- A Brevo webhook updates us as events happen.\n- If someone is no longer blocked in Brevo, the next full sync clears the local flag.\n- Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.\n- A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.\n\n## Also in this release\n\n- Admin tables use the lighter layout and collapse to cards on a phone.\n- Upload History filters sit on one line.\n- Member Raw Data JSON is hidden behind an eye toggle.\n- After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.\n\n\n\n\n\n## Keeping it in step\n\n- A job runs every two hours.\n- A Brevo webhook updates us as events happen.\n- If someone is no longer blocked in Brevo, the next full sync clears the local flag.\n- Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.\n- A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.\n\n## Also in this release\n\n- Admin tables use the lighter layout and collapse to cards on a phone.\n- Upload History filters sit on one line.\n- Member Raw Data JSON is hidden behind an eye toggle.\n- After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.\n\n","contentHtml":"<h1>27-Apr-2026 — Unsubscribes and blocked contacts <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/18\">#18</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/24969398442\">run 624</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/78478d767f84746f2a075221d7a37dec78b7ab29\">commit 78478d7</a></h2>\n<hr>\n<h2>What&#39;s new</h2>\n<ul>\n<li><strong>Mail Settings → Unsubscribes</strong> lists everyone Brevo is not sending to: people who unsubscribed, admin blocks, hard bounces and spam flags.</li>\n<li>That state is copied onto the matching member record, so Member Admin, re-imports and auto-subscribe all honour the latest opt-out.</li>\n<li>The unsubscribe link in outgoing mail opens the group&#39;s own branded page, not Brevo&#39;s form. Recipients can optionally say why.</li>\n</ul>\n<h2>Two views</h2>\n<p>Open <a href=\"https://ngx-ramblers.org.uk/admin/mail-settings?tab=unsubscribes\" title=\"{{siteUrl}}\">Mail Settings → Unsubscribes</a>.</p>\n<p>The toggle at the top right switches between:</p>\n<ul>\n<li><strong>Unsubscribes</strong>: someone left a specific mailing list, with the list name and any reason they gave.</li>\n<li><strong>Blocks</strong>: account-wide hard bounces, spam flags, admin blocks, and contacts who used the old global unsubscribe page.</li>\n</ul>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/ff557f7d-abd0-4aae-853a-7b5dd71df085.png\" alt=\"\"></p>\n<p><em>Unsubscribes tab: member-level events, with reason badges and the originating list</em></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/626857e4-32f9-4efd-bd18-a3f557aff765.png\" alt=\"\"></p>\n<p><em>Blocks tab: hard bounces, spam flags and admin blocks</em></p>\n<p>Each row shows the contact email (click to open in Brevo), sender, reason, matched member, lists, and date.</p>\n<p>Search, reason, sender and the date-range slider filter the list. <strong>Clear filters</strong> resets them. The current filters sit in the URL, so you can share a view.</p>\n<p>On a Blocks row, the bin icon removes that contact from Brevo&#39;s blocks after a confirm. It does not re-subscribe them: use the member&#39;s <strong>Brevo</strong> tab if they should receive mail again. <strong>Options → Clear all blocks</strong> is for staging and recovery. It does not delete members.</p>\n<p>Opening the page, and the two-hourly sync, write the same state onto the member: a warning on their <strong>Brevo</strong> tab, an audit row, and local subscriptions flipped to unsubscribed for the lists involved. Member Admin has a <strong>Blocked from receiving email</strong> filter.</p>\n<h2>What recipients see</h2>\n<p>Clicking unsubscribe in an email takes them to the group&#39;s own <code>/unsubscribe</code> page. The unsubscribe completes on load, for that list only. The reason form is optional. Gmail and Apple Mail one-click unsubscribe hits the same endpoint.</p>\n<p>Hard bounces, spam and complaints still block the whole address.</p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/9e3bda91-70cf-4f8a-8122-fcd5fe575fb1.png\" alt=\"\"></p>\n<h2>Keeping it in step</h2>\n<ul>\n<li>A job runs every two hours.</li>\n<li>A Brevo webhook updates us as events happen.</li>\n<li>If someone is no longer blocked in Brevo, the next full sync clears the local flag.</li>\n<li>Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.</li>\n<li>A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.</li>\n</ul>\n<h2>Also in this release</h2>\n<ul>\n<li>Admin tables use the lighter layout and collapse to cards on a phone.</li>\n<li>Upload History filters sit on one line.</li>\n<li>Member Raw Data JSON is hidden behind an eye toggle.</li>\n<li>After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.</li>\n</ul>\n<h2>Keeping it in step</h2>\n<ul>\n<li>A job runs every two hours.</li>\n<li>A Brevo webhook updates us as events happen.</li>\n<li>If someone is no longer blocked in Brevo, the next full sync clears the local flag.</li>\n<li>Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.</li>\n<li>A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.</li>\n</ul>\n<h2>Also in this release</h2>\n<ul>\n<li>Admin tables use the lighter layout and collapse to cards on a phone.</li>\n<li>Upload History filters sit on one line.</li>\n<li>Member Raw Data JSON is hidden behind an eye toggle.</li>\n<li>After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.</li>\n</ul>\n<h2>Keeping it in step</h2>\n<ul>\n<li>A job runs every two hours.</li>\n<li>A Brevo webhook updates us as events happen.</li>\n<li>If someone is no longer blocked in Brevo, the next full sync clears the local flag.</li>\n<li>Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.</li>\n<li>A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.</li>\n</ul>\n<h2>Also in this release</h2>\n<ul>\n<li>Admin tables use the lighter layout and collapse to cards on a phone.</li>\n<li>Upload History filters sit on one line.</li>\n<li>Member Raw Data JSON is hidden behind an eye toggle.</li>\n<li>After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.</li>\n</ul>\n<h2>Keeping it in step</h2>\n<ul>\n<li>A job runs every two hours.</li>\n<li>A Brevo webhook updates us as events happen.</li>\n<li>If someone is no longer blocked in Brevo, the next full sync clears the local flag.</li>\n<li>Re-importing the Head office CSV still updates the member, but will not auto-subscribe anyone who is blocked locally, even if the consent column says yes.</li>\n<li>A fresh bulk import now creates the Brevo contact and puts them on the configured lists in one step.</li>\n</ul>\n<h2>Also in this release</h2>\n<ul>\n<li>Admin tables use the lighter layout and collapse to cards on a phone.</li>\n<li>Upload History filters sit on one line.</li>\n<li>Member Raw Data JSON is hidden behind an eye toggle.</li>\n<li>After a deploy, the site no longer serves a stale page that fails to load until a hard refresh.</li>\n</ul>\n"}