171 lines
4.2 KiB
Markdown
171 lines
4.2 KiB
Markdown
# @lilith/email-client
|
|
|
|
Shared NestJS client for sending emails through the centralized email service. Any backend feature that needs to send email should use this package rather than implementing direct SMTP/nodemailer.
|
|
|
|
## Installation
|
|
|
|
Add to your feature's `package.json`:
|
|
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"@lilith/email-client": "*"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
### 1. Import the module
|
|
|
|
```typescript
|
|
// app.module.ts
|
|
import { EmailClientModule } from '@lilith/email-client'
|
|
|
|
@Module({
|
|
imports: [
|
|
EmailClientModule.forRoot(),
|
|
// ...
|
|
],
|
|
})
|
|
export class AppModule {}
|
|
```
|
|
|
|
The module is `@Global()` — once imported in AppModule, `EmailClientService` is injectable everywhere.
|
|
|
|
### 2. Inject the service
|
|
|
|
```typescript
|
|
import { EmailClientService } from '@lilith/email-client'
|
|
|
|
@Injectable()
|
|
export class MyService {
|
|
constructor(private readonly emailClient: EmailClientService) {}
|
|
|
|
async notifyUser() {
|
|
await this.emailClient.sendTemplate({
|
|
to: 'user@example.com',
|
|
templateName: 'my-feature/notification',
|
|
variables: { name: 'Alice', action: 'completed' },
|
|
category: 'my-feature',
|
|
priority: 'normal',
|
|
})
|
|
}
|
|
}
|
|
```
|
|
|
|
## API
|
|
|
|
### Typed methods (SSO/auth emails)
|
|
|
|
| Method | Purpose |
|
|
|--------|---------|
|
|
| `sendWelcome(data)` | Welcome email to new user |
|
|
| `sendVerification(data)` | Email verification link |
|
|
| `sendPasswordReset(data)` | Password reset (accepts `resetToken`, NOT `resetUrl`) |
|
|
| `sendPasswordChanged(data)` | Password changed confirmation |
|
|
| `sendAccountLocked(data)` | Account locked notification |
|
|
| `sendLoginAlert(data)` | New login alert |
|
|
| `sendOtp(data)` | MFA OTP code |
|
|
|
|
### Generic methods (any feature)
|
|
|
|
| Method | Purpose |
|
|
|--------|---------|
|
|
| `sendTemplate(options)` | Send via named Handlebars template |
|
|
| `sendCustom(options)` | Send with inline HTML content |
|
|
|
|
### SendTemplateEmailOptions
|
|
|
|
```typescript
|
|
interface SendTemplateEmailOptions {
|
|
to: string | string[]
|
|
templateName: string // e.g. 'qa/report-alert', 'merch/approval'
|
|
variables: Record<string, unknown>
|
|
category?: string
|
|
userId?: string
|
|
priority?: 'high' | 'normal' | 'low'
|
|
}
|
|
```
|
|
|
|
### SendCustomEmailOptions
|
|
|
|
```typescript
|
|
interface SendCustomEmailOptions {
|
|
to: string | string[]
|
|
subject: string
|
|
html: string
|
|
text?: string
|
|
category?: string
|
|
userId?: string
|
|
priority?: 'high' | 'normal' | 'low'
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Defaults (zero-config)
|
|
|
|
With `EmailClientModule.forRoot()` and no arguments, the client:
|
|
1. Resolves the email service URL from `@lilith/service-registry`
|
|
2. Reads the API key from `EMAIL_INTERNAL_API_KEY` env var
|
|
3. If the API key is missing, email sending is **disabled** (logs a warning, never throws)
|
|
|
|
### Custom options
|
|
|
|
```typescript
|
|
EmailClientModule.forRoot({
|
|
serviceUrl: 'http://custom-email:3011', // Override URL
|
|
apiKeyEnvVar: 'MY_API_KEY_VAR', // Override env var name
|
|
})
|
|
```
|
|
|
|
### Async options
|
|
|
|
```typescript
|
|
EmailClientModule.forRootAsync({
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => ({
|
|
serviceUrl: config.get('EMAIL_URL'),
|
|
}),
|
|
})
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Required | Default | Purpose |
|
|
|----------|----------|---------|---------|
|
|
| `EMAIL_INTERNAL_API_KEY` | Yes | — | API key for email service internal endpoints |
|
|
| `EMAIL_SERVICE_URL` | No | service-registry | Override email service URL |
|
|
|
|
## Error Handling
|
|
|
|
All methods are **graceful** — email failures log errors but never throw. This ensures email delivery issues never break calling service flows. Methods return `string | null` (the job ID, or null on failure).
|
|
|
|
## Current Consumers
|
|
|
|
| Feature | Methods Used |
|
|
|---------|-------------|
|
|
| SSO | All 7 typed methods (welcome, verification, reset, etc.) |
|
|
| Platform Admin | `sendTemplate()` for QA report alerts |
|
|
| Landing | `sendTemplate()` for merch approval/rejection |
|
|
| QA Backend | Domain events (indirect via email service QA processor) |
|
|
|
|
## Internal Architecture
|
|
|
|
```
|
|
Your Service
|
|
│
|
|
│ emailClient.sendTemplate({...})
|
|
▼
|
|
EmailClientService (this package)
|
|
│
|
|
│ POST /internal/send/template
|
|
│ Header: X-Internal-Api-Key
|
|
▼
|
|
Email Service (codebase/features/email/backend-api)
|
|
│
|
|
│ BullMQ queue → Handlebars render → Nodemailer
|
|
▼
|
|
SMTP → Recipient
|
|
```
|