[object Object]

← back to Rentv

Content Studio: Email-to-Boom now creates a Gmail DRAFT in steve-office (no send-gate; Steve reviews + sends)

b1efd88a05ac01132333b641bfc995ac766a96ac · 2026-08-05 11:34:15 -0700 · steve

Files touched

Diff

commit b1efd88a05ac01132333b641bfc995ac766a96ac
Author: steve <steve@designerwallcoverings.com>
Date:   Wed Aug 5 11:34:15 2026 -0700

    Content Studio: Email-to-Boom now creates a Gmail DRAFT in steve-office (no send-gate; Steve reviews + sends)
---
 public/admin/pr-intelligence/content-studio.html |  8 ++++----
 server.js                                        | 10 ++++++----
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/public/admin/pr-intelligence/content-studio.html b/public/admin/pr-intelligence/content-studio.html
index a1f4b90d..2998b090 100644
--- a/public/admin/pr-intelligence/content-studio.html
+++ b/public/admin/pr-intelligence/content-studio.html
@@ -146,7 +146,7 @@
       <div class="cs-field"><label>Body <a class="cs-copy" data-copy="b_body">📋 copy</a></label><textarea id="b_body" class="cs-body"></textarea></div>
       <div class="cs-row">
         <button class="btn" id="publish">🚀 Publish to blog</button>
-        <button class="btn" id="emailboom">📧 Email to Boom</button>
+        <button class="btn" id="emailboom">📧 Draft to Boom (steve-office)</button>
         <span class="cs-meta" id="pubmeta"></span>
       </div>
     </div>
@@ -273,7 +273,7 @@
   // ── Email the full assembled post to Boom ──────────────────────────────────
   $('emailboom').addEventListener('click', () => PR.guard(async () => {
     if (!$('b_title').value.trim()) { PR.toast('Generate a post first', true); return; }
-    if (!confirm('Email this full post to Boom (sbloom@rentv.com)?')) return;
+    if (!confirm('Create a Gmail draft to Boom (sbloom@rentv.com) in steve-office? You review + send it from Gmail.')) return;
     $('emailboom').disabled = true;
     try {
       const r = await PR.api('/../content/email', { method: 'POST', body: {
@@ -281,8 +281,8 @@
         photo_credit: $('b_credit').value.trim(), videos: $('b_videos').value, body: $('b_body').value,
         linkedin: $('s_li').value, x: $('s_x').value,
       } });
-      $('pubmeta').innerHTML = `<span class="cs-ok">✅ Emailed to ${PR.esc(r.to)}</span>`;
-      PR.toast('Emailed to Boom');
+      $('pubmeta').innerHTML = `<span class="cs-ok">✅ Draft created in steve-office → ${PR.esc(r.to)}</span> — review + send from Gmail.`;
+      PR.toast('Draft created in steve-office');
     } finally { $('emailboom').disabled = false; }
   }, null));
 
diff --git a/server.js b/server.js
index 3f90f565..fe435185 100644
--- a/server.js
+++ b/server.js
@@ -529,14 +529,16 @@ app.post('/api/content/email', adminOnly, async (req, res) => {
     + (b.linkedin ? `<hr><h3>LinkedIn</h3><p>${clean(b.linkedin, 3000)}</p>` : '')
     + (b.x ? `<h3>X</h3><p>${clean(b.x, 600)}</p>` : '');
   try {
-    const r = await fetch(GEORGE_URL + '/api/send', {
-      method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: GEORGE_HDR, ...(GEORGE_SEND_APPROVAL ? { 'X-Send-Approval': GEORGE_SEND_APPROVAL } : {}) },
+    // Create a Gmail DRAFT in steve-office (Steve reviews + sends it himself). A draft is NOT a
+    // send, so it never trips George's external-send anti-exfil gate — only Basic auth is needed.
+    const r = await fetch(GEORGE_URL + '/api/drafts', {
+      method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: GEORGE_HDR },
       body: JSON.stringify({ account: 'steve-office', to: BOOM_EMAIL, subject: 'RENTV draft: ' + title, body: html }),
       signal: AbortSignal.timeout(25000),
     });
     const j = await r.json().catch(() => ({}));
-    if (j.success) return res.json({ ok: true, to: BOOM_EMAIL });
-    return res.status(502).json({ ok: false, error: (j.error || 'send failed'), to: BOOM_EMAIL });
+    if (j.success) return res.json({ ok: true, drafted: true, to: BOOM_EMAIL, draftId: j.draftId });
+    return res.status(502).json({ ok: false, error: (j.error || 'draft failed'), to: BOOM_EMAIL });
   } catch (e) { return res.status(502).json({ ok: false, error: String(e.message || e).slice(0, 160) }); }
 });
 

← 6d2fbcd3 Deal Desk: viewer for an uncovered closed CRE deal — chat-ad  ·  back to Rentv  ·  George draft auth: try Basic <GEORGE_AUTH> (secrets-master v c5edf510 →