From 49b7b0d83b3890d3a9bb41bb3c2df022aec0ee2a Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 10 Sep 2026 11:30:50 -0400 Subject: [PATCH 1/3] Align README, docker-compose, .env.template with SMTP mailer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all Postmark references (POSTMARK_API_KEY, POSTMARK_SENDER_ADDRESS) with SMTP configuration (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM) across documentation, deployment config, template, and test. - README.md: architecture diagram (Postmark → SMTP) and configuration table - docker-compose.yml: POSTMARK_* env vars replaced with SMTP_* required vars - .env.template: POSTMARK_* entries replaced with SMTP_* entries - test/integration.sh: POSTMARK_* test exports replaced with SMTP_* test values --- .env.template | 7 +++++-- README.md | 9 ++++++--- docker-compose.yml | 7 +++++-- test/integration.sh | 7 +++++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.env.template b/.env.template index 885b96f..4f469f2 100644 --- a/.env.template +++ b/.env.template @@ -5,7 +5,10 @@ BASE_URL=http://localhost:4738 INDEXER_RELAYS=purplepag.es,relay.damus.io,relay.nostr.band DEFAULT_RELAYS=relay.damus.io,nos.lol SEARCH_RELAYS=relay.nostr.band -POSTMARK_API_KEY= -POSTMARK_SENDER_ADDRESS= +SMTP_HOST= +SMTP_PORT= +SMTP_USER= +SMTP_PASSWORD= +SMTP_FROM= PORT=4738 DATA_DIR=./data diff --git a/README.md b/README.md index 563d760..a7d388a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Flotilla ──HTTP──▶ Mailship (POST /subscription/email) UUID in path ├── fetch event from relay is the auth ├── store in SQLite (dedup) │ - cron fires ──▶ render digest ──▶ Postmark ──▶ email + cron fires ──▶ render digest ──▶ SMTP ──▶ email ``` ## Configuration @@ -30,8 +30,11 @@ Flotilla ──HTTP──▶ Mailship (POST /subscription/email) | `MAILSHIP_NAME` | ✓ | Name of this Mailship instance | | `MAILSHIP_URL` | ✓ | Public URL of this instance | | `BASE_URL` | ✓ | Base URL for callback URLs (same as MAILSHIP_URL typically) | -| `POSTMARK_API_KEY` | ✓ | Postmark API key for sending emails | -| `POSTMARK_SENDER_ADDRESS` | ✓ | Verified sender email in Postmark | +| `SMTP_HOST` | ✓ | SMTP server hostname | +| `SMTP_PORT` | ✓ | SMTP server port | +| `SMTP_USER` | ✓ | SMTP username | +| `SMTP_PASSWORD` | ✓ | SMTP password | +| `SMTP_FROM` | ✓ | From email address for outgoing mail | | `DEFAULT_RELAYS` | ✓ | Comma-separated list of default relays | | `INDEXER_RELAYS` | ✓ | Comma-separated list of indexer relays | | `SEARCH_RELAYS` | ✓ | Comma-separated list of search relays | diff --git a/docker-compose.yml b/docker-compose.yml index 1d172dd..10eac1b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,11 @@ services: - MAILSHIP_NAME=${MAILSHIP_NAME:-Mailship} - MAILSHIP_URL=${MAILSHIP_URL:?required} - BASE_URL=${BASE_URL:?required} - - POSTMARK_API_KEY=${POSTMARK_API_KEY:?required} - - POSTMARK_SENDER_ADDRESS=${POSTMARK_SENDER_ADDRESS:?required} + - SMTP_HOST=${SMTP_HOST:?required} + - SMTP_PORT=${SMTP_PORT:?required} + - SMTP_USER=${SMTP_USER:?required} + - SMTP_PASSWORD=${SMTP_PASSWORD:?required} + - SMTP_FROM=${SMTP_FROM:?required} - DEFAULT_RELAYS=${DEFAULT_RELAYS:-wss://relay.damus.io,wss://relay.primal.net} - INDEXER_RELAYS=${INDEXER_RELAYS:-wss://purplepag.es,wss://relay.damus.io} - SEARCH_RELAYS=${SEARCH_RELAYS:-wss://relay.nostr.band} diff --git a/test/integration.sh b/test/integration.sh index 88dcc3a..e6f629a 100755 --- a/test/integration.sh +++ b/test/integration.sh @@ -46,8 +46,11 @@ export MAILSHIP_SECRET="$SECRET" export MAILSHIP_NAME="Mailship Test" export MAILSHIP_URL="$BASE_URL" export BASE_URL="$BASE_URL" -export POSTMARK_API_KEY="test" -export POSTMARK_SENDER_ADDRESS="test@test.com" +export SMTP_HOST="localhost" +export SMTP_PORT="587" +export SMTP_USER="test@test.com" +export SMTP_PASSWORD="test" +export SMTP_FROM="test@test.com" export DEFAULT_RELAYS="wss://relay.damus.io" export INDEXER_RELAYS="wss://purplepag.es" export SEARCH_RELAYS="wss://relay.nostr.band" -- 2.45.2 From 0eca03189020b0e031f4a4d8fa401fdff30e204e Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 10 Sep 2026 16:59:15 -0400 Subject: [PATCH 2/3] fix: update stale 'Postmark' comment to 'SMTP' in server.ts The subscription error fallback comment still referenced Postmark after the mailer migration. Update it to reflect the SMTP mailer. --- src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index 8671380..bdc913c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -113,7 +113,7 @@ addRoute('post', '/subscription/email', async (req: Request, res: Response) => { const result = await registerSubscription({ pubkey, email, frequency }) res.json(result) } catch (error: any) { - // If the error is just Postmark failing, the subscription was still created + // If the error is just SMTP failing, the subscription was still created // Look up the actual subscription key from the DB const sub = await getSubscriptionByPubkey(pubkey) if (sub) { -- 2.45.2 From 2e2676012604480c502042fbee660a89cd21f1d6 Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 10 Sep 2026 17:03:35 -0400 Subject: [PATCH 3/3] fix: remove unused imports and variables flagged by eslint Resolve 21 pre-existing @typescript-eslint/no-unused-vars errors across 5 files (actions.ts, alert.ts, digest.ts, env.ts, worker/email.ts) that were blocking the script/checks gate. All removals are unused imports and unused variable assignments with no runtime impact. --- src/actions.ts | 2 -- src/alert.ts | 3 --- src/digest.ts | 11 +---------- src/env.ts | 1 - src/worker/email.ts | 2 +- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/actions.ts b/src/actions.ts index 459cd01..dd0c082 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -1,6 +1,4 @@ import { instrument } from 'succinct-async' -import type { Subscription } from './alert.js' -import { getCronExpression } from './alert.js' import * as mailer from './mailer.js' import * as worker from './worker/index.js' import * as db from './database.js' diff --git a/src/alert.ts b/src/alert.ts index 01df785..c61586f 100644 --- a/src/alert.ts +++ b/src/alert.ts @@ -1,6 +1,3 @@ -import { CronExpressionParser } from 'cron-parser' -import { tryCatch, int, HOUR } from '@welshman/lib' - export type Subscription = { id: string key: string diff --git a/src/digest.ts b/src/digest.ts index a693aaa..538c7d5 100644 --- a/src/digest.ts +++ b/src/digest.ts @@ -1,36 +1,27 @@ import { neventEncode, decode } from 'nostr-tools/nip19' import { spec, - now, sortBy, groupBy, displayList, - nth, - nthEq, - dateToSeconds, secondsToDate, } from '@welshman/lib' import { parse, truncate, renderAsHtml } from '@welshman/content' import { TrustedEvent, getParentId, - getIdFilters, - getReplyFilters, NOTE, COMMENT, REACTION, displayProfile, displayPubkey, } from '@welshman/util' -import { Loader, AdapterContext, makeLoader, SocketAdapter } from '@welshman/net' -import { Router, addMinimalFallbacks } from '@welshman/router' -import { call } from '@welshman/lib' +import { Router } from '@welshman/router' import { displayDuration, createElement } from './util.js' import type { Subscription } from './alert.js' import { sendDigest } from './mailer.js' import { profilesByPubkey, - loadRelaySelections, loadProfile, } from './repository.js' diff --git a/src/env.ts b/src/env.ts index 218e4c2..fc7d3ae 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,7 +1,6 @@ import 'dotenv/config' import { always } from '@welshman/lib' import { normalizeRelayUrl } from '@welshman/util' -import { netContext } from '@welshman/net' import { Nip01Signer } from '@welshman/signer' import { routerContext } from '@welshman/router' diff --git a/src/worker/email.ts b/src/worker/email.ts index d60e4a3..df776a5 100644 --- a/src/worker/email.ts +++ b/src/worker/email.ts @@ -65,7 +65,7 @@ export const removeJob = (sub: Subscription) => { } // Daily purge of events older than 7 days -const purgeJob = CronJob.from({ +CronJob.from({ cronTime: '0 0 3 * * *', // 3am UTC daily onTick: async () => { const weekAgo = Math.floor(Date.now() / 1000) - 7 * 24 * 3600 -- 2.45.2