#
Outbound Service
The outbound service listens to Nostr events and sends them as legacy emails.
#
Architecture
┌──────┐ ┌────────┐ ┌─────────────────┐ ┌─────────────┐
│ User │ ───► │ Relays │ ───► │ Outbound Service│ ───► │ Legacy Email│
└──────┘ └────────┘ └─────────────────┘ └─────────────┘
#
Setup
cd bridge-outbound
npm install
cp .env.example .env
npm run build
npm start
#
Configuration
BRIDGE_PRIVATE_KEY=<hex>
RELAYS=wss://relay.damus.io,wss://nos.lol
# Outbound provider: 'smtp' or 'mailgun'
OUTBOUND_PROVIDER=smtp
FROM_DOMAIN=mail.example.com
# SMTP settings (when OUTBOUND_PROVIDER=smtp)
SMTP_HOST=localhost
SMTP_PORT=25
SMTP_SECURE=false
SMTP_USER=
SMTP_PASS=
# Mailgun settings (when OUTBOUND_PROVIDER=mailgun)
MAILGUN_API_KEY=key-xxx
MAILGUN_DOMAIN=mail.example.com
#
How It Works
- Service subscribes to gift-wrapped events (kind 1059) for its pubkey
- When an event arrives, it unwraps the NIP-59 encryption
- Extracts the email content from the kind 1301 rumor
- Parses the
To:header to find the legacy recipient - Sends via configured provider (SMTP or Mailgun)
#
Processing Flow
flowchart TD
A[Subscribe to Kind 1059] --> B[Receive Gift-Wrapped Event]
B --> C[Unwrap NIP-59]
C --> D[Extract Kind 1301 Rumor]
D --> E[Parse Email Headers]
E --> F{To: is Legacy?}
F -->|No| G[Skip - Nostr Native]
F -->|Yes| H{Plugin Enabled?}
H -->|No| I[Send via Provider]
H -->|Yes| J[Run Plugin Filter]
J -->|Accept| I
J -->|Reject| K[Discard]
J -->|Shadow Reject| L[Silent Discard]
I --> M{SMTP or Mailgun?}
M -->|SMTP| N[Send via SMTP]
M -->|Mailgun| O[Send via Mailgun API]
#
Email From Address
The bridge determines the From address:
- NIP-05 valid: If the email's
Fromis a valid NIP-05 that resolves toevent.pubkey, it's used as-is - Fallback: Otherwise, uses
npub@bridge-domain
# If alice@example.com resolves to event.pubkey
From: alice@example.com
# Otherwise, fallback to npub
From: npub1abc123...@yourdomain.com
#
SMTP Provider
For direct SMTP sending:
OUTBOUND_PROVIDER=smtp
SMTP_HOST=localhost # Your MTA (Postfix, etc.)
SMTP_PORT=25
SMTP_SECURE=false # true for TLS
SMTP_USER= # Optional auth
SMTP_PASS=
#
Mailgun Provider
For Mailgun API sending:
OUTBOUND_PROVIDER=mailgun
MAILGUN_API_KEY=key-xxx
MAILGUN_DOMAIN=mail.example.com
#
Event Format
The service expects events in this format:
{
"kind": 1059,
"pubkey": "<sender>",
"tags": [
["p", "<bridge_pubkey>"]
],
"content": "<encrypted_gift_wrap>"
}
After unwrapping, the inner rumor:
{
"kind": 1301,
"content": "From: sender@nostr\nTo: recipient@gmail.com\nSubject: Hello\n\nMessage body"
}