423 lines
9.8 KiB
Markdown
Executable file
423 lines
9.8 KiB
Markdown
Executable file
# Email Service Usage Guide
|
|
|
|
How to integrate with and use the Lilith email service.
|
|
|
|
---
|
|
|
|
## For Developers
|
|
|
|
### Sending Transactional Emails
|
|
|
|
The email service exposes internal APIs for other platform services to send emails.
|
|
|
|
#### Immediate Send (High Priority)
|
|
|
|
Use for security-critical emails that must be delivered immediately:
|
|
|
|
```typescript
|
|
// From another NestJS service
|
|
import { EmailService } from '@lilith/email-backend';
|
|
|
|
@Injectable()
|
|
export class AuthService {
|
|
constructor(private emailService: EmailService) {}
|
|
|
|
async sendPasswordReset(user: User, token: string) {
|
|
await this.emailService.send({
|
|
to: user.email,
|
|
userId: user.id,
|
|
template: 'user-password-reset',
|
|
category: 'users',
|
|
variables: {
|
|
name: user.firstName,
|
|
resetUrl: `https://lilith.gg/reset-password?token=${token}`,
|
|
expiresIn: '1 hour',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Queued Send (Standard Priority)
|
|
|
|
Use for non-urgent emails that can tolerate slight delays:
|
|
|
|
```typescript
|
|
async sendOrderConfirmation(order: Order) {
|
|
await this.emailService.queue({
|
|
to: order.customerEmail,
|
|
userId: order.customerId,
|
|
template: 'order-confirmation',
|
|
category: 'orders',
|
|
priority: 'normal', // 'high' | 'normal' | 'low'
|
|
variables: {
|
|
orderNumber: order.id,
|
|
items: order.items,
|
|
total: order.total,
|
|
deliveryDate: order.estimatedDelivery,
|
|
},
|
|
});
|
|
}
|
|
```
|
|
|
|
### Creating New Email Templates
|
|
|
|
Templates live in `backend/templates/{category}/`:
|
|
|
|
```
|
|
templates/
|
|
├── layouts/
|
|
│ └── base.hbs # Shared wrapper
|
|
├── orders/
|
|
│ ├── confirmation.hbs
|
|
│ └── shipped.hbs
|
|
├── users/
|
|
│ ├── welcome.hbs
|
|
│ ├── verification.hbs
|
|
│ └── password-reset.hbs
|
|
└── employees/
|
|
└── daily-digest.hbs
|
|
```
|
|
|
|
#### Template Structure
|
|
|
|
```handlebars
|
|
{{!-- templates/orders/confirmation.hbs --}}
|
|
{{!-- Variables: orderNumber, items, total, deliveryDate --}}
|
|
|
|
<h1>Order Confirmed</h1>
|
|
|
|
<p>Thank you for your order, {{name}}!</p>
|
|
|
|
<table>
|
|
<tr>
|
|
<th>Order Number</th>
|
|
<td>#{{orderNumber}}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>Total</th>
|
|
<td>{{formatCurrency total}}</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h2>Items</h2>
|
|
<ul>
|
|
{{#each items}}
|
|
<li>{{this.name}} - {{formatCurrency this.price}}</li>
|
|
{{/each}}
|
|
</ul>
|
|
|
|
{{#if deliveryDate}}
|
|
<p>Estimated delivery: {{formatDate deliveryDate}}</p>
|
|
{{/if}}
|
|
```
|
|
|
|
#### Registering Templates in Database
|
|
|
|
Templates are stored in the database for admin editing. Seed them via migration:
|
|
|
|
```typescript
|
|
// migrations/SeedOrderTemplates.ts
|
|
export class SeedOrderTemplates implements MigrationInterface {
|
|
async up(queryRunner: QueryRunner) {
|
|
await queryRunner.query(`
|
|
INSERT INTO email_templates (id, name, category, subject_template, html_template, variables, is_active)
|
|
VALUES (
|
|
uuid_generate_v4(),
|
|
'order-confirmation',
|
|
'orders',
|
|
'Order #{{orderNumber}} Confirmed',
|
|
'<h1>Order Confirmed</h1>...',
|
|
'{"orderNumber": {"required": true}, "items": {"required": true}, "total": {"required": true}}',
|
|
true
|
|
)
|
|
`);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Integrating the Messaging Gateway
|
|
|
|
To enable email-to-conversation for a feature:
|
|
|
|
```typescript
|
|
// In your feature's module
|
|
import { MessagingGatewayModule } from '@lilith/email-messaging-plugin';
|
|
|
|
@Module({
|
|
imports: [
|
|
MessagingGatewayModule.forRoot({
|
|
inboundMode: process.env.EMAIL_INBOUND_MODE || 'disabled',
|
|
outboundEnabled: process.env.EMAIL_OUTBOUND_ENABLED === 'true',
|
|
replyDomain: process.env.EMAIL_REPLY_DOMAIN || 'inbox.lilith.gg',
|
|
}),
|
|
],
|
|
})
|
|
export class ConversationModule {}
|
|
```
|
|
|
|
---
|
|
|
|
## For Platform Administrators
|
|
|
|
### Accessing the Admin Dashboard
|
|
|
|
Navigate to `/email` in the platform admin interface:
|
|
|
|
```
|
|
Platform Admin
|
|
├── /email Dashboard with stats
|
|
├── /email/logs Searchable email history
|
|
└── /email/templates Template editor
|
|
```
|
|
|
|
### Monitoring Email Health
|
|
|
|
**Key Metrics to Watch**:
|
|
|
|
| Metric | Healthy | Warning | Critical |
|
|
|--------|---------|---------|----------|
|
|
| Delivery Rate | >98% | 95-98% | <95% |
|
|
| Bounce Rate | <2% | 2-5% | >5% |
|
|
| Queue Depth | <100 | 100-500 | >500 |
|
|
|
|
**Common Issues**:
|
|
|
|
| Symptom | Likely Cause | Action |
|
|
|---------|--------------|--------|
|
|
| High bounce rate | Invalid emails in database | Review failed logs, clean bad addresses |
|
|
| Queue backing up | SMTP connection issues | Check SMTP credentials, connection limits |
|
|
| Low open rates | Emails going to spam | Review SPF/DKIM/DMARC configuration |
|
|
|
|
### Editing Templates
|
|
|
|
1. Navigate to `/email/templates`
|
|
2. Select template from category list
|
|
3. Edit subject and body in the editor
|
|
4. Use "Preview" to test with sample data
|
|
5. Click "Save" to deploy changes
|
|
|
|
**Template Best Practices**:
|
|
- Keep subject lines under 50 characters
|
|
- Use the preview to test on mobile widths
|
|
- Always include unsubscribe link (auto-injected in base layout)
|
|
- Test with real data before deploying
|
|
|
|
### Managing the Queue
|
|
|
|
**Pause Queue** (during maintenance):
|
|
```
|
|
POST /api/email/admin/queue/pause
|
|
```
|
|
|
|
**Resume Queue**:
|
|
```
|
|
POST /api/email/admin/queue/resume
|
|
```
|
|
|
|
**Force Cleanup** (remove old logs):
|
|
```
|
|
POST /api/email/admin/cleanup
|
|
Body: { "olderThanDays": 90 }
|
|
```
|
|
|
|
---
|
|
|
|
## For Users
|
|
|
|
### Managing Your Email Preferences
|
|
|
|
1. Go to your account settings
|
|
2. Click "Email Preferences"
|
|
3. Toggle categories on/off:
|
|
- **Order Updates**: Purchase confirmations, shipping notifications
|
|
- **Marketing**: Promotional emails, newsletters
|
|
- **Account**: Security alerts (always on)
|
|
|
|
4. Set digest frequency:
|
|
- **Daily**: Get a morning summary
|
|
- **Weekly**: Sunday roundup
|
|
- **Real-time**: Individual notifications
|
|
|
|
### Unsubscribing from Emails
|
|
|
|
Every email includes an unsubscribe link in the footer. Clicking it:
|
|
|
|
1. Opens a confirmation page (no login required)
|
|
2. Shows what you're unsubscribing from
|
|
3. One click to confirm
|
|
4. Immediate effect
|
|
|
|
**Note**: Account security emails cannot be unsubscribed. This protects your account.
|
|
|
|
### Managing Your Email Addresses (Creators)
|
|
|
|
If you're a creator on the platform:
|
|
|
|
1. Go to profile settings
|
|
2. Click "Email Addresses"
|
|
3. **Add Address**: Claim a new `@inbox.lilith.gg` address
|
|
4. **Create Alias**: Add variations for organization
|
|
5. **Set Primary**: Choose which address appears publicly
|
|
|
|
**Tips**:
|
|
- Use aliases to organize by purpose (shopping, business, fans)
|
|
- Enable forwarding if you want copies to external email
|
|
- Set up auto-replies for vacation or busy periods
|
|
|
|
---
|
|
|
|
## API Reference
|
|
|
|
### Public Endpoints (No Auth)
|
|
|
|
```
|
|
GET /api/email/preferences/unsubscribe/:token
|
|
POST /api/email/preferences/unsubscribe/:token
|
|
```
|
|
|
|
### User Endpoints (Requires User JWT)
|
|
|
|
```
|
|
# Preferences
|
|
GET /api/email/preferences
|
|
PUT /api/email/preferences
|
|
|
|
# Addresses (creators)
|
|
GET /api/email/addresses
|
|
POST /api/email/addresses
|
|
GET /api/email/addresses/check?local=xxx&domain=xxx
|
|
GET /api/email/addresses/:id
|
|
PATCH /api/email/addresses/:id
|
|
DELETE /api/email/addresses/:id
|
|
|
|
# Aliases
|
|
GET /api/email/addresses/:id/aliases
|
|
POST /api/email/addresses/:id/aliases
|
|
PATCH /api/email/addresses/aliases/:aliasId
|
|
DELETE /api/email/addresses/aliases/:aliasId
|
|
```
|
|
|
|
### Admin Endpoints (Requires Admin JWT)
|
|
|
|
```
|
|
# Statistics
|
|
GET /api/email/admin/stats
|
|
|
|
# Queue Control
|
|
POST /api/email/admin/queue/pause
|
|
POST /api/email/admin/queue/resume
|
|
POST /api/email/admin/cleanup
|
|
|
|
# Logs
|
|
GET /api/email/admin/logs
|
|
GET /api/email/admin/logs/:id
|
|
|
|
# Templates
|
|
GET /api/email/admin/templates
|
|
GET /api/email/admin/templates/:id
|
|
PUT /api/email/admin/templates/:id
|
|
POST /api/email/admin/templates/:id/preview
|
|
```
|
|
|
|
### Gateway Endpoints (HMAC Signature)
|
|
|
|
```
|
|
POST /api/email/gateway/inbound # Webhook for incoming mail
|
|
POST /api/email/gateway/sync # Force IMAP sync (admin)
|
|
GET /api/email/gateway/stats # Gateway statistics
|
|
GET /api/email/gateway/mappings # Thread mappings
|
|
```
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
### Required
|
|
|
|
```env
|
|
# Application
|
|
PORT=3011
|
|
NODE_ENV=production
|
|
|
|
# Database
|
|
DB_HOST=localhost
|
|
DB_PORT=5432
|
|
DB_NAME=lilith_email
|
|
DB_USER=email_service
|
|
DB_PASS=secret
|
|
|
|
# SMTP
|
|
SMTP_HOST=smtp.example.com
|
|
SMTP_PORT=587
|
|
SMTP_USER=noreply@lilith.gg
|
|
SMTP_PASS=secret
|
|
|
|
# Queue (Redis)
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
```
|
|
|
|
### Optional
|
|
|
|
```env
|
|
# SMTP Options
|
|
SMTP_SECURE=false # TLS on port 465
|
|
SMTP_FROM=noreply@lilith.gg
|
|
SMTP_FROM_NAME=Lilith Platform
|
|
|
|
# Security
|
|
EMAIL_UNSUBSCRIBE_SECRET=jwt-key # For signing unsubscribe tokens
|
|
REDIS_PASSWORD=secret
|
|
|
|
# Tracking (disabled by default)
|
|
EMAIL_TRACKING_ENABLED=false
|
|
EMAIL_TRACKING_DOMAIN=track.lilith.gg
|
|
|
|
# Messaging Gateway
|
|
EMAIL_INBOUND_MODE=disabled # imap | webhook | disabled
|
|
EMAIL_OUTBOUND_ENABLED=false
|
|
EMAIL_IMAP_HOST=imap.example.com
|
|
EMAIL_IMAP_PORT=993
|
|
EMAIL_IMAP_USER=inbox@lilith.gg
|
|
EMAIL_IMAP_PASS=secret
|
|
EMAIL_REPLY_DOMAIN=inbox.lilith.gg
|
|
EMAIL_REPLY_SECRET=jwt-key
|
|
EMAIL_WEBHOOK_SECRET=hmac-key
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Emails Not Sending
|
|
|
|
1. **Check SMTP credentials**: Verify `SMTP_HOST`, `SMTP_USER`, `SMTP_PASS`
|
|
2. **Check Redis connection**: Queue might not be processing
|
|
3. **Check service logs**: `pnpm --filter @lilith/email-backend logs`
|
|
4. **Check queue status**: `GET /api/email/admin/stats`
|
|
|
|
### High Bounce Rate
|
|
|
|
1. **Review failed logs**: `/email/logs?status=bounced`
|
|
2. **Check SPF record**: `dig TXT lilith.gg`
|
|
3. **Verify DKIM**: Check your DNS provider
|
|
4. **Test deliverability**: Use mail-tester.com
|
|
|
|
### Gateway Not Working
|
|
|
|
1. **Check mode**: Is `EMAIL_INBOUND_MODE` set correctly?
|
|
2. **Verify IMAP credentials**: Test connection manually
|
|
3. **Check webhook secret**: Must match email provider config
|
|
4. **Review gateway stats**: `GET /api/email/gateway/stats`
|
|
|
|
### Templates Not Rendering
|
|
|
|
1. **Check template exists**: In database and file system
|
|
2. **Verify variables**: All required variables provided?
|
|
3. **Check syntax**: Valid Handlebars syntax?
|
|
4. **Test preview**: Use admin template preview
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-28
|