@flusys/ng-email 4.1.0 → 5.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 +6 -392
- package/fesm2022/flusys-ng-email-email-config-form.component-M0g9fxU1.mjs +793 -0
- package/fesm2022/flusys-ng-email-email-config-form.component-M0g9fxU1.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-email-config-list.component-oznfQvxo.mjs → flusys-ng-email-email-config-list.component-DorIeenX.mjs} +149 -72
- package/fesm2022/flusys-ng-email-email-config-list.component-DorIeenX.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-template-form.component-B2vIO6ow.mjs → flusys-ng-email-template-form.component-SbeCuxm5.mjs} +19 -24
- package/fesm2022/flusys-ng-email-template-form.component-SbeCuxm5.mjs.map +1 -0
- package/fesm2022/{flusys-ng-email-template-list.component-0PJxS33a.mjs → flusys-ng-email-template-list.component-DrtU0xLq.mjs} +43 -40
- package/fesm2022/flusys-ng-email-template-list.component-DrtU0xLq.mjs.map +1 -0
- package/fesm2022/flusys-ng-email.mjs +89 -185
- package/fesm2022/flusys-ng-email.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-email.d.ts +0 -2
- package/fesm2022/flusys-ng-email-email-config-form.component-Cj2U6Tgf.mjs +0 -718
- package/fesm2022/flusys-ng-email-email-config-form.component-Cj2U6Tgf.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-email-config-list.component-oznfQvxo.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-template-form.component-B2vIO6ow.mjs.map +0 -1
- package/fesm2022/flusys-ng-email-template-list.component-0PJxS33a.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,92 +1,19 @@
|
|
|
1
1
|
# @flusys/ng-email
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Email management UI for FLUSYS — visual block-based template builder, email config CRUD, and programmatic sending via `EmailSendService`.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@flusys/ng-email)
|
|
6
|
-
[](https://www.typescriptlang.org)
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Table of Contents
|
|
13
|
-
|
|
14
|
-
- [Overview](#overview)
|
|
15
|
-
- [Features](#features)
|
|
16
|
-
- [Compatibility](#compatibility)
|
|
17
|
-
- [Installation](#installation)
|
|
18
|
-
- [Quick Start](#quick-start)
|
|
19
|
-
- [Email Schema](#email-schema)
|
|
20
|
-
- [IEmailSchema](#iemailschema)
|
|
21
|
-
- [Block Types](#block-types)
|
|
22
|
-
- [Services](#services)
|
|
23
|
-
- [EmailProviderApiService](#emailproviderapiservice)
|
|
24
|
-
- [EmailTemplateApiService](#emailtemplateapiservice)
|
|
25
|
-
- [EmailSendService](#emailsendservice)
|
|
26
|
-
- [EmailBuilderStateService](#emailbuilderstateservice)
|
|
27
|
-
- [Components](#components)
|
|
28
|
-
- [EmailBuilderComponent](#emailbuildercomponent)
|
|
29
|
-
- [EmailPreviewComponent](#emailpreviewcomponent)
|
|
30
|
-
- [Email Provider Enum](#email-provider-enum)
|
|
31
|
-
- [API Endpoints](#api-endpoints)
|
|
32
|
-
- [Configuration Reference](#configuration-reference)
|
|
33
|
-
- [Troubleshooting](#troubleshooting)
|
|
34
|
-
- [License](#license)
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Overview
|
|
39
|
-
|
|
40
|
-
`@flusys/ng-email` provides a complete email management UI for FLUSYS applications. Administrators can configure SMTP/SendGrid/Mailgun providers, design reusable email templates via a block-based visual builder, and developers can send emails programmatically using `EmailSendService`.
|
|
41
|
-
|
|
42
|
-
Templates are stored as `IEmailSchema` JSON in the backend (`nestjs-email`) and rendered server-side with `{{variable}}` interpolation.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Features
|
|
47
|
-
|
|
48
|
-
- ✅ Email provider configuration UI (SMTP, SendGrid, Mailgun)
|
|
49
|
-
- ✅ Visual block-based email template builder
|
|
50
|
-
- ✅ `{{variable}}` interpolation with XSS protection
|
|
51
|
-
- ✅ Email template preview (desktop + mobile viewport)
|
|
52
|
-
- ✅ `EmailSendService` for programmatic sending from any feature
|
|
53
|
-
- ✅ Template versioning (draft / published)
|
|
54
|
-
- ✅ File/image insertion via `ng-storage` integration
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Compatibility
|
|
59
|
-
|
|
60
|
-
| Package | Version |
|
|
61
|
-
|---------|---------|
|
|
62
|
-
| Angular | 21+ |
|
|
63
|
-
| @flusys/ng-core | 4.x |
|
|
64
|
-
| @flusys/ng-shared | 4.x |
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
65
7
|
|
|
66
8
|
---
|
|
67
9
|
|
|
68
10
|
## Installation
|
|
69
11
|
|
|
70
12
|
```bash
|
|
71
|
-
npm install @flusys/ng-email
|
|
13
|
+
npm install @flusys/ng-email
|
|
72
14
|
```
|
|
73
15
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
## Quick Start
|
|
77
|
-
|
|
78
|
-
### 1. Enable Email in Config
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
// environments/environment.ts
|
|
82
|
-
export const environment = {
|
|
83
|
-
services: {
|
|
84
|
-
email: { enabled: true },
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### 2. Add Email Routes
|
|
16
|
+
## 1. Add Email Routes
|
|
90
17
|
|
|
91
18
|
```typescript
|
|
92
19
|
// app.routes.ts
|
|
@@ -100,322 +27,9 @@ export const routes: Routes = [
|
|
|
100
27
|
];
|
|
101
28
|
```
|
|
102
29
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
import { EmailSendService } from '@flusys/ng-email';
|
|
107
|
-
|
|
108
|
-
@Injectable({ providedIn: 'root' })
|
|
109
|
-
export class OrderService {
|
|
110
|
-
private emailSend = inject(EmailSendService);
|
|
111
|
-
|
|
112
|
-
sendOrderConfirmation(order: Order): Observable<IMessageResponse> {
|
|
113
|
-
return this.emailSend.send({
|
|
114
|
-
templateKey: 'order-confirmation',
|
|
115
|
-
to: order.customerEmail,
|
|
116
|
-
variables: {
|
|
117
|
-
customerName: order.customerName,
|
|
118
|
-
orderNumber: order.id,
|
|
119
|
-
totalAmount: order.total.toFixed(2),
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## Email Schema
|
|
129
|
-
|
|
130
|
-
### IEmailSchema
|
|
131
|
-
|
|
132
|
-
Complete email template definition stored as JSON:
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
interface IEmailSchema {
|
|
136
|
-
id: string;
|
|
137
|
-
name: string;
|
|
138
|
-
key: string; // Unique identifier for programmatic sending
|
|
139
|
-
subject: string; // Supports {{variable}} interpolation
|
|
140
|
-
previewText?: string;
|
|
141
|
-
blocks: IEmailBlock[];
|
|
142
|
-
settings: IEmailSettings;
|
|
143
|
-
isDraft: boolean;
|
|
144
|
-
createdAt: string;
|
|
145
|
-
updatedAt: string;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
interface IEmailSettings {
|
|
149
|
-
backgroundColor: string;
|
|
150
|
-
contentWidth: number; // pixels (default: 600)
|
|
151
|
-
fontFamily: string;
|
|
152
|
-
padding: number; // px
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Block Types
|
|
157
|
-
|
|
158
|
-
Email templates are composed of blocks:
|
|
159
|
-
|
|
160
|
-
| Block Type | Description | Key Properties |
|
|
161
|
-
|------------|-------------|----------------|
|
|
162
|
-
| `header` | Logo + company name header | `logoFileId`, `companyName`, `backgroundColor` |
|
|
163
|
-
| `text` | Rich text paragraph | `content` (HTML), `fontSize`, `color`, `align` |
|
|
164
|
-
| `heading` | H1-H4 heading | `content`, `level`, `color`, `align` |
|
|
165
|
-
| `button` | Call-to-action button | `label`, `url`, `backgroundColor`, `textColor` |
|
|
166
|
-
| `image` | Image block | `fileId`, `altText`, `width`, `link` |
|
|
167
|
-
| `divider` | Horizontal rule | `color`, `thickness` |
|
|
168
|
-
| `spacer` | Vertical whitespace | `height` |
|
|
169
|
-
| `columns` | Two-column layout | `leftBlock`, `rightBlock` |
|
|
170
|
-
| `footer` | Unsubscribe/legal footer | `content`, `unsubscribeUrl` |
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
interface IEmailBlock {
|
|
174
|
-
id: string;
|
|
175
|
-
type: EmailBlockType;
|
|
176
|
-
[key: string]: unknown; // Block-specific properties
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**Variable Interpolation:**
|
|
181
|
-
|
|
182
|
-
Use `{{variableName}}` in any text content:
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
Subject: "Order {{orderNumber}} Confirmed"
|
|
186
|
-
Content: "Hi {{customerName}}, your order totaling ${{totalAmount}} is confirmed."
|
|
187
|
-
```
|
|
30
|
+
Routes included (all protected by `permissionGuard`):
|
|
188
31
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
## Services
|
|
194
|
-
|
|
195
|
-
### EmailProviderApiService
|
|
196
|
-
|
|
197
|
-
Manages email provider configuration (SMTP, SendGrid, Mailgun):
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
import { EmailProviderApiService } from '@flusys/ng-email';
|
|
201
|
-
|
|
202
|
-
@Injectable({ ... })
|
|
203
|
-
export class MyService {
|
|
204
|
-
private providerApi = inject(EmailProviderApiService);
|
|
205
|
-
|
|
206
|
-
getProviders(): Observable<IListResponse<IEmailProvider>> {
|
|
207
|
-
return this.providerApi.getAll({});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
configureSmtp(config: ISmtpConfig): Observable<ISingleResponse<IEmailProvider>> {
|
|
211
|
-
return this.providerApi.insert({
|
|
212
|
-
type: EmailProviderEnum.SMTP,
|
|
213
|
-
...config,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
testProvider(id: string): Observable<IMessageResponse> {
|
|
218
|
-
return this.providerApi.test(id);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### EmailTemplateApiService
|
|
224
|
-
|
|
225
|
-
Manages email template CRUD and publishing:
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
import { EmailTemplateApiService } from '@flusys/ng-email';
|
|
229
|
-
|
|
230
|
-
@Injectable({ ... })
|
|
231
|
-
export class MyService {
|
|
232
|
-
private templateApi = inject(EmailTemplateApiService);
|
|
233
|
-
|
|
234
|
-
getTemplates(): Observable<IListResponse<IEmailTemplate>> {
|
|
235
|
-
return this.templateApi.getAll({ pageSize: 50 });
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
getByKey(key: string): Observable<ISingleResponse<IEmailTemplate>> {
|
|
239
|
-
return this.templateApi.getByKey(key);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
publish(id: string): Observable<IMessageResponse> {
|
|
243
|
-
return this.templateApi.publish(id);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### EmailSendService
|
|
249
|
-
|
|
250
|
-
Programmatic email sending from any feature module:
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
import { EmailSendService } from '@flusys/ng-email';
|
|
254
|
-
|
|
255
|
-
@Injectable({ providedIn: 'root' })
|
|
256
|
-
export class NotificationBridgeService {
|
|
257
|
-
private emailSend = inject(EmailSendService);
|
|
258
|
-
|
|
259
|
-
sendWelcomeEmail(user: IUser): Observable<IMessageResponse> {
|
|
260
|
-
return this.emailSend.send({
|
|
261
|
-
templateKey: 'welcome',
|
|
262
|
-
to: user.email,
|
|
263
|
-
variables: {
|
|
264
|
-
firstName: user.firstName,
|
|
265
|
-
loginUrl: 'https://app.example.com/auth/login',
|
|
266
|
-
},
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
sendPasswordReset(email: string, resetToken: string): Observable<IMessageResponse> {
|
|
271
|
-
return this.emailSend.send({
|
|
272
|
-
templateKey: 'password-reset',
|
|
273
|
-
to: email,
|
|
274
|
-
variables: { resetToken, expiresIn: '24 hours' },
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
**EmailSendService.send() Options:**
|
|
281
|
-
|
|
282
|
-
| Field | Type | Required | Description |
|
|
283
|
-
|-------|------|----------|-------------|
|
|
284
|
-
| `templateKey` | `string` | ✅ | Unique template key |
|
|
285
|
-
| `to` | `string \| string[]` | ✅ | Recipient(s) |
|
|
286
|
-
| `variables` | `Record<string, string \| number>` | — | Template variables |
|
|
287
|
-
| `cc` | `string[]` | — | CC recipients |
|
|
288
|
-
| `bcc` | `string[]` | — | BCC recipients |
|
|
289
|
-
| `replyTo` | `string` | — | Reply-to address |
|
|
290
|
-
| `attachments` | `IEmailAttachment[]` | — | File attachments |
|
|
291
|
-
|
|
292
|
-
### EmailBuilderStateService
|
|
293
|
-
|
|
294
|
-
Component-scoped service managing the visual builder state:
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
// Component-scoped — not provided at root
|
|
298
|
-
@Component({
|
|
299
|
-
providers: [EmailBuilderStateService],
|
|
300
|
-
})
|
|
301
|
-
export class EmailBuilderComponent {
|
|
302
|
-
private state = inject(EmailBuilderStateService);
|
|
303
|
-
|
|
304
|
-
schema = this.state.schema; // Signal<IEmailSchema>
|
|
305
|
-
selectedBlock = this.state.selectedBlock; // Signal<IEmailBlock | null>
|
|
306
|
-
isDirty = this.state.isDirty; // Signal<boolean>
|
|
307
|
-
previewMode = this.state.previewMode; // Signal<'desktop' | 'mobile'>
|
|
308
|
-
}
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## Components
|
|
314
|
-
|
|
315
|
-
### EmailBuilderComponent
|
|
316
|
-
|
|
317
|
-
Visual block-based email template editor:
|
|
318
|
-
|
|
319
|
-
```html
|
|
320
|
-
<flusys-email-builder
|
|
321
|
-
[templateId]="templateId"
|
|
322
|
-
(saved)="onTemplateSaved($event)"
|
|
323
|
-
/>
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
Features:
|
|
327
|
-
- Left panel: Block type palette
|
|
328
|
-
- Center: Email canvas (drag to reorder blocks)
|
|
329
|
-
- Right panel: Selected block properties
|
|
330
|
-
- Top bar: Save draft / Publish / Preview toggle
|
|
331
|
-
|
|
332
|
-
### EmailPreviewComponent
|
|
333
|
-
|
|
334
|
-
Renders an email template with mock variable values:
|
|
335
|
-
|
|
336
|
-
```html
|
|
337
|
-
<flusys-email-preview
|
|
338
|
-
[schema]="emailSchema"
|
|
339
|
-
[variables]="mockVariables"
|
|
340
|
-
[viewport]="'desktop'"
|
|
341
|
-
/>
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
| Input | Type | Description |
|
|
345
|
-
|-------|------|-------------|
|
|
346
|
-
| `schema` | `IEmailSchema` | Template to preview |
|
|
347
|
-
| `variables` | `Record<string, string>` | Mock values for `{{vars}}` |
|
|
348
|
-
| `viewport` | `'desktop' \| 'mobile'` | Preview viewport width |
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
|
|
352
|
-
## Email Provider Enum
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
import { EmailProviderEnum } from '@flusys/ng-email';
|
|
356
|
-
|
|
357
|
-
enum EmailProviderEnum {
|
|
358
|
-
SMTP = 'SMTP',
|
|
359
|
-
SENDGRID = 'SENDGRID',
|
|
360
|
-
MAILGUN = 'MAILGUN',
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## API Endpoints
|
|
367
|
-
|
|
368
|
-
| Method | Endpoint | Description |
|
|
369
|
-
|--------|----------|-------------|
|
|
370
|
-
| POST | `/email/provider/get-all` | List email providers |
|
|
371
|
-
| POST | `/email/provider/get/:id` | Get provider config |
|
|
372
|
-
| POST | `/email/provider/insert` | Add provider |
|
|
373
|
-
| POST | `/email/provider/update` | Update provider |
|
|
374
|
-
| POST | `/email/provider/delete` | Delete provider |
|
|
375
|
-
| POST | `/email/provider/test/:id` | Send test email |
|
|
376
|
-
| POST | `/email/template/get-all` | List templates |
|
|
377
|
-
| POST | `/email/template/get/:id` | Get template |
|
|
378
|
-
| POST | `/email/template/insert` | Create template |
|
|
379
|
-
| POST | `/email/template/update` | Update template |
|
|
380
|
-
| POST | `/email/template/delete` | Delete template |
|
|
381
|
-
| POST | `/email/template/publish/:id` | Publish template |
|
|
382
|
-
| POST | `/email/send` | Send email |
|
|
383
|
-
|
|
384
|
-
---
|
|
385
|
-
|
|
386
|
-
## Configuration Reference
|
|
387
|
-
|
|
388
|
-
| Config Key | Type | Default | Description |
|
|
389
|
-
|------------|------|---------|-------------|
|
|
390
|
-
| `services.email.enabled` | `boolean` | `false` | Enable email module |
|
|
391
|
-
|
|
392
|
-
Email provider credentials (API keys, SMTP host/port) are configured server-side in `nestjs-email`. The Angular client only calls the send API.
|
|
393
|
-
|
|
394
|
-
---
|
|
395
|
-
|
|
396
|
-
## Troubleshooting
|
|
397
|
-
|
|
398
|
-
**`EmailSendService.send()` returns 404**
|
|
399
|
-
|
|
400
|
-
Template with the given `key` doesn't exist or is still in draft. Publish the template first via the builder UI or `templateApi.publish(id)`.
|
|
401
|
-
|
|
402
|
-
**Visual builder blocks not reordering**
|
|
403
|
-
|
|
404
|
-
CDK drag-and-drop requires `@angular/cdk`. Install it and import `DragDropModule`.
|
|
405
|
-
|
|
406
|
-
**Images in email not displaying for recipients**
|
|
407
|
-
|
|
408
|
-
Images are referenced by file ID. The backend resolves these to absolute URLs when rendering. Ensure `ng-storage` is configured and the storage backend is publicly accessible (or uses presigned URLs).
|
|
409
|
-
|
|
410
|
-
**Variables showing as `{{varName}}` in sent emails**
|
|
411
|
-
|
|
412
|
-
The `variables` object key doesn't match the template placeholder. Check for exact case match: `{{customerName}}` requires `{ customerName: '...' }`.
|
|
413
|
-
|
|
414
|
-
**Provider test fails with "Connection refused"**
|
|
415
|
-
|
|
416
|
-
SMTP host/port is incorrect or the email provider's server is blocking the connection. Verify credentials in the Email Providers configuration page.
|
|
417
|
-
|
|
418
|
-
---
|
|
32
|
+
Routes require permissions (`EMAIL_TEMPLATE_PERMISSIONS`, `EMAIL_CONFIG_PERMISSIONS`) from `@flusys/ng-shared` — ensure IAM is configured.
|
|
419
33
|
|
|
420
34
|
## License
|
|
421
35
|
|