// unsubscribe.mjs, 2026.02.12 // Email blast unsubscribe / resubscribe endpoint. // GET ?email=X&token=Y → confirmation page // POST {email, token, action} → process unsubscribe/resubscribe import { createHmac, timingSafeEqual } from "crypto"; import { connect } from "../../backend/database.mjs"; import { respond } from "../../backend/http.mjs"; const COLLECTION = "email-blast-unsubscribes"; let cachedSecret = null; async function getUnsubscribeSecret(database) { if (cachedSecret) return cachedSecret; const secrets = await database.db.collection("secrets").findOne({ _id: "email-blast" }); if (!secrets?.unsubscribeSecret) throw new Error("email-blast secrets not found in database"); cachedSecret = secrets.unsubscribeSecret; return cachedSecret; } function generateToken(email, secret) { return createHmac("sha256", secret) .update(email.toLowerCase().trim()) .digest("hex"); } function verifyToken(email, token, secret) { try { const expected = generateToken(email, secret); if (expected.length !== token.length) return false; return timingSafeEqual(Buffer.from(expected), Buffer.from(token)); } catch { return false; } } function html(title, body) { return ` ${title} — Aesthetic.Computer ${body} `; } function parseBody(event) { const contentType = (event.headers["content-type"] || "").toLowerCase(); if (contentType.includes("application/json")) { return JSON.parse(event.body || "{}"); } return Object.fromEntries(new URLSearchParams(event.body || "")); } export async function handler(event) { if (event.httpMethod === "OPTIONS") return respond(200, {}); const H = { "Content-Type": "text/html; charset=utf-8" }; let database; try { database = await connect(); const secret = await getUnsubscribeSecret(database); const col = database.db.collection(COLLECTION); // --- GET: show confirmation page --- if (event.httpMethod === "GET") { const { email, token } = event.queryStringParameters || {}; if (!email || !token) { return respond(400, html("Error", `

Missing email or token.

`), H); } if (!verifyToken(email, token, secret)) { return respond( 403, html("Invalid Link", `

invalid link

This unsubscribe link is expired or invalid.

If you need help, email me@jas.life

`), H, ); } const existing = await col.findOne({ email: email.toLowerCase().trim() }); if (existing) { return respond( 200, html( "Unsubscribed", `

you're unsubscribed

you won't receive email blasts from aesthetic.computer.

changed your mind?

`, ), H, ); } return respond( 200, html( "Unsubscribe", `

unsubscribe

click below to stop receiving email blasts from aesthetic.computer.

`, ), H, ); } // --- POST: process action --- if (event.httpMethod === "POST") { const body = parseBody(event); const { email, token, action } = body; if (!email || !token || !action) { return respond(400, html("Error", `

Missing required fields.

`), H); } if (!verifyToken(email, token, secret)) { return respond( 403, html("Invalid Link", `

invalid link

This link is expired or invalid.

`), H, ); } const normalizedEmail = email.toLowerCase().trim(); await col.createIndex({ email: 1 }, { unique: true }); if (action === "unsubscribe") { try { await col.insertOne({ email: normalizedEmail, unsubscribedAt: new Date(), }); } catch (err) { if (err.code !== 11000) throw err; } return respond( 200, html( "Unsubscribed", `

done!

you've been unsubscribed from aesthetic.computer emails.

changed your mind? resubscribe

`, ), H, ); } if (action === "resubscribe") { await col.deleteOne({ email: normalizedEmail }); return respond( 200, html( "Resubscribed", `

welcome back!

you've been resubscribed to aesthetic.computer emails.

`, ), H, ); } return respond(400, html("Error", `

Unknown action.

`), H); } return respond(405, html("Error", `

Method not allowed.

`), H); } finally { if (database) await database.disconnect(); } }