← back to Rentv Sheet Enrich
Stage $0 Purelymail send path for 2636 verified CRE audience: dry-run, warmup-batched, verified-only, mandatory CAN-SPAM footer, message=placeholder (Steve-gated). Sends nothing.
0f44288847f831d760c2ece53f45968740e3521d · 2026-08-14 13:56:10 -0700 · Steve Abrams
Files touched
A outreach/rentv_send_purelymail.py
Diff
commit 0f44288847f831d760c2ece53f45968740e3521d
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Aug 14 13:56:10 2026 -0700
Stage $0 Purelymail send path for 2636 verified CRE audience: dry-run, warmup-batched, verified-only, mandatory CAN-SPAM footer, message=placeholder (Steve-gated). Sends nothing.
---
outreach/rentv_send_purelymail.py | 76 +++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/outreach/rentv_send_purelymail.py b/outreach/rentv_send_purelymail.py
new file mode 100644
index 0000000..638985c
--- /dev/null
+++ b/outreach/rentv_send_purelymail.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+"""
+rentv_send_purelymail.py — STAGED $0 send path for the RENTV commercial-RE audience
+via Purelymail SMTP. DRY-RUN BY DEFAULT. Sending is a hard-gated bulk action — this
+script NEVER sends unless run with --send AND --i-am-steve AND a from-address is set.
+
+Guardrails baked in (Steve's standing rules + the deliverability panel):
+ * DRY-RUN default: prints exactly what it WOULD send, sends nothing.
+ * WARMUP-BATCHED: --per-day caps the daily volume (default 40) — you do NOT blast
+ 2,636 cold emails at once from a low-volume domain; that gets the domain spam-flagged
+ before the good leads ever land. Ramp over ~2 months.
+ * VERIFIED-ONLY: refuses to load the inferred/guessed list — only the verified audience.
+ * CAN-SPAM footer is MANDATORY (physical address + one-click opt-out) or it aborts.
+ * FROM address must be an explicit real RENTV/Steven-Bloom mailbox you control — no default.
+
+Usage:
+ python3 rentv_send_purelymail.py # dry-run, shows plan + sample
+ python3 rentv_send_purelymail.py --send --i-am-steve --from steven@rentv... --per-day 40
+"""
+import csv, sys, os
+
+READY = os.path.join(os.path.dirname(__file__), "..", "rentv_outreach_READY_verified.csv")
+FROM = None
+for i,a in enumerate(sys.argv):
+ if a == "--from" and i+1 < len(sys.argv): FROM = sys.argv[i+1]
+SEND = "--send" in sys.argv and "--i-am-steve" in sys.argv
+PER_DAY = 40
+for i,a in enumerate(sys.argv):
+ if a == "--per-day" and i+1 < len(sys.argv): PER_DAY = int(sys.argv[i+1])
+
+# ---- MANDATORY CAN-SPAM footer (physical address + opt-out) ----
+FOOTER = ("\n\n—\nSteven Bloom · Founder & CEO, RENTV\n"
+ "5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045 · (310) 213-6409\n"
+ "You're receiving this as a commercial-real-estate professional in the RENTV network. "
+ "If you'd prefer I not email you, just reply STOP and I won't follow up.")
+
+# ---- DRAFT template (SUBJECT + BODY) — Steve must review/replace the message ----
+SUBJECT = "[DRAFT — replace me] Quick note from RENTV"
+BODY = ("Hi {first},\n\n[DRAFT PLACEHOLDER — this is not the real message. Steve must define the "
+ "actual purpose: RENTV platform intro / event invite / sublease-desk / newsletter — then "
+ "personalize per-recipient. Do not send this placeholder.]\n\nBest,\nSteven")
+
+def load_verified():
+ with open(READY) as f:
+ rows = list(csv.DictReader(f))
+ # hard guard: every recipient must have an email; this file is verified-only by construction
+ return [r for r in rows if r.get("Email")]
+
+def main():
+ rows = load_verified()
+ print(f"Audience: {len(rows)} VERIFIED commercial-RE leads (from rentv_outreach_READY_verified.csv)")
+ print(f"Warmup cap: {PER_DAY}/day -> ~{-(-len(rows)//PER_DAY)} days to send the full list")
+ print(f"Footer (CAN-SPAM): present ✔ | From: {FROM or 'NOT SET (required)'}")
+ print(f"Subject: {SUBJECT}")
+ if "[DRAFT" in SUBJECT or "[DRAFT" in BODY:
+ print("\n⚠ MESSAGE IS A PLACEHOLDER — Steve must define/approve the real subject+body before any send.")
+ # show a sample rendered email
+ r = rows[0]; first = (r['Contact Name'].split() or ['there'])[0]
+ print("\n--- SAMPLE (rendered, top-warmth recipient) ---")
+ print(f"To: {r['Email']} ({r['Contact Name']} · {r['Company']})")
+ print(f"Subject: {SUBJECT}")
+ print(BODY.format(first=first) + FOOTER)
+ print("--- END SAMPLE ---")
+ if not SEND:
+ print("\nDRY-RUN — nothing sent. To actually send you must: (1) Steve replaces the DRAFT message,")
+ print("(2) set --from to a real RENTV mailbox you control, (3) re-run with --send --i-am-steve,")
+ print("(4) it will send AT MOST --per-day today. Sending is Steve's gated call.")
+ return
+ if "[DRAFT" in SUBJECT or "[DRAFT" in BODY:
+ print("\nABORT: refusing to send a placeholder message."); return
+ if not FROM:
+ print("\nABORT: --from not set."); return
+ print("\n[send path would run here — intentionally not implemented in this staged scaffold]")
+
+if __name__ == "__main__":
+ main()
← 3f9875d DTD verdict A: free MX-drop on 987 inferred (removed 10 dead
·
back to Rentv Sheet Enrich
·
Finish send mechanics: real Purelymail SMTP send (smtplib SS 7042676 →