Mail safety: internal-domain exclusion in reactivation + active-dev outreach script - #111
Merged
Merged
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
CHANGE 1 — reactivationEmail.ts internal-domain exclusion: The 2026-07-31 dry-run (Render job job-d9mcdd6gekts7389tcb0) showed eligible=183 with the first 10 recipients ALL internal @archtools.dev aliases. Cloudflare Email Routing for archtools.dev forwards only abuse@/security@/privacy@/support@ and the catch-all is DISABLED, so marketing sends to those aliases hard-bounce at SMTP and damage Resend sender reputation. - New env EXCLUDE_EMAIL_DOMAINS (comma-separated, default archtools.dev); matching recipients are skipped entirely — no email, no top-up (exclusion runs before SEND_LIMIT slicing and top-up selection). - Dry-run now prints a per-domain recipient histogram plus the count excluded as internal; summary JSON gains excludedInternal/excludeDomains. - Copy strings untouched (a parallel PR owns them); existing safety model (CONFIRM_SEND, BUSINESS_ADDRESS, SEND_LIMIT) unchanged. CHANGE 2 — new outreachActiveDevs.ts: Personal-ask email to developers with real API activity in the last 30 days (ApiRequest SUCCESS rows grouped by agentId — funnelReport's stage-2 pattern, time-bounded). Mirrors the reactivation safety model exactly: dry-run by default, CONFIRM_SEND=YES + BUSINESS_ADDRESS gates, SEND_LIMIT, RFC 8058 one-click unsubscribe, live opt-out recheck, emailVerified/emailOptOut filters, EXCLUDE_EMAIL_DOMAINS. Copy claims USDC on Base or Polygon ONLY (the only live chains) — enforced by test. Tests: exclusion-helper cases added to reactivation-render.test.mjs; new outreach-active-devs.test.mjs (render + honest-claims guard); both wired into npm test. Verified: npx tsc --noEmit clean; both test files pass. dist/node_modules churn deliberately not committed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deesmo
force-pushed
the
mail-safety-internal-exclusion
branch
from
July 31, 2026 16:47
64e63a2 to
a1f51a5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The 2026-07-31 reactivation dry-run (Render job
job-d9mcdd6gekts7389tcb0) reported eligible=183 with the first 10 recipients ALL internal @archtools.dev aliases (lucius*/brad*/mc*). Verified live: Cloudflare Email Routing for archtools.dev forwards ONLY abuse@/security@/privacy@/support@ and the catch-all is DISABLED — so marketing sends to those aliases hard-bounce at SMTP and burn Resend sender reputation.Change 1 —
api/src/scripts/reactivationEmail.ts: internal-domain exclusionEXCLUDE_EMAIL_DOMAINS(comma-separated, defaultarchtools.dev; explicit""disables). Matching recipients are skipped entirely — no email, no top-up (exclusion runs beforeSEND_LIMITslicing and top-up selection).gmail.com: 57) and an "Excluded as internal: N" line; the summary JSON gainsexcludedInternal+excludeDomains.CONFIRM_SEND,BUSINESS_ADDRESS,SEND_LIMIT, RFC 8058 headers, live opt-out recheck).Change 2 — new
api/src/scripts/outreachActiveDevs.tsPersonal-ask email to the ~13-15 developers with real API activity in the last 30 days.
ApiRequestrows withstatus="SUCCESS"grouped byagentId(the exact patternfunnelReport.tsuses for its "made ≥1 successful call" stage), bounded toACTIVE_WINDOW_DAYS(default 30, within the 90-day ApiRequest retention window),MIN_CALLSdefault 1. Internal/seed/self accounts are removed by the sameEXCLUDE_EMAIL_DOMAINSfilter (internal traffic = the @archtools.dev aliases; funnelReport has no separate seed flag).CONFIRM_SEND=YES+ realBUSINESS_ADDRESSrequired to send;SEND_LIMIT; RFC 8058 one-click unsubscribe viasignUnsubscribeToken+ List-Unsubscribe headers;sendMarketingEmail;emailVerified/emailOptOutfilters with live opt-out recheck per send;isMainModuleguard.Tests / verification
api/tests/reactivation-render.test.mjs: +5 cases forparseExcludeDomains/emailDomain(default, parsing, explicit-disable, case-insensitivity, internal-alias matching). It renders copy but asserts none of the parallel-PR copy strings changed here.api/tests/outreach-active-devs.test.mjs: CAN-SPAM elements, personal ask, MCP URL, honest-claims guard (Base+Polygon only), personalization, HTML escaping. Wired intonpm test.npx tsc --noEmit→ clean; both test files pass (25 + 17 assertions).api/dist/api/node_modulesdeliberately not committed (build churn reverted).🤖 Generated with Claude Code
Note
Medium Risk
Touches production marketing scripts that query agents, may top up credits, and send bulk email when
CONFIRM_SEND=YES; logic is dry-run by default and adds exclusion rather than widening sends.Overview
Adds internal-domain exclusion to marketing one-off scripts so
@archtools.devaliases (and other configured domains) are never emailed or topped up—addressing dry-run findings that internal addresses would hard-bounce and hurt Resend reputation.reactivationEmail.tsgainsEXCLUDE_EMAIL_DOMAINS(defaultarchtools.dev), shared helpers (parseExcludeDomains,emailDomain, exportedescapeHtml/maskEmail), filtering beforeSEND_LIMITand credit top-ups, plus dry-run per-domain histogram andexcludedInternalin JSON logs.New
outreachActiveDevs.tstargets verified, non–opted-out agents with successful API calls in a configurable window (funnelReport-styleApiRequestgrouping), reuses the same exclusion and CAN-SPAM/send safeguards (dry-run default, live opt-out recheck, List-Unsubscribe). Copy is a short personal ask from Brad; payment claims limited to USDC on Base/Polygon.Tests: domain-exclusion cases in
reactivation-render.test.mjs, newoutreach-active-devs.test.mjs(CAN-SPAM, honest chain claims, HTML escape), wired intonpm test.Reviewed by Cursor Bugbot for commit 64e63a2. Configure here.