A lightweight, stateless SMTP HTTP proxy built with Bun/TypeScript/ElysiaJS.
- Multiple SMTP providers with automatic failover
- API key authentication via Bearer tokens
- Full email support: text, HTML, CC, BCC, attachments
- Rate limiting per API key
- Stateless: No database required
- Docker-ready: Easy self-hosting
# Required
CORS_ORIGIN=http://localhost:3000
DATABASE_URL=postgres://localhost:5432/dummy # Required by @stem/env, can be dummy
API_KEYS=sk-key-1,sk-key-2 # Comma-separated API keys
# SMTP providers (JSON array)
SMTP_PROVIDERS=[{
"name": "gmail",
"host": "smtp.gmail.com",
"port": 587,
"secure": false,
"auth": {
"user": "your-email@gmail.com",
"pass": "your-app-password"
}
}]
# Optional
MAX_ATTACHMENT_SIZE=10MB # Default: 10MB
RATE_LIMIT_PER_MINUTE=60 # Default: 60 requests/minutedocker-compose up -dSend Email:
curl -X POST http://localhost:3000/v1/send \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"to": "recipient@example.com",
"subject": "Hello",
"text": "Plain text body",
"html": "<h1>HTML body</h1>"
}'Health Check:
curl http://localhost:3000/v1/health \
-H "Authorization: Bearer your-api-key"| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Service status |
/v1/send |
POST | Send email |
/v1/health |
GET | Provider health status |
{
to: string | string[]; // Required
from?: string; // Optional
subject: string; // Required
text?: string; // Plain text body
html?: string; // HTML body
cc?: string | string[]; // CC recipients
bcc?: string | string[]; // BCC recipients
replyTo?: string; // Reply-to address
attachments?: Array<{ // Base64 encoded attachments
filename: string;
content: string; // Base64
contentType?: string;
}>;
}Success (200):
{
"success": true,
"messageId": "<...>",
"provider": "gmail",
"accepted": ["recipient@example.com"],
"rejected": []
}Error (400/401/429/500):
{
"success": false,
"error": "Error description"
}