Email notifications for Nostr private groups
Find a file
2026-08-25 10:37:55 -04:00
.agents/skills/beads bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
.beads bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
.claude bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
.codex bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
.fragua Onboard to fragua 2026-08-25 10:37:14 -04:00
script Onboard to fragua 2026-08-25 10:37:14 -04:00
src Switch postmark api to smtp 2026-08-24 16:12:32 -04:00
test test: add failing test for normalizeRelayUrl(undefined) crash 2026-08-25 09:29:29 -04:00
web fix: guard deleteAlert and publishAlert against undefined relay 2026-08-24 18:22:46 -04:00
.dockerignore Add Dockerfile, docker-compose.yml, .dockerignore 2026-08-18 12:40:42 -04:00
.env.template Add Dockerfile, docker-compose.yml, .dockerignore 2026-08-18 12:40:42 -04:00
.gitattributes Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
.gitignore bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
.nvmrc Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
.prettierignore Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
.prettierrc Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
AGENTS.md bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
build-in-production.sh Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
CLAUDE.md bd init: initialize beads issue tracking 2026-08-24 16:11:52 -04:00
docker-compose.yml Add Dockerfile, docker-compose.yml, .dockerignore 2026-08-18 12:40:42 -04:00
Dockerfile Fix docker build 2026-08-24 15:45:40 -04:00
eslint.config.mjs Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
LICENSE Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
package.json Switch postmark api to smtp 2026-08-24 16:12:32 -04:00
pnpm-lock.yaml Switch postmark api to smtp 2026-08-24 16:12:32 -04:00
pnpm-workspace.yaml Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
README.md Add Dockerfile, docker-compose.yml, .dockerignore 2026-08-18 12:40:42 -04:00
remove-pnpm-overrides.js Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00
tsconfig.json Initial mailship fork from anchor 2026-08-18 12:21:22 -04:00

Mailship

A Nostr email notification server. Receives events pushed from relays via NIP-9a, stores them, and sends daily or weekly digest emails.

Architecture

Flotilla ──HTTP──▶ Mailship (POST /subscription/email)
  │                   NIP-98 auth
  │                   returns {key, callback}
  │
  └──kind 30390──▶ relay or NPB
                         │
                    event matches filter
                         │
                         ▼
                    POST /notify/:subId ──▶ Mailship
                         {id, relay}         │
                           UUID in path      ├── fetch event from relay
                           is the auth       ├── store in SQLite (dedup)
                                             │
                                        cron fires ──▶ render digest ──▶ Postmark ──▶ email

Configuration

Variable Required Description
MAILSHIP_SECRET ✓ A nostr private key hex string for the server's identity
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
DEFAULT_RELAYS ✓ Comma-separated list of default relays
INDEXER_RELAYS ✓ Comma-separated list of indexer relays
SEARCH_RELAYS ✓ Comma-separated list of search relays
PORT Port to run on (default: 3000)

API

POST /subscription/email

Register for email digests.

Body: { email, frequency, pubkey }
Auth: NIP-98 (planned)
Response: { key, callback }

DELETE /subscription/:key

Unsubscribe.

Auth: NIP-98 (planned)
Response: { ok: true }

POST /notify/:id

NIP-9a relay push callback. Called by relays or NPB when matching events are found.

Body: { id, relay }
Response: { ok: true, stored: boolean }
Returns 404 if subscription not found or inactive.

GET /confirm?token=...

Confirm email address via link from confirmation email.

GET /unsubscribe?token=...

Unsubscribe via link from digest email.

Development

pnpm install
pnpm run build
pnpm run start

Docker

Quick start

cp .env.template .env
# Fill in your secrets in .env
docker compose up -d

Build and run manually

docker build -t mailship .
docker run -d \
  -p 4738:4738 \
  -v mailship-data:/data \
  --env-file .env \
  mailship

Tests

pnpm test          # Run integration tests
pnpm test:server   # Start server for manual testing

Forked from Anchor

Mailship is a fork of Anchor, stripped of push notification support and adapted for NIP-9a relay push event intake.