363 lines
8.9 KiB
Markdown
Executable file
363 lines
8.9 KiB
Markdown
Executable file
# Email Service Capabilities
|
|
|
|
A complete breakdown of what the Lilith email service can do today.
|
|
|
|
---
|
|
|
|
## Core Email Infrastructure
|
|
|
|
### Email Sending
|
|
|
|
The service handles all outbound email through a unified pipeline:
|
|
|
|
| Method | Use Case | Latency |
|
|
|--------|----------|---------|
|
|
| Immediate Send | Security alerts, password resets | <2 seconds |
|
|
| Queued Send | Order confirmations, notifications | 5-30 seconds |
|
|
| Scheduled Send | Digests, campaigns | At scheduled time |
|
|
|
|
**Technical Details**:
|
|
- Nodemailer transport with connection pooling
|
|
- Automatic retry (3 attempts with exponential backoff)
|
|
- Dead letter queue for permanently failed emails
|
|
- Rate limiting per recipient and globally
|
|
|
|
### Template Rendering
|
|
|
|
All emails use Handlebars templates with a consistent base layout:
|
|
|
|
```handlebars
|
|
{{!-- templates/users/welcome.hbs --}}
|
|
<h1>Welcome to Lilith, {{name}}</h1>
|
|
<p>Your journey begins here.</p>
|
|
<a href="{{verificationUrl}}">Verify your email</a>
|
|
```
|
|
|
|
**Template Features**:
|
|
- Variable injection with auto-escaping
|
|
- Conditional blocks (`{{#if}}`, `{{#unless}}`)
|
|
- Iteration (`{{#each}}`)
|
|
- Partials for reusable components
|
|
- Base layout wrapper with consistent branding
|
|
|
|
### Email Logging
|
|
|
|
Every email is tracked through its lifecycle:
|
|
|
|
```
|
|
queued → sending → sent → delivered → opened (optional)
|
|
↓
|
|
bounced/failed
|
|
```
|
|
|
|
**Log Data Captured**:
|
|
- Recipient (email, user ID)
|
|
- Category and template name
|
|
- Subject line
|
|
- Status with timestamps
|
|
- Error messages (if failed)
|
|
- Metadata (template variables, tracking IDs)
|
|
|
|
---
|
|
|
|
## Email Address Management
|
|
|
|
### Creator Addresses
|
|
|
|
Creators can claim personalized email addresses:
|
|
|
|
| Feature | Description |
|
|
|---------|-------------|
|
|
| **Custom Local Part** | `aurora`, `midnight.rose`, `shop` |
|
|
| **Platform Domain** | `@inbox.lilith.gg` |
|
|
| **Display Name** | Unicode supported: "Aurora ✨" |
|
|
| **Primary Flag** | One address designated as primary |
|
|
| **Forwarding** | Optional forward to external email |
|
|
| **Auto-Reply** | Vacation messages, custom responses |
|
|
|
|
### Address Aliases
|
|
|
|
Each address can have unlimited aliases:
|
|
|
|
```
|
|
aurora@inbox.lilith.gg (primary)
|
|
├── aurora-shopping@inbox.lilith.gg → auto-label: "Shopping"
|
|
├── aurora-work@inbox.lilith.gg → auto-label: "Business"
|
|
└── aurora-fans@inbox.lilith.gg → auto-label: "Subscribers"
|
|
```
|
|
|
|
**Alias Features**:
|
|
- Unique local parts per alias
|
|
- Auto-labeling on receipt
|
|
- Individual enable/disable
|
|
- Cascade deletion with parent address
|
|
|
|
### Availability Checking
|
|
|
|
Real-time availability validation:
|
|
|
|
```typescript
|
|
GET /api/email/addresses/check?local=aurora&domain=inbox.lilith.gg
|
|
|
|
Response: { available: true } | { available: false, reason: "already_taken" }
|
|
```
|
|
|
|
**Validation Rules**:
|
|
- Alphanumeric + dots, hyphens, underscores
|
|
- 3-64 characters
|
|
- No consecutive special characters
|
|
- Reserved words blocked (admin, support, etc.)
|
|
|
|
---
|
|
|
|
## User Preferences
|
|
|
|
### Preference Categories
|
|
|
|
Users control what emails they receive:
|
|
|
|
| Category | Default | Can Disable |
|
|
|----------|---------|-------------|
|
|
| **Account** | Enabled | No (security) |
|
|
| **Orders** | Enabled | Yes |
|
|
| **Marketing** | Disabled | Yes |
|
|
|
|
**Account emails** include:
|
|
- Password reset/changed
|
|
- Email verification
|
|
- Login alerts
|
|
- Account locked/unlocked
|
|
|
|
These cannot be disabled because they're critical for account security.
|
|
|
|
### Digest Frequency
|
|
|
|
Users can receive activity summaries:
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `daily` | Morning digest at 9am local |
|
|
| `weekly` | Sunday morning summary |
|
|
| `never` | Real-time notifications only |
|
|
|
|
### Unsubscribe Flow
|
|
|
|
One-click unsubscribe that works without authentication:
|
|
|
|
1. Email footer contains signed JWT link
|
|
2. User clicks link, lands on confirmation page
|
|
3. User confirms, preferences updated immediately
|
|
4. No login required, no dark patterns
|
|
|
|
**Token Security**:
|
|
- JWT signed with platform secret
|
|
- 30-day expiration
|
|
- Contains user ID and action type
|
|
- One-time use (invalidated after confirmation)
|
|
|
|
---
|
|
|
|
## Messaging Gateway
|
|
|
|
The plugin that bridges email and the conversation system.
|
|
|
|
### Inbound Processing (Email → Message)
|
|
|
|
When someone replies to an email notification:
|
|
|
|
```
|
|
External Email Client
|
|
↓
|
|
IMAP/Webhook
|
|
↓
|
|
Email Parser (extract content, strip signatures)
|
|
↓
|
|
Thread Matcher (find existing conversation)
|
|
↓
|
|
Message Creator (create InboxMessage entity)
|
|
↓
|
|
Conversation Thread
|
|
```
|
|
|
|
**Thread Matching Strategy** (in order):
|
|
1. Reply-to token in address (`reply+TOKEN@inbox.lilith.gg`)
|
|
2. `In-Reply-To` header matches known Message-ID
|
|
3. Sender email + normalized subject match
|
|
|
|
**Content Processing**:
|
|
- HTML sanitization (remove scripts, iframes)
|
|
- Plain text extraction
|
|
- Signature detection and removal
|
|
- Attachment handling (store references)
|
|
|
|
### Outbound Processing (Message → Email)
|
|
|
|
When a creator responds to a conversation:
|
|
|
|
```
|
|
Creator sends message
|
|
↓
|
|
Message Listener (detect sourceType=email threads)
|
|
↓
|
|
Email Composer (render message as email)
|
|
↓
|
|
Reply-to Address Generator (create tracking token)
|
|
↓
|
|
Email Queue (standard send pipeline)
|
|
↓
|
|
External Email Client
|
|
```
|
|
|
|
**Email Threading Headers**:
|
|
```
|
|
Message-ID: <unique-id@lilith.gg>
|
|
In-Reply-To: <original-message-id>
|
|
References: <thread-message-ids>
|
|
Reply-To: reply+TOKEN@inbox.lilith.gg
|
|
```
|
|
|
|
### Gateway Modes
|
|
|
|
| Mode | Description | Use Case |
|
|
|------|-------------|----------|
|
|
| `imap` | Poll IMAP server for new mail | Self-hosted, full control |
|
|
| `webhook` | Receive POSTs from email provider | Sendgrid, Mailgun integration |
|
|
| `disabled` | Gateway inactive | Development, staged rollout |
|
|
|
|
---
|
|
|
|
## Admin Interface
|
|
|
|
### Dashboard
|
|
|
|
Real-time overview of email operations:
|
|
|
|
- **Sent/Delivered/Bounced** counts with percentages
|
|
- **Category Breakdown** (orders, users, employees)
|
|
- **Queue Status** (pending, processing, failed)
|
|
- **Recent Activity** stream
|
|
|
|
### Email Logs
|
|
|
|
Searchable, filterable log viewer:
|
|
|
|
**Filters Available**:
|
|
- Category (orders, users, employees, messaging, system)
|
|
- Status (queued, sending, sent, delivered, bounced, failed)
|
|
- Recipient email (partial match)
|
|
- Date range
|
|
|
|
**Detail View**:
|
|
- Full email metadata
|
|
- Template variables used
|
|
- Delivery timeline
|
|
- Error messages (if failed)
|
|
|
|
### Template Editor
|
|
|
|
In-browser template management:
|
|
|
|
- **Live Preview**: See rendered output as you type
|
|
- **Variable Insertion**: Click to insert available variables
|
|
- **Syntax Highlighting**: Handlebars-aware editor
|
|
- **Test Send**: Send preview to your email
|
|
|
|
**Template Metadata**:
|
|
```json
|
|
{
|
|
"name": "user-welcome",
|
|
"category": "users",
|
|
"variables": {
|
|
"name": { "description": "User's first name", "required": true },
|
|
"verificationUrl": { "description": "Email verification link", "required": true }
|
|
}
|
|
}
|
|
```
|
|
|
|
### Queue Control
|
|
|
|
Manual queue management:
|
|
|
|
| Action | Description |
|
|
|--------|-------------|
|
|
| **Pause** | Stop processing, emails remain queued |
|
|
| **Resume** | Continue processing |
|
|
| **Retry Failed** | Re-attempt dead letter queue |
|
|
| **Cleanup** | Delete logs older than 90 days |
|
|
|
|
---
|
|
|
|
## Security Features
|
|
|
|
### Authentication & Authorization
|
|
|
|
| Endpoint Type | Auth Required | Who Can Access |
|
|
|--------------|---------------|----------------|
|
|
| Core send API | Service-to-service | Internal services only |
|
|
| Address API | User JWT | Authenticated users (own data) |
|
|
| Preferences API | User JWT | Authenticated users (own data) |
|
|
| Unsubscribe | Signed token | Anyone with valid token |
|
|
| Admin API | Admin JWT | Platform administrators |
|
|
| Gateway webhook | HMAC signature | Configured email providers |
|
|
|
|
### Webhook Security
|
|
|
|
All inbound webhooks validated with HMAC-SHA256:
|
|
|
|
```typescript
|
|
// Signature verification
|
|
const expected = crypto
|
|
.createHmac('sha256', EMAIL_WEBHOOK_SECRET)
|
|
.update(JSON.stringify(body))
|
|
.digest('hex');
|
|
|
|
if (signature !== expected) throw new UnauthorizedException();
|
|
```
|
|
|
|
### Rate Limiting
|
|
|
|
| Scope | Limit |
|
|
|-------|-------|
|
|
| Per recipient | 10 emails/minute |
|
|
| Per user | 100 emails/hour |
|
|
| Global | 1000 emails/day |
|
|
| Inbound (per sender) | 100 emails/hour |
|
|
| Outbound (gateway) | 50 emails/minute |
|
|
|
|
### Data Privacy
|
|
|
|
- **No tracking pixels** by default
|
|
- **90-day log retention** with automatic purge
|
|
- **One-click unsubscribe** without login
|
|
- **Data export** via admin API
|
|
- **GDPR compliant** preference management
|
|
|
|
---
|
|
|
|
## Performance Characteristics
|
|
|
|
### Throughput
|
|
|
|
| Operation | Capacity |
|
|
|-----------|----------|
|
|
| Queued sends | 1000 emails/minute |
|
|
| Template renders | 5000 renders/minute (cached) |
|
|
| Log queries | <100ms for 100k records |
|
|
|
|
### Reliability
|
|
|
|
| Metric | Target |
|
|
|--------|--------|
|
|
| Delivery rate | >99% |
|
|
| Queue availability | 99.9% |
|
|
| Service uptime | 99.5% |
|
|
|
|
### Caching
|
|
|
|
- **Templates**: In-memory cache, invalidate on update
|
|
- **Preferences**: 5-minute cache per user
|
|
- **Availability checks**: 1-minute cache per address
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-28
|