Monorepo for Aesthetic.Computer aesthetic.computer
core plans EMAIL-BLAST-GIVE-AC.md
5.8 kB

Email Blast Tool: give.aesthetic.computer #

Created: January 5, 2026 Updated: March 30, 2026 Status: Prepared, verified, and intentionally on hold Goal: Warmly email recent AC users about what feels alive in AC this year and invite support via give.aesthetic.computer


Quick Start #

cd /workspaces/aesthetic-computer

# 1. Preview the email
node artery/email-blast.mjs --preview

# 2. Test with your own email
node artery/email-blast.mjs --test me@jas.life

# 3. Use the current 60-day audience snapshot in reports/mail/
#    or re-fetch if you want a newer audience export
node artery/email-blast.mjs --fetch-all

# 4. Hold here unless Jeffrey explicitly wants to send
node artery/email-blast.mjs --send

# 5. Resume next day (Gmail caps at ~500/day)
node artery/email-blast.mjs --send --resume

Current recommendation:

  • Do not send the blast yet.
  • Use --preview and --test me@jas.life only until the audience and tone feel final.

March 30, 2026 Status #

Audience Snapshot #

  • 183 verified users logged in within the last 60 days
  • 182 emailable after unsubscribe filtering
  • 139 have AC handles
  • 99 logged in within the last 30 days
  • 31 logged in within the last 7 days

Private working files were exported locally to reports/mail/ and should stay out of git.

Copy Status #

  • The blast copy is no longer an emergency ask.
  • Current subject: a little note from aesthetic computer
  • Current body: a softer note about what feels alive in AC this year so far, with links to:
    • https://give.aesthetic.computer
    • https://bills.aesthetic.computer
  • Current stats referenced in the copy came from the live metrics snapshot on March 30, 2026 around 04:20 UTC:
    • 4448 paintings
    • 17145 KidLisp programs
    • 18723 chat messages
    • 252 published pages

Verification Status #

  • Lith unsubscribe POST handling was fixed after the migration.
  • application/x-www-form-urlencoded requests now survive the lith adapter correctly.
  • artery/email-blast.mjs now loads the unsubscribe secret from Mongo if the env var is absent, matching the live unsubscribe endpoint.
  • Verified locally and on production:
    • valid unsubscribe GET returns 200
    • unsubscribe POST returns 200 and inserts the Mongo unsubscribe record
    • resubscribe POST returns 200 and removes the record
    • invalid tokens return 403

Test Sends #

  • Test sends were sent to me@jas.life only while validating the unsubscribe flow and updated copy.
  • No audience send has happened.

Next Move #

  • Keep the blast paused.
  • If Jeffrey wants to proceed later, start with the 99 users active within the last 30 days, not the full 182.

Architecture #

Credentials #

  • SMTP: Gmail via mail@aesthetic.computer (in at/.env)
  • Auth0 M2M: For listing all users (in at/.env)
  • UNSUBSCRIBE_SECRET: HMAC secret for unsubscribe tokens (in at/.env + Netlify)

Data Sources (MongoDB) #

  • @handles — users who have claimed a handle
  • email-blast-unsubscribes — users who unsubscribed via email link
  • chat-*-mutes — muted users (also excluded)

Unsubscribe System #

Each email contains a personalized unsubscribe link using HMAC tokens:

https://aesthetic.computer/api/unsubscribe?email=X&token=HMAC

Flow:

  1. User clicks link → GET shows confirmation page
  2. User clicks "Unsubscribe" button → POST records in MongoDB
  3. Next blast run → checks email-blast-unsubscribes and skips those emails
  4. Users can also resubscribe from the same page

Files:

  • system/netlify/functions/unsubscribe.mjs — Netlify endpoint
  • Token generated via HMAC-SHA256 of email + UNSUBSCRIBE_SECRET
  • Emails also include List-Unsubscribe header (Gmail native unsub button)

Commands #

Command Description
--fetch Fetch users (page-based, max 1k)
--fetch-all Bulk export ALL users (16k+)
--list Show cached users
--export Export to CSV
--preview Preview email content
--test EMAIL Send test email
--send Send to VERIFIED users only (default)
--send --all Send to ALL users
--send --resume Resume interrupted send
--clear Clear cached data

Rate Limits #

  • Gmail SMTP: ~500 emails/day
  • Verified users (~5.3k): ~11 days to complete
  • All users (~18k): ~36 days to complete
  • Tool auto-pauses at 400 emails and supports --resume

February 2026 Updates #

March 2026 Updates #


File Map #

File Purpose
artery/email-blast.mjs Main blast tool
lith/server.mjs Lith request adapter fix for urlencoded unsubscribe POSTs
system/netlify/functions/unsubscribe.mjs Unsubscribe/resubscribe endpoint
system/netlify.toml Function config + routing
system/public/give.aesthetic.computer/ Give donation page
reports/email-blast-give-ac-status-2026-02.md Status report