@flusys/nestjs-email 1.1.0-beta → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +589 -0
- package/cjs/config/email.constants.js +0 -18
- package/cjs/config/index.js +0 -1
- package/cjs/controllers/email-config.controller.js +46 -4
- package/cjs/controllers/email-send.controller.js +13 -26
- package/cjs/controllers/email-template.controller.js +60 -11
- package/cjs/docs/email-swagger.config.js +18 -80
- package/cjs/dtos/email-config.dto.js +6 -106
- package/cjs/dtos/email-send.dto.js +101 -123
- package/cjs/dtos/email-template.dto.js +41 -103
- package/cjs/entities/email-config-with-company.entity.js +2 -2
- package/cjs/entities/email-config.entity.js +92 -3
- package/cjs/entities/email-template-with-company.entity.js +5 -3
- package/cjs/entities/email-template.entity.js +119 -3
- package/cjs/entities/index.js +34 -19
- package/cjs/index.js +1 -0
- package/cjs/interfaces/email-provider.interface.js +1 -3
- package/cjs/modules/email.module.js +50 -104
- package/cjs/providers/email-factory.service.js +37 -109
- package/cjs/providers/email-provider.registry.js +5 -15
- package/cjs/providers/mailgun-provider.js +54 -58
- package/cjs/providers/sendgrid-provider.js +68 -92
- package/cjs/providers/smtp-provider.js +58 -69
- package/cjs/{config → services}/email-config.service.js +9 -32
- package/cjs/services/email-datasource.provider.js +17 -104
- package/cjs/services/email-provider-config.service.js +28 -58
- package/cjs/services/email-send.service.js +120 -125
- package/cjs/services/email-template.service.js +62 -85
- package/cjs/services/index.js +2 -1
- package/cjs/utils/email-templates.util.js +64 -0
- package/cjs/utils/index.js +18 -0
- package/config/email.constants.d.ts +0 -9
- package/config/index.d.ts +0 -1
- package/controllers/email-send.controller.d.ts +5 -12
- package/controllers/email-template.controller.d.ts +5 -7
- package/dtos/email-config.dto.d.ts +5 -13
- package/dtos/email-send.dto.d.ts +17 -21
- package/dtos/email-template.dto.d.ts +5 -16
- package/entities/email-config-with-company.entity.d.ts +2 -2
- package/entities/email-config.entity.d.ts +10 -2
- package/entities/email-template-with-company.entity.d.ts +2 -2
- package/entities/email-template.entity.d.ts +13 -2
- package/entities/index.d.ts +9 -3
- package/fesm/config/email.constants.js +0 -9
- package/fesm/config/index.js +0 -1
- package/fesm/controllers/email-config.controller.js +49 -7
- package/fesm/controllers/email-send.controller.js +13 -26
- package/fesm/controllers/email-template.controller.js +61 -12
- package/fesm/docs/email-swagger.config.js +21 -86
- package/fesm/dtos/email-config.dto.js +9 -115
- package/fesm/dtos/email-send.dto.js +103 -139
- package/fesm/dtos/email-template.dto.js +43 -111
- package/fesm/entities/email-config-with-company.entity.js +2 -2
- package/fesm/entities/email-config.entity.js +93 -4
- package/fesm/entities/email-template-with-company.entity.js +5 -3
- package/fesm/entities/email-template.entity.js +120 -4
- package/fesm/entities/index.js +22 -16
- package/fesm/index.js +1 -0
- package/fesm/interfaces/email-config.interface.js +1 -3
- package/fesm/interfaces/email-module-options.interface.js +1 -3
- package/fesm/interfaces/email-provider.interface.js +1 -5
- package/fesm/interfaces/email-template.interface.js +1 -3
- package/fesm/modules/email.module.js +52 -106
- package/fesm/providers/email-factory.service.js +38 -69
- package/fesm/providers/email-provider.registry.js +6 -19
- package/fesm/providers/mailgun-provider.js +55 -63
- package/fesm/providers/sendgrid-provider.js +69 -97
- package/fesm/providers/smtp-provider.js +59 -73
- package/fesm/{config → services}/email-config.service.js +9 -32
- package/fesm/services/email-datasource.provider.js +18 -64
- package/fesm/services/email-provider-config.service.js +26 -56
- package/fesm/services/email-send.service.js +118 -123
- package/fesm/services/email-template.service.js +60 -83
- package/fesm/services/index.js +2 -1
- package/fesm/utils/email-templates.util.js +47 -0
- package/fesm/utils/index.js +1 -0
- package/index.d.ts +1 -0
- package/interfaces/email-config.interface.d.ts +6 -0
- package/interfaces/email-module-options.interface.d.ts +0 -5
- package/modules/email.module.d.ts +1 -2
- package/package.json +4 -4
- package/providers/email-factory.service.d.ts +4 -7
- package/providers/mailgun-provider.d.ts +6 -2
- package/providers/sendgrid-provider.d.ts +6 -2
- package/providers/smtp-provider.d.ts +7 -2
- package/services/email-config.service.d.ts +12 -0
- package/services/email-datasource.provider.d.ts +3 -6
- package/services/email-provider-config.service.d.ts +3 -3
- package/services/email-send.service.d.ts +11 -3
- package/services/email-template.service.d.ts +5 -4
- package/services/index.d.ts +2 -1
- package/utils/email-templates.util.d.ts +2 -0
- package/utils/index.d.ts +1 -0
- package/cjs/entities/email-config-base.entity.js +0 -111
- package/cjs/entities/email-template-base.entity.js +0 -134
- package/config/email-config.service.d.ts +0 -13
- package/entities/email-config-base.entity.d.ts +0 -11
- package/entities/email-template-base.entity.d.ts +0 -14
- package/fesm/entities/email-config-base.entity.js +0 -101
- package/fesm/entities/email-template-base.entity.js +0 -124
package/README.md
ADDED
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
# Email Package Guide
|
|
2
|
+
|
|
3
|
+
> **Package:** `@flusys/nestjs-email`
|
|
4
|
+
> **Type:** Email sending with templates, multiple providers, and multi-tenant support
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
- [Overview](#overview)
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Constants](#constants)
|
|
11
|
+
- [Module Setup](#module-setup)
|
|
12
|
+
- [Entities](#entities)
|
|
13
|
+
- [Email Providers](#email-providers)
|
|
14
|
+
- [Email Configuration](#email-configuration)
|
|
15
|
+
- [Email Templates](#email-templates)
|
|
16
|
+
- [Email Sending](#email-sending)
|
|
17
|
+
- [API Endpoints](#api-endpoints)
|
|
18
|
+
- [Multi-Tenant Support](#multi-tenant-support)
|
|
19
|
+
- [Best Practices](#best-practices)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
`@flusys/nestjs-email` provides:
|
|
26
|
+
|
|
27
|
+
- **Multiple Providers** - SMTP, SendGrid, Mailgun with dynamic registration
|
|
28
|
+
- **Email Templates** - Variable interpolation with `{{variableName}}` syntax
|
|
29
|
+
- **HTML/Plain Text** - Support via `isHtml` toggle
|
|
30
|
+
- **Multi-Tenant Support** - Company-scoped configurations and templates
|
|
31
|
+
- **Attachments** - File attachment support
|
|
32
|
+
|
|
33
|
+
### Package Hierarchy
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
@flusys/nestjs-core ← Foundation
|
|
37
|
+
↓
|
|
38
|
+
@flusys/nestjs-shared ← Shared utilities
|
|
39
|
+
↓
|
|
40
|
+
@flusys/nestjs-email ← Email system (THIS PACKAGE)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @flusys/nestjs-email
|
|
49
|
+
|
|
50
|
+
# Provider-specific packages (install as needed)
|
|
51
|
+
npm install nodemailer # For SMTP
|
|
52
|
+
npm install @sendgrid/mail # For SendGrid
|
|
53
|
+
npm install mailgun.js form-data # For Mailgun
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Constants
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Injection Token
|
|
62
|
+
export const EMAIL_MODULE_OPTIONS = 'EMAIL_MODULE_OPTIONS';
|
|
63
|
+
|
|
64
|
+
// Default Configuration
|
|
65
|
+
export const DEFAULT_FROM_NAME = 'FLUSYS';
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Module Setup
|
|
71
|
+
|
|
72
|
+
### Basic Setup
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { EmailModule } from '@flusys/nestjs-email';
|
|
76
|
+
|
|
77
|
+
@Module({
|
|
78
|
+
imports: [
|
|
79
|
+
EmailModule.forRoot({
|
|
80
|
+
global: true,
|
|
81
|
+
includeController: true,
|
|
82
|
+
bootstrapAppConfig: {
|
|
83
|
+
databaseMode: 'single',
|
|
84
|
+
enableCompanyFeature: false,
|
|
85
|
+
},
|
|
86
|
+
config: {
|
|
87
|
+
defaultDatabaseConfig: {
|
|
88
|
+
type: 'postgres',
|
|
89
|
+
host: 'localhost',
|
|
90
|
+
port: 5432,
|
|
91
|
+
username: 'user',
|
|
92
|
+
password: 'password',
|
|
93
|
+
database: 'myapp',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
],
|
|
98
|
+
})
|
|
99
|
+
export class AppModule {}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### With Company Feature
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
EmailModule.forRoot({
|
|
106
|
+
global: true,
|
|
107
|
+
includeController: true,
|
|
108
|
+
bootstrapAppConfig: {
|
|
109
|
+
databaseMode: 'single',
|
|
110
|
+
enableCompanyFeature: true,
|
|
111
|
+
},
|
|
112
|
+
config: {
|
|
113
|
+
defaultDatabaseConfig: { ... },
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Async Configuration
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
EmailModule.forRootAsync({
|
|
122
|
+
global: true,
|
|
123
|
+
includeController: true,
|
|
124
|
+
bootstrapAppConfig: {
|
|
125
|
+
databaseMode: 'single',
|
|
126
|
+
enableCompanyFeature: true,
|
|
127
|
+
},
|
|
128
|
+
imports: [ConfigModule],
|
|
129
|
+
useFactory: async (configService: ConfigService) => ({
|
|
130
|
+
defaultDatabaseConfig: configService.getDatabaseConfig(),
|
|
131
|
+
}),
|
|
132
|
+
inject: [ConfigService],
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Entities
|
|
139
|
+
|
|
140
|
+
### Entity Groups
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Core entities (no company feature)
|
|
144
|
+
export const EmailCoreEntities = [EmailConfig, EmailTemplate];
|
|
145
|
+
|
|
146
|
+
// Company-specific entities
|
|
147
|
+
export const EmailCompanyEntities = [EmailConfigWithCompany, EmailTemplateWithCompany];
|
|
148
|
+
|
|
149
|
+
// Helper function
|
|
150
|
+
export function getEmailEntitiesByConfig(enableCompanyFeature: boolean): any[] {
|
|
151
|
+
return enableCompanyFeature ? EmailCompanyEntities : EmailCoreEntities;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Base type aliases for backwards compatibility
|
|
155
|
+
export { EmailConfig as EmailConfigBase } from './email-config.entity';
|
|
156
|
+
export { EmailTemplate as EmailTemplateBase } from './email-template.entity';
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Email Providers
|
|
162
|
+
|
|
163
|
+
### Provider Types
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
enum EmailProviderTypeEnum {
|
|
167
|
+
SMTP = 'smtp',
|
|
168
|
+
SENDGRID = 'sendgrid',
|
|
169
|
+
MAILGUN = 'mailgun',
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Providers are auto-registered at module load via `EmailProviderRegistry`.
|
|
174
|
+
|
|
175
|
+
### SMTP Configuration
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
{
|
|
179
|
+
provider: 'smtp',
|
|
180
|
+
config: {
|
|
181
|
+
host: 'smtp.gmail.com',
|
|
182
|
+
port: 587,
|
|
183
|
+
secure: false,
|
|
184
|
+
auth: { user: 'your@gmail.com', pass: 'app-password' },
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### SendGrid Configuration
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// Requires: npm install @sendgrid/mail
|
|
193
|
+
{
|
|
194
|
+
provider: 'sendgrid',
|
|
195
|
+
config: { apiKey: 'SG.xxxxxxxxxxxx' }
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Mailgun Configuration
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Requires: npm install mailgun.js form-data
|
|
203
|
+
{
|
|
204
|
+
provider: 'mailgun',
|
|
205
|
+
config: {
|
|
206
|
+
apiKey: 'key-xxxxxxxx',
|
|
207
|
+
domain: 'mail.yourdomain.com',
|
|
208
|
+
region: 'us', // 'us' or 'eu'
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Provider Interface
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
interface IEmailProvider {
|
|
217
|
+
sendEmail(options: IEmailSendOptions): Promise<IEmailSendResult>;
|
|
218
|
+
sendBulkEmails(options: IEmailSendOptions[]): Promise<IEmailSendResult[]>;
|
|
219
|
+
healthCheck(): Promise<boolean>;
|
|
220
|
+
initialize?(config: any): Promise<void>;
|
|
221
|
+
close?(): Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
interface IEmailSendOptions {
|
|
225
|
+
to: string | string[];
|
|
226
|
+
cc?: string | string[];
|
|
227
|
+
bcc?: string | string[];
|
|
228
|
+
subject: string;
|
|
229
|
+
html?: string;
|
|
230
|
+
text?: string;
|
|
231
|
+
from?: string;
|
|
232
|
+
fromName?: string;
|
|
233
|
+
replyTo?: string;
|
|
234
|
+
attachments?: IEmailAttachment[];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
interface IEmailSendResult {
|
|
238
|
+
success: boolean;
|
|
239
|
+
messageId?: string;
|
|
240
|
+
error?: string;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Email Configuration
|
|
247
|
+
|
|
248
|
+
### EmailConfig Entity
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
interface IEmailConfig {
|
|
252
|
+
id: string;
|
|
253
|
+
name: string; // e.g., 'default', 'marketing'
|
|
254
|
+
provider: EmailProviderTypeEnum;
|
|
255
|
+
config: Record<string, any>; // Provider-specific config
|
|
256
|
+
fromEmail: string | null;
|
|
257
|
+
fromName: string | null;
|
|
258
|
+
isActive: boolean;
|
|
259
|
+
isDefault: boolean; // Auto-selected when emailConfigId not provided
|
|
260
|
+
companyId?: string | null; // When company feature enabled
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Default Configuration Resolution
|
|
265
|
+
|
|
266
|
+
When `emailConfigId` is not provided:
|
|
267
|
+
1. Find config with `isDefault: true` and `isActive: true`
|
|
268
|
+
2. Fall back to oldest active config
|
|
269
|
+
|
|
270
|
+
### Creating Configurations
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import { EmailProviderConfigService } from '@flusys/nestjs-email';
|
|
274
|
+
|
|
275
|
+
await emailConfigService.insert({
|
|
276
|
+
name: 'default',
|
|
277
|
+
provider: 'smtp',
|
|
278
|
+
fromEmail: 'noreply@example.com',
|
|
279
|
+
fromName: 'My App',
|
|
280
|
+
config: {
|
|
281
|
+
host: 'smtp.gmail.com',
|
|
282
|
+
port: 587,
|
|
283
|
+
auth: { user: '...', pass: '...' },
|
|
284
|
+
},
|
|
285
|
+
isActive: true,
|
|
286
|
+
isDefault: true,
|
|
287
|
+
}, user);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Email Templates
|
|
293
|
+
|
|
294
|
+
### EmailTemplate Entity
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
interface IEmailTemplate {
|
|
298
|
+
id: string;
|
|
299
|
+
name: string;
|
|
300
|
+
slug: string; // URL-friendly identifier
|
|
301
|
+
description: string | null;
|
|
302
|
+
subject: string; // Supports {{variables}}
|
|
303
|
+
schema: Record<string, unknown>;
|
|
304
|
+
htmlContent: string;
|
|
305
|
+
textContent: string | null;
|
|
306
|
+
schemaVersion: number; // Auto-incremented on schema change
|
|
307
|
+
isActive: boolean;
|
|
308
|
+
isHtml: boolean; // true=HTML, false=plain text
|
|
309
|
+
metadata: Record<string, unknown> | null;
|
|
310
|
+
companyId?: string | null;
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Creating Templates
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
import { EmailTemplateService } from '@flusys/nestjs-email';
|
|
318
|
+
|
|
319
|
+
await templateService.insert({
|
|
320
|
+
name: 'Welcome Email',
|
|
321
|
+
slug: 'welcome-email',
|
|
322
|
+
subject: 'Welcome to {{appName}}, {{userName}}!',
|
|
323
|
+
isHtml: true,
|
|
324
|
+
htmlContent: `
|
|
325
|
+
<h1>Welcome, {{userName}}!</h1>
|
|
326
|
+
<p>Thank you for joining {{appName}}.</p>
|
|
327
|
+
<a href="{{verificationLink}}">Verify Email</a>
|
|
328
|
+
`,
|
|
329
|
+
textContent: 'Welcome! Verify: {{verificationLink}}',
|
|
330
|
+
schema: {},
|
|
331
|
+
isActive: true,
|
|
332
|
+
}, user);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Variable Interpolation
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// Template: "Hello {{userName}}, your order #{{orderId}} is {{status}}."
|
|
339
|
+
// Variables: { userName: "John", orderId: "12345", status: "shipped" }
|
|
340
|
+
// Result: "Hello John, your order #12345 is shipped."
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### isHtml Toggle
|
|
344
|
+
|
|
345
|
+
- **`isHtml: true`** - Sends `htmlContent` as HTML, `textContent` as fallback
|
|
346
|
+
- **`isHtml: false`** - Sends `textContent` only (no HTML)
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Email Sending
|
|
351
|
+
|
|
352
|
+
### EmailSendService
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
import { EmailSendService } from '@flusys/nestjs-email';
|
|
356
|
+
|
|
357
|
+
// Send direct email
|
|
358
|
+
const result = await emailSendService.sendEmail({
|
|
359
|
+
to: 'user@example.com',
|
|
360
|
+
subject: 'Hello!',
|
|
361
|
+
html: '<h1>Hello World</h1>',
|
|
362
|
+
text: 'Hello World',
|
|
363
|
+
emailConfigId: 'config-uuid', // Optional - uses default
|
|
364
|
+
}, user);
|
|
365
|
+
|
|
366
|
+
// Send using template
|
|
367
|
+
const result = await emailSendService.sendTemplateEmail({
|
|
368
|
+
templateSlug: 'welcome-email',
|
|
369
|
+
to: 'user@example.com',
|
|
370
|
+
variables: {
|
|
371
|
+
userName: 'John',
|
|
372
|
+
appName: 'My App',
|
|
373
|
+
},
|
|
374
|
+
}, user);
|
|
375
|
+
|
|
376
|
+
// Send with attachments
|
|
377
|
+
const result = await emailSendService.sendEmail({
|
|
378
|
+
to: 'user@example.com',
|
|
379
|
+
subject: 'Your Invoice',
|
|
380
|
+
html: '<p>Invoice attached.</p>',
|
|
381
|
+
attachments: [{
|
|
382
|
+
filename: 'invoice.pdf',
|
|
383
|
+
content: base64Content,
|
|
384
|
+
contentType: 'application/pdf',
|
|
385
|
+
}],
|
|
386
|
+
}, user);
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## API Endpoints
|
|
392
|
+
|
|
393
|
+
All endpoints use POST (RPC pattern) and require JWT authentication.
|
|
394
|
+
|
|
395
|
+
### Email Configuration
|
|
396
|
+
|
|
397
|
+
| Endpoint | Description |
|
|
398
|
+
|----------|-------------|
|
|
399
|
+
| `POST /email/email-config/insert` | Create configuration |
|
|
400
|
+
| `POST /email/email-config/get/:id` | Get by ID |
|
|
401
|
+
| `POST /email/email-config/get-all` | Get all (paginated) |
|
|
402
|
+
| `POST /email/email-config/update` | Update |
|
|
403
|
+
| `POST /email/email-config/delete` | Delete |
|
|
404
|
+
|
|
405
|
+
### Email Templates
|
|
406
|
+
|
|
407
|
+
| Endpoint | Description |
|
|
408
|
+
|----------|-------------|
|
|
409
|
+
| `POST /email/email-template/insert` | Create template |
|
|
410
|
+
| `POST /email/email-template/get/:id` | Get by ID |
|
|
411
|
+
| `POST /email/email-template/get-all` | Get all (paginated) |
|
|
412
|
+
| `POST /email/email-template/get-by-slug` | Get by slug |
|
|
413
|
+
| `POST /email/email-template/update` | Update |
|
|
414
|
+
| `POST /email/email-template/delete` | Delete |
|
|
415
|
+
|
|
416
|
+
### Email Sending
|
|
417
|
+
|
|
418
|
+
| Endpoint | Description |
|
|
419
|
+
|----------|-------------|
|
|
420
|
+
| `POST /email/send/direct` | Send direct email |
|
|
421
|
+
| `POST /email/send/template` | Send using template |
|
|
422
|
+
| `POST /email/send/test` | Test configuration |
|
|
423
|
+
|
|
424
|
+
### Example Requests
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
# Send template email
|
|
428
|
+
curl -X POST http://localhost:3000/email/send/template \
|
|
429
|
+
-H "Authorization: Bearer <token>" \
|
|
430
|
+
-H "Content-Type: application/json" \
|
|
431
|
+
-d '{
|
|
432
|
+
"templateSlug": "welcome-email",
|
|
433
|
+
"to": "user@example.com",
|
|
434
|
+
"variables": { "userName": "John" }
|
|
435
|
+
}'
|
|
436
|
+
|
|
437
|
+
# Test configuration
|
|
438
|
+
curl -X POST http://localhost:3000/email/send/test \
|
|
439
|
+
-H "Authorization: Bearer <token>" \
|
|
440
|
+
-d '{ "emailConfigId": "uuid", "recipient": "test@example.com" }'
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Multi-Tenant Support
|
|
446
|
+
|
|
447
|
+
### Company Isolation
|
|
448
|
+
|
|
449
|
+
When `enableCompanyFeature: true`:
|
|
450
|
+
- Email configs are company-scoped
|
|
451
|
+
- Templates are company-scoped
|
|
452
|
+
- Users can only access their company's resources
|
|
453
|
+
|
|
454
|
+
### Company Filtering
|
|
455
|
+
|
|
456
|
+
Services automatically filter by `companyId`:
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
// In EmailTemplateService
|
|
460
|
+
if (this.emailConfig.isCompanyFeatureEnabled() && user?.companyId) {
|
|
461
|
+
query.andWhere('emailTemplate.companyId = :companyId', {
|
|
462
|
+
companyId: user.companyId,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Dynamic Entity Selection
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
protected resolveEntity(): EntityTarget<EmailTemplateBase> {
|
|
471
|
+
return this.emailConfig.isCompanyFeatureEnabled()
|
|
472
|
+
? EmailTemplateWithCompany
|
|
473
|
+
: EmailTemplate;
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Best Practices
|
|
480
|
+
|
|
481
|
+
### 1. Use Template Slugs
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// Use slug for stable references
|
|
485
|
+
await emailSendService.sendTemplateEmail({
|
|
486
|
+
templateSlug: 'welcome-email', // Stable
|
|
487
|
+
...
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// Avoid hardcoded IDs
|
|
491
|
+
templateId: 'f47ac10b-58cc-4372-a567-...' // May change
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### 2. Provide Both HTML and Text
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
await templateService.insert({
|
|
498
|
+
isHtml: true,
|
|
499
|
+
htmlContent: '<h1>Thank you!</h1>',
|
|
500
|
+
textContent: 'Thank you!', // For clients that don't render HTML
|
|
501
|
+
});
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### 3. Test Before Production
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
const result = await emailSendService.sendTestEmail(
|
|
508
|
+
configId,
|
|
509
|
+
'admin@example.com',
|
|
510
|
+
user,
|
|
511
|
+
);
|
|
512
|
+
if (!result.success) throw new Error(result.error);
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### 4. Use Variables for Personalization
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
// Template
|
|
519
|
+
subject: 'Hello {{userName}}!'
|
|
520
|
+
|
|
521
|
+
// Sending
|
|
522
|
+
variables: { userName: 'John' }
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
## API Reference
|
|
528
|
+
|
|
529
|
+
### Main Exports
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
// Module
|
|
533
|
+
import { EmailModule } from '@flusys/nestjs-email';
|
|
534
|
+
|
|
535
|
+
// Services
|
|
536
|
+
import {
|
|
537
|
+
EmailProviderConfigService,
|
|
538
|
+
EmailTemplateService,
|
|
539
|
+
EmailSendService,
|
|
540
|
+
EmailDataSourceProvider,
|
|
541
|
+
} from '@flusys/nestjs-email/services';
|
|
542
|
+
|
|
543
|
+
// Entities
|
|
544
|
+
import {
|
|
545
|
+
EmailConfig,
|
|
546
|
+
EmailConfigBase,
|
|
547
|
+
EmailConfigWithCompany,
|
|
548
|
+
EmailTemplate,
|
|
549
|
+
EmailTemplateBase,
|
|
550
|
+
EmailTemplateWithCompany,
|
|
551
|
+
} from '@flusys/nestjs-email/entities';
|
|
552
|
+
|
|
553
|
+
// DTOs
|
|
554
|
+
import {
|
|
555
|
+
CreateEmailConfigDto,
|
|
556
|
+
UpdateEmailConfigDto,
|
|
557
|
+
EmailConfigResponseDto,
|
|
558
|
+
CreateEmailTemplateDto,
|
|
559
|
+
UpdateEmailTemplateDto,
|
|
560
|
+
EmailTemplateResponseDto,
|
|
561
|
+
SendEmailDto,
|
|
562
|
+
SendTemplateEmailDto,
|
|
563
|
+
TestEmailDto,
|
|
564
|
+
EmailSendResultDto,
|
|
565
|
+
} from '@flusys/nestjs-email/dtos';
|
|
566
|
+
|
|
567
|
+
// Interfaces
|
|
568
|
+
import {
|
|
569
|
+
IEmailProvider,
|
|
570
|
+
IEmailSendOptions,
|
|
571
|
+
IEmailSendResult,
|
|
572
|
+
IEmailConfig,
|
|
573
|
+
IEmailTemplate,
|
|
574
|
+
EmailModuleOptions,
|
|
575
|
+
} from '@flusys/nestjs-email/interfaces';
|
|
576
|
+
|
|
577
|
+
// Providers
|
|
578
|
+
import {
|
|
579
|
+
EmailProviderRegistry,
|
|
580
|
+
EmailFactoryService,
|
|
581
|
+
SmtpProvider,
|
|
582
|
+
SendGridProvider,
|
|
583
|
+
MailgunProvider,
|
|
584
|
+
} from '@flusys/nestjs-email/providers';
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
**Last Updated:** 2026-02-21
|
|
@@ -14,27 +14,9 @@ _export(exports, {
|
|
|
14
14
|
get DEFAULT_FROM_NAME () {
|
|
15
15
|
return DEFAULT_FROM_NAME;
|
|
16
16
|
},
|
|
17
|
-
get EMAIL_CONFIG_SERVICE () {
|
|
18
|
-
return EMAIL_CONFIG_SERVICE;
|
|
19
|
-
},
|
|
20
|
-
get EMAIL_DATA_SOURCE_PROVIDER () {
|
|
21
|
-
return EMAIL_DATA_SOURCE_PROVIDER;
|
|
22
|
-
},
|
|
23
17
|
get EMAIL_MODULE_OPTIONS () {
|
|
24
18
|
return EMAIL_MODULE_OPTIONS;
|
|
25
|
-
},
|
|
26
|
-
get EMAIL_VALIDATION_MESSAGES () {
|
|
27
|
-
return EMAIL_VALIDATION_MESSAGES;
|
|
28
19
|
}
|
|
29
20
|
});
|
|
30
21
|
const EMAIL_MODULE_OPTIONS = 'EMAIL_MODULE_OPTIONS';
|
|
31
|
-
const EMAIL_CONFIG_SERVICE = 'EMAIL_CONFIG_SERVICE';
|
|
32
|
-
const EMAIL_DATA_SOURCE_PROVIDER = 'EMAIL_DATA_SOURCE_PROVIDER';
|
|
33
22
|
const DEFAULT_FROM_NAME = 'FLUSYS';
|
|
34
|
-
const EMAIL_VALIDATION_MESSAGES = {
|
|
35
|
-
INVALID_RECIPIENT: 'Invalid email recipient',
|
|
36
|
-
TEMPLATE_NOT_FOUND: 'Email template not found',
|
|
37
|
-
CONFIG_NOT_FOUND: 'Email configuration not found',
|
|
38
|
-
PROVIDER_NOT_AVAILABLE: 'Email provider not available',
|
|
39
|
-
SEND_FAILED: 'Failed to send email'
|
|
40
|
-
};
|
package/cjs/config/index.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
_export_star(require("./email.constants"), exports);
|
|
6
|
-
_export_star(require("./email-config.service"), exports);
|
|
7
6
|
function _export_star(from, to) {
|
|
8
7
|
Object.keys(from).forEach(function(k) {
|
|
9
8
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "EmailConfigController", {
|
|
|
8
8
|
return EmailConfigController;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _guards = require("@flusys/nestjs-shared/guards");
|
|
12
11
|
const _classes = require("@flusys/nestjs-shared/classes");
|
|
13
12
|
const _common = require("@nestjs/common");
|
|
14
13
|
const _swagger = require("@nestjs/swagger");
|
|
@@ -41,16 +40,59 @@ function _ts_param(paramIndex, decorator) {
|
|
|
41
40
|
decorator(target, key, paramIndex);
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
|
-
let EmailConfigController = class EmailConfigController extends (0, _classes.createApiController)(_dtos.CreateEmailConfigDto, _dtos.UpdateEmailConfigDto, _dtos.EmailConfigResponseDto
|
|
43
|
+
let EmailConfigController = class EmailConfigController extends (0, _classes.createApiController)(_dtos.CreateEmailConfigDto, _dtos.UpdateEmailConfigDto, _dtos.EmailConfigResponseDto, {
|
|
44
|
+
security: {
|
|
45
|
+
insert: {
|
|
46
|
+
level: 'permission',
|
|
47
|
+
permissions: [
|
|
48
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.CREATE
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
insertMany: {
|
|
52
|
+
level: 'permission',
|
|
53
|
+
permissions: [
|
|
54
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.CREATE
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
getById: {
|
|
58
|
+
level: 'permission',
|
|
59
|
+
permissions: [
|
|
60
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.READ
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
getAll: {
|
|
64
|
+
level: 'permission',
|
|
65
|
+
permissions: [
|
|
66
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.READ
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
update: {
|
|
70
|
+
level: 'permission',
|
|
71
|
+
permissions: [
|
|
72
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.UPDATE
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
updateMany: {
|
|
76
|
+
level: 'permission',
|
|
77
|
+
permissions: [
|
|
78
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.UPDATE
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
delete: {
|
|
82
|
+
level: 'permission',
|
|
83
|
+
permissions: [
|
|
84
|
+
_classes.EMAIL_CONFIG_PERMISSIONS.DELETE
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}) {
|
|
45
89
|
constructor(emailConfigService){
|
|
46
90
|
super(emailConfigService), _define_property(this, "emailConfigService", void 0), this.emailConfigService = emailConfigService;
|
|
47
91
|
}
|
|
48
92
|
};
|
|
49
93
|
EmailConfigController = _ts_decorate([
|
|
50
94
|
(0, _swagger.ApiTags)('Email Config'),
|
|
51
|
-
(0, _swagger.ApiBearerAuth)(),
|
|
52
95
|
(0, _common.Controller)('email/email-config'),
|
|
53
|
-
(0, _common.UseGuards)(_guards.JwtAuthGuard),
|
|
54
96
|
_ts_param(0, (0, _common.Inject)(_services.EmailProviderConfigService)),
|
|
55
97
|
_ts_metadata("design:type", Function),
|
|
56
98
|
_ts_metadata("design:paramtypes", [
|