[object Object]

← back to Commercialrealestate

CRCP email-alerts: George Basic Auth header + don't advance state on send failure (news-loss guard)

7d99a283394cf31318caf0bf1f1dda093d3125a7 · 2026-07-12 11:17:51 -0700 · Steve

Files touched

Diff

commit 7d99a283394cf31318caf0bf1f1dda093d3125a7
Author: Steve <steve@designerwallcoverings.com>
Date:   Sun Jul 12 11:17:51 2026 -0700

    CRCP email-alerts: George Basic Auth header + don't advance state on send failure (news-loss guard)
---
 scripts/email-alerts.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/scripts/email-alerts.js b/scripts/email-alerts.js
index 5a3257c..1716b81 100644
--- a/scripts/email-alerts.js
+++ b/scripts/email-alerts.js
@@ -171,9 +171,10 @@ function georgeSend({ to, subject, html, from }) {
     const payload = JSON.stringify({ to, subject, body: html, from, account: 'steve-office' });
     const u = new URL(base + '/api/send');
     const lib = u.protocol === 'https:' ? https : http;
+    const basic = Buffer.from(process.env.GEORGE_BASIC_AUTH || 'admin:').toString('base64');
     const req = lib.request(u, { method: 'POST', headers: {
       'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload),
-      'X-Send-Approval': token,
+      'X-Send-Approval': token, 'Authorization': 'Basic ' + basic,
     } }, r => { let s = ''; r.on('data', d => s += d); r.on('end', () => (r.statusCode < 300 ? resolve(s) : reject(new Error(`George ${r.statusCode}: ${s.slice(0,200)}`)))); });
     req.on('error', reject); req.write(payload); req.end();
   });
@@ -197,6 +198,7 @@ function georgeSend({ to, subject, html, from }) {
 
   const date = new Date().toISOString().slice(0, 10);
   const results = [];
+  let sendFailures = 0;
   for (const sub of cfg.subscribers) {
     const { html, listingCount, brokerCount } = buildDigestHTML(sub, newListings, newBrokers);
     if (!listingCount && !brokerCount) { console.log(`  ${sub.email}: nothing new — skip`); continue; }
@@ -208,11 +210,15 @@ function georgeSend({ to, subject, html, from }) {
 
     if (SEND) {
       try { await georgeSend({ to: sub.email, subject, html, from: cfg.from }); console.log(`    ✉ sent via George`); }
-      catch (e) { console.error(`    ⚠ send failed: ${e.message}`); }
+      catch (e) { sendFailures++; console.error(`    ⚠ send failed: ${e.message}`); }
     }
   }
 
-  if (COMMIT_STATE) {
+  // In SEND mode, only advance state if every send succeeded — otherwise the news
+  // would be silently consumed and lost on the next run. Baseline seed always advances.
+  const advance = COMMIT_STATE && !(SEND && sendFailures > 0);
+  if (SEND && sendFailures > 0) console.error(`⚠ ${sendFailures} send failure(s) — state NOT advanced; news preserved for retry.`);
+  if (advance) {
     state.seen.listings = listings.map(l => l.id);
     state.seen.brokers = brokers.map(b => b.id);
     state.last_run = new Date().toISOString();

← 035640a CRCP email-alerts: fix George send (/api/send + body field)  ·  back to Commercialrealestate  ·  auto-save: 2026-07-12T11:17:54 (2 files) — data/alerts-state c102c07 →