Default-deny outbound mail and a sign-up gate

This is a test area on a testnet contract, but it was seeded on 15 Sep with a copy of
InstantAdPay's live member list and it carried a working SendGrid key. On 18 Sep the
coach's stall nudges fired on schedule and emailed 95 real people from it. One of them
clicked through and opened a fresh account two hours later.

Nothing was misconfigured. Every send site checked mailer.hasKey(), the key was there,
so every send site got a yes. The default was wrong, not the plumbing.

OUTBOUND=on is now required before anything can leave: hasKey() is false without it,
send() rejects outright, and the two mailing loops (coach nudges, lead drip) never start.
SIGNUPS=closed shuts the three registration doors and reports signupsOpen:false, which
also drops the email-code card from the UI. Members already here keep their dashboards.

A missing env var means silence now, not delivery.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-19 04:29:08 -05:00
parent 00ab223ce6
commit 0374b04f0d
2 changed files with 28 additions and 7 deletions
+6 -1
View File
@@ -13,9 +13,14 @@ function key() {
if (process.env.SENDGRID_KEY) return process.env.SENDGRID_KEY.trim();
try { return fs.readFileSync(path.join(DATA_DIR, 'sendgrid.key'), 'utf8').trim(); } catch (e) { return ''; }
}
function hasKey() { return !!key(); }
// A deployment must opt IN to sending mail. Default-deny, on purpose: on 2026-09-18 this
// test area mailed 95 real people because a seeded member list and a live key were both
// present and every send site dutifully checked hasKey() and got a yes.
const OUTBOUND = process.env.OUTBOUND === 'on';
function hasKey() { return OUTBOUND && !!key(); }
function send(to, subject, text) {
if (!OUTBOUND) return Promise.reject(new Error('outbound mail is off on this deployment (set OUTBOUND=on to allow it)'));
return new Promise((resolve, reject) => {
const body = JSON.stringify({
personalizations: [{ to: [{ email: to }] }],