@venturialstd/email 0.0.1

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.
Files changed (64) hide show
  1. package/README.md +315 -0
  2. package/data/README.md +102 -0
  3. package/data/default-templates.json +34 -0
  4. package/dist/constants/email.constant.d.ts +9 -0
  5. package/dist/constants/email.constant.d.ts.map +1 -0
  6. package/dist/constants/email.constant.js +13 -0
  7. package/dist/constants/email.constant.js.map +1 -0
  8. package/dist/constants/email.settings.constant.d.ts +10 -0
  9. package/dist/constants/email.settings.constant.d.ts.map +1 -0
  10. package/dist/constants/email.settings.constant.js +13 -0
  11. package/dist/constants/email.settings.constant.js.map +1 -0
  12. package/dist/constants/index.d.ts +3 -0
  13. package/dist/constants/index.d.ts.map +1 -0
  14. package/dist/constants/index.js +19 -0
  15. package/dist/constants/index.js.map +1 -0
  16. package/dist/email.module.d.ts +3 -0
  17. package/dist/email.module.d.ts.map +1 -0
  18. package/dist/email.module.js +75 -0
  19. package/dist/email.module.js.map +1 -0
  20. package/dist/entities/email-log.entity.d.ts +24 -0
  21. package/dist/entities/email-log.entity.d.ts.map +1 -0
  22. package/dist/entities/email-log.entity.js +110 -0
  23. package/dist/entities/email-log.entity.js.map +1 -0
  24. package/dist/entities/email-template.entity.d.ts +20 -0
  25. package/dist/entities/email-template.entity.d.ts.map +1 -0
  26. package/dist/entities/email-template.entity.js +90 -0
  27. package/dist/entities/email-template.entity.js.map +1 -0
  28. package/dist/entities/index.d.ts +3 -0
  29. package/dist/entities/index.d.ts.map +1 -0
  30. package/dist/entities/index.js +19 -0
  31. package/dist/entities/index.js.map +1 -0
  32. package/dist/index.d.ts +7 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +23 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/services/email-log.service.d.ts +8 -0
  37. package/dist/services/email-log.service.d.ts.map +1 -0
  38. package/dist/services/email-log.service.js +34 -0
  39. package/dist/services/email-log.service.js.map +1 -0
  40. package/dist/services/email-template.service.d.ts +46 -0
  41. package/dist/services/email-template.service.d.ts.map +1 -0
  42. package/dist/services/email-template.service.js +198 -0
  43. package/dist/services/email-template.service.js.map +1 -0
  44. package/dist/services/email.service.d.ts +75 -0
  45. package/dist/services/email.service.d.ts.map +1 -0
  46. package/dist/services/email.service.js +406 -0
  47. package/dist/services/email.service.js.map +1 -0
  48. package/dist/services/index.d.ts +4 -0
  49. package/dist/services/index.d.ts.map +1 -0
  50. package/dist/services/index.js +20 -0
  51. package/dist/services/index.js.map +1 -0
  52. package/dist/settings/email.settings.d.ts +3 -0
  53. package/dist/settings/email.settings.d.ts.map +1 -0
  54. package/dist/settings/email.settings.js +92 -0
  55. package/dist/settings/email.settings.js.map +1 -0
  56. package/dist/types/email.config.type.d.ts +33 -0
  57. package/dist/types/email.config.type.d.ts.map +1 -0
  58. package/dist/types/email.config.type.js +3 -0
  59. package/dist/types/email.config.type.js.map +1 -0
  60. package/dist/types/index.d.ts +2 -0
  61. package/dist/types/index.d.ts.map +1 -0
  62. package/dist/types/index.js +18 -0
  63. package/dist/types/index.js.map +1 -0
  64. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,315 @@
1
+ # @venturialstd/email
2
+
3
+ Email Module with Multiple Transporter Support for Venturial Standard Backend.
4
+
5
+ ## Features
6
+
7
+ - 📧 Multiple transporter support (SMTP, and extensible for others)
8
+ - 🔧 Configuration via code or settings service
9
+ - 🎨 **Handlebars template support** - Beautiful, dynamic email templates
10
+ - 📊 **Database template management** - Store and manage templates in database
11
+ - 📝 HTML and plain text emails
12
+ - 🔄 Attachment support
13
+ - 📊 **Email logging and tracking** - All sent emails are logged with status
14
+ - 🚀 Built on top of @nestjs-modules/mailer
15
+
16
+ ## Quick Links
17
+
18
+ - [Database Template Management](./DATABASE_TEMPLATES.md) - Store templates in database
19
+ - [Handlebars Templates Guide](./HANDLEBARS_TEMPLATES.md) - Complete guide to using templates
20
+ - [Email Logging Documentation](./EMAIL_LOGGING.md) - Email tracking and monitoring
21
+ - [Usage Examples](./USAGE.md) - Comprehensive usage examples
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @venturialstd/email
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Import the Module
32
+
33
+ ```typescript
34
+ import { EmailModule } from '@venturialstd/email';
35
+
36
+ @Module({
37
+ imports: [
38
+ EmailModule,
39
+ // ... other modules
40
+ ],
41
+ })
42
+ export class AppModule {}
43
+ ```
44
+
45
+ ### Send Emails
46
+
47
+ ```typescript
48
+ import { EmailService, EmailConfig } from '@venturialstd/email';
49
+
50
+ @Injectable()
51
+ export class MyService {
52
+ constructor(private readonly emailService: EmailService) {}
53
+
54
+ async sendWelcomeEmail() {
55
+ const config: EmailConfig = {
56
+ transporter: 'SMTP',
57
+ smtp: {
58
+ host: 'smtp.example.com',
59
+ port: 587,
60
+ secure: false,
61
+ auth: {
62
+ user: 'user@example.com',
63
+ pass: 'password',
64
+ },
65
+ },
66
+ };
67
+
68
+ await this.emailService.sendEmail(config, {
69
+ to: 'recipient@example.com',
70
+ subject: 'Welcome!',
71
+ html: '<h1>Welcome to our platform!</h1>',
72
+ });
73
+ }
74
+ }
75
+ ```
76
+
77
+ ### Send Emails with Handlebars Templates
78
+
79
+ The module includes pre-built Handlebars templates and helper methods:
80
+
81
+ ```typescript
82
+ // Welcome email
83
+ await emailService.sendWelcomeEmail(null, {
84
+ to: 'user@example.com',
85
+ name: 'John Doe',
86
+ message: 'Thank you for joining our platform!',
87
+ actionUrl: 'https://app.example.com/onboarding',
88
+ });
89
+
90
+ // Password reset email
91
+ await emailService.sendPasswordResetEmail(null, {
92
+ to: 'user@example.com',
93
+ name: 'John Doe',
94
+ resetUrl: 'https://app.example.com/reset?token=abc123',
95
+ expirationTime: 30,
96
+ });
97
+
98
+ // Notification email
99
+ await emailService.sendNotificationEmail(null, {
100
+ to: 'user@example.com',
101
+ name: 'John Doe',
102
+ title: 'Order Confirmation',
103
+ notificationTitle: 'Your order has been confirmed!',
104
+ message: 'Order #12345 is being processed.',
105
+ });
106
+
107
+ // Custom template
108
+ await emailService.sendEmailWithTemplate(null, {
109
+ to: 'user@example.com',
110
+ subject: 'Custom Email',
111
+ template: 'my-custom-template',
112
+ context: {
113
+ customVariable: 'value',
114
+ },
115
+ });
116
+ ```
117
+
118
+ See [HANDLEBARS_TEMPLATES.md](./HANDLEBARS_TEMPLATES.md) for complete template documentation.
119
+
120
+ ### Configuration Options
121
+
122
+ #### SMTP Configuration
123
+
124
+ ```typescript
125
+ const config: EmailConfig = {
126
+ transporter: 'SMTP',
127
+ smtp: {
128
+ host: 'smtp.gmail.com',
129
+ port: 587,
130
+ secure: false, // true for 465, false for other ports
131
+ auth: {
132
+ user: 'your-email@gmail.com',
133
+ pass: 'your-password',
134
+ },
135
+ },
136
+ defaults: {
137
+ from: '"Your Name" <your-email@gmail.com>',
138
+ },
139
+ };
140
+ ```
141
+
142
+ ### Using Settings Service
143
+
144
+ If no config is provided, the module will attempt to load configuration from the Settings Service:
145
+
146
+ - `EMAIL_TRANSPORTER` - Transport type (default: 'SMTP')
147
+ - `EMAIL_SMTP_HOST` - SMTP server host
148
+ - `EMAIL_SMTP_PORT` - SMTP server port
149
+ - `EMAIL_SMTP_SECURE` - Use SSL/TLS (true/false)
150
+ - `EMAIL_SMTP_USER` - SMTP authentication user
151
+ - `EMAIL_SMTP_PASSWORD` - SMTP authentication password
152
+ - `EMAIL_DEFAULT_FROM` - Default sender email address
153
+
154
+ ## API
155
+
156
+ ### EmailService
157
+
158
+ #### `sendEmail(config, options)`
159
+
160
+ Sends an email with the specified options. **All emails are automatically logged to the database.**
161
+
162
+ **Parameters:**
163
+ - `config: EmailConfig | null` - Email configuration (transporter settings)
164
+ - `options: SendEmailOptions` - Email options (to, subject, html, etc.)
165
+
166
+ **Returns:** `Promise<void>`
167
+
168
+ #### `getEmailLogs(options?)`
169
+
170
+ Retrieves email logs with optional filtering.
171
+
172
+ **Parameters:**
173
+ - `options?`: Optional filtering options
174
+ - `status?: EmailStatus` - Filter by status (PENDING, SENT, FAILED)
175
+ - `to?: string` - Filter by recipient email
176
+ - `from?: string` - Filter by sender email
177
+ - `startDate?: Date` - Filter from this date
178
+ - `endDate?: Date` - Filter until this date
179
+ - `limit?: number` - Limit number of results
180
+
181
+ **Returns:** `Promise<EmailLog[]>`
182
+
183
+ **Example:**
184
+ ```typescript
185
+ // Get all failed emails
186
+ const failedEmails = await emailService.getEmailLogs({
187
+ status: EmailStatus.FAILED,
188
+ limit: 10,
189
+ });
190
+
191
+ // Get emails sent to specific recipient
192
+ const userEmails = await emailService.getEmailLogs({
193
+ to: 'user@example.com',
194
+ });
195
+ ```
196
+
197
+ #### `getEmailLogById(id)`
198
+
199
+ Gets a single email log by ID.
200
+
201
+ **Parameters:**
202
+ - `id: string` - Email log ID
203
+
204
+ **Returns:** `Promise<EmailLog | null>`
205
+
206
+ #### `getEmailLogStats(startDate?, endDate?)`
207
+
208
+ Gets email statistics for a date range.
209
+
210
+ **Parameters:**
211
+ - `startDate?: Date` - Start date for statistics
212
+ - `endDate?: Date` - End date for statistics
213
+
214
+ **Returns:** `Promise<{ total: number; sent: number; failed: number; pending: number }>`
215
+
216
+ **Example:**
217
+ ```typescript
218
+ const stats = await emailService.getEmailLogStats(
219
+ new Date('2024-01-01'),
220
+ new Date('2024-01-31')
221
+ );
222
+ console.log(`Total emails: ${stats.total}, Sent: ${stats.sent}, Failed: ${stats.failed}`);
223
+ ```
224
+
225
+ ## Email Logging
226
+
227
+ All emails sent through the service are automatically logged to the `email_log` table with the following information:
228
+
229
+ - **Recipient(s)**: to, cc, bcc
230
+ - **Sender**: from address
231
+ - **Content**: subject, text, html
232
+ - **Status**: PENDING, SENT, or FAILED
233
+ - **Metadata**: Additional information like template name, config source
234
+ - **Timestamps**: Created, updated, and sent timestamps
235
+ - **Error tracking**: Error messages for failed emails
236
+
237
+ ### Email Log Entity
238
+
239
+ ```typescript
240
+ export enum EmailStatus {
241
+ PENDING = 'PENDING',
242
+ SENT = 'SENT',
243
+ FAILED = 'FAILED',
244
+ }
245
+
246
+ export interface EmailLog {
247
+ id: string;
248
+ to: string;
249
+ from?: string;
250
+ cc?: string;
251
+ bcc?: string;
252
+ subject: string;
253
+ textContent?: string;
254
+ htmlContent?: string;
255
+ transporter: string;
256
+ status: EmailStatus;
257
+ errorMessage?: string;
258
+ metadata?: Record<string, any>;
259
+ hasAttachments: boolean;
260
+ sentAt?: Date;
261
+ createdAt: Date;
262
+ updatedAt: Date;
263
+ }
264
+ ```
265
+
266
+ ## Types
267
+
268
+ ### EmailConfig
269
+
270
+ ```typescript
271
+ interface EmailConfig {
272
+ transporter: 'SMTP';
273
+ smtp?: SMTPConfig;
274
+ defaults?: {
275
+ from?: string;
276
+ };
277
+ }
278
+ ```
279
+
280
+ ### SMTPConfig
281
+
282
+ ```typescript
283
+ interface SMTPConfig {
284
+ host: string;
285
+ port: number;
286
+ secure: boolean;
287
+ auth: {
288
+ user: string;
289
+ pass: string;
290
+ };
291
+ }
292
+ ```
293
+
294
+ ### SendEmailOptions
295
+
296
+ ```typescript
297
+ interface SendEmailOptions {
298
+ to: string | string[];
299
+ subject: string;
300
+ text?: string;
301
+ html?: string;
302
+ from?: string;
303
+ cc?: string | string[];
304
+ bcc?: string | string[];
305
+ attachments?: Array<{
306
+ filename: string;
307
+ content?: string | Buffer;
308
+ path?: string;
309
+ }>;
310
+ }
311
+ ```
312
+
313
+ ## License
314
+
315
+ Proprietary - Venturial Standard
package/data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Email Templates Data
2
+
3
+ This folder contains the default email templates in JSON format that are seeded into the database during setup.
4
+
5
+ ## File Structure
6
+
7
+ ### `default-templates.json`
8
+
9
+ Contains an array of email template objects with the following structure:
10
+
11
+ ```json
12
+ {
13
+ "name": "template-name", // Unique identifier (lowercase, hyphenated)
14
+ "type": "HANDLEBARS", // Template type: HANDLEBARS, HTML, or TEXT
15
+ "subject": "Email Subject {{var}}", // Subject line (supports Handlebars variables)
16
+ "description": "Template description", // Human-readable description
17
+ "variables": ["var1", "var2"], // Array of variable names used in template
18
+ "defaultValues": { // Default values for variables
19
+ "var1": "default value"
20
+ },
21
+ "htmlContent": "HTML content...", // Full HTML email content
22
+ "textContent": "Text content..." // Optional plain text version (optional)
23
+ }
24
+ ```
25
+
26
+ ## Template Types
27
+
28
+ - **HANDLEBARS**: Template uses Handlebars syntax for variable interpolation and logic
29
+ - **HTML**: Plain HTML template without variable processing
30
+ - **TEXT**: Plain text template without HTML
31
+
32
+ ## Default Templates
33
+
34
+ The following templates are included by default:
35
+
36
+ 1. **welcome** - Welcome email for new users
37
+ 2. **password-reset** - Password reset request with URL or code
38
+ 3. **notification** - General notification email
39
+
40
+ ## Adding New Templates
41
+
42
+ To add new default templates:
43
+
44
+ 1. Add a new template object to the `default-templates.json` array
45
+ 2. Ensure all required fields are included
46
+ 3. Test the template by running `npm run db:setup` in the test folder
47
+ 4. The template will be automatically seeded into the database
48
+
49
+ ## Variable Interpolation
50
+
51
+ Templates support Handlebars syntax:
52
+
53
+ - Simple variables: `{{variableName}}`
54
+ - Conditional blocks: `{{#if variable}}...{{/if}}`
55
+ - Loops: `{{#each items}}{{name}}{{/each}}`
56
+ - Nested properties: `{{user.name}}`
57
+
58
+ ## Best Practices
59
+
60
+ 1. **Keep HTML inline-styled** - Email clients don't support external CSS well
61
+ 2. **Provide default values** - Include sensible defaults for optional variables
62
+ 3. **List all variables** - Document all variables used in the `variables` array
63
+ 4. **Test across clients** - Email rendering varies significantly across clients
64
+ 5. **Include text version** - Always provide a `textContent` fallback for accessibility
65
+
66
+ ## Usage in Code
67
+
68
+ Templates are automatically loaded from this file during database setup:
69
+
70
+ ```typescript
71
+ // test/db-setup.ts
72
+ const defaultTemplates = JSON.parse(
73
+ readFileSync(join(__dirname, '..', 'data', 'default-templates.json'), 'utf-8')
74
+ );
75
+ ```
76
+
77
+ For production use, templates are managed through the `EmailTemplateService`:
78
+
79
+ ```typescript
80
+ // Create a new template
81
+ await emailTemplateService.createTemplate({
82
+ name: 'my-template',
83
+ subject: 'Hello {{name}}',
84
+ htmlContent: '<h1>Hello {{name}}!</h1>',
85
+ type: TemplateType.HANDLEBARS,
86
+ variables: ['name'],
87
+ });
88
+
89
+ // Send email using template
90
+ await emailService.sendEmailWithTemplate(null, {
91
+ to: 'user@example.com',
92
+ template: 'my-template',
93
+ context: { name: 'John' },
94
+ });
95
+ ```
96
+
97
+ ## Notes
98
+
99
+ - Templates are seeded only during `npm run db:setup`
100
+ - Existing templates in the database are not overwritten
101
+ - Template modifications should be done through the API or database directly
102
+ - This file is for initial seeding only
@@ -0,0 +1,34 @@
1
+ [
2
+ {
3
+ "name": "welcome",
4
+ "type": "HANDLEBARS",
5
+ "subject": "Welcome to {{companyName}}!",
6
+ "description": "Welcome email for new users",
7
+ "variables": ["name", "message", "companyName", "actionUrl", "actionText"],
8
+ "defaultValues": {
9
+ "companyName": "Your Company",
10
+ "actionText": "Get Started"
11
+ },
12
+ "htmlContent": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{subject}}</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .header {\n background-color: #4CAF50;\n color: white;\n padding: 20px;\n text-align: center;\n border-radius: 5px 5px 0 0;\n }\n .content {\n background-color: #f9f9f9;\n padding: 30px;\n border-radius: 0 0 5px 5px;\n }\n .button {\n display: inline-block;\n padding: 12px 24px;\n background-color: #4CAF50;\n color: white;\n text-decoration: none;\n border-radius: 4px;\n margin: 20px 0;\n }\n .footer {\n text-align: center;\n margin-top: 30px;\n padding-top: 20px;\n border-top: 1px solid #ddd;\n color: #666;\n font-size: 12px;\n }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>Welcome!</h1>\n </div>\n <div class=\"content\">\n <h2>Hello {{name}}!</h2>\n <p>Welcome to our platform. We're excited to have you on board.</p>\n <p>{{message}}</p>\n {{#if actionUrl}}\n <p style=\"text-align: center;\">\n <a href=\"{{actionUrl}}\" class=\"button\">{{actionText}}</a>\n </p>\n {{/if}}\n </div>\n <div class=\"footer\">\n <p>&copy; {{year}} {{companyName}}. All rights reserved.</p>\n </div>\n</body>\n</html>"
13
+ },
14
+ {
15
+ "name": "password-reset",
16
+ "type": "HANDLEBARS",
17
+ "subject": "Password Reset Request",
18
+ "description": "Password reset email with URL or code",
19
+ "variables": ["name", "resetUrl", "resetCode", "expirationTime"],
20
+ "defaultValues": {
21
+ "expirationTime": 60
22
+ },
23
+ "htmlContent": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{subject}}</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .header {\n background-color: #ff9800;\n color: white;\n padding: 20px;\n text-align: center;\n border-radius: 5px 5px 0 0;\n }\n .content {\n background-color: #f9f9f9;\n padding: 30px;\n border-radius: 0 0 5px 5px;\n }\n .button {\n display: inline-block;\n padding: 12px 24px;\n background-color: #ff9800;\n color: white;\n text-decoration: none;\n border-radius: 4px;\n margin: 20px 0;\n }\n .code {\n background-color: #f0f0f0;\n padding: 15px;\n text-align: center;\n font-size: 24px;\n font-weight: bold;\n letter-spacing: 5px;\n border-radius: 4px;\n margin: 20px 0;\n }\n .footer {\n text-align: center;\n margin-top: 30px;\n padding-top: 20px;\n border-top: 1px solid #ddd;\n color: #666;\n font-size: 12px;\n }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>Password Reset Request</h1>\n </div>\n <div class=\"content\">\n <h2>Hello {{name}}!</h2>\n <p>We received a request to reset your password. If you didn't make this request, you can safely ignore this email.</p>\n {{#if resetCode}}\n <p>Your password reset code is:</p>\n <div class=\"code\">{{resetCode}}</div>\n <p>This code will expire in {{expirationTime}} minutes.</p>\n {{else}}\n <p>Click the button below to reset your password:</p>\n <p style=\"text-align: center;\">\n <a href=\"{{resetUrl}}\" class=\"button\">Reset Password</a>\n </p>\n <p>This link will expire in {{expirationTime}} minutes.</p>\n <p style=\"font-size: 12px; color: #666;\">If the button doesn't work, copy and paste this link into your browser:<br>{{resetUrl}}</p>\n {{/if}}\n </div>\n <div class=\"footer\">\n <p>&copy; {{year}} Your Company. All rights reserved.</p>\n <p>If you didn't request this password reset, please contact support immediately.</p>\n </div>\n</body>\n</html>"
24
+ },
25
+ {
26
+ "name": "notification",
27
+ "type": "HANDLEBARS",
28
+ "subject": "{{title}}",
29
+ "description": "General notification email",
30
+ "variables": ["name", "title", "notificationTitle", "message", "details"],
31
+ "defaultValues": {},
32
+ "htmlContent": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{subject}}</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .header {\n background-color: #2196F3;\n color: white;\n padding: 20px;\n text-align: center;\n border-radius: 5px 5px 0 0;\n }\n .content {\n background-color: #f9f9f9;\n padding: 30px;\n border-radius: 0 0 5px 5px;\n }\n .notification-box {\n background-color: white;\n border-left: 4px solid #2196F3;\n padding: 15px;\n margin: 20px 0;\n }\n .footer {\n text-align: center;\n margin-top: 30px;\n padding-top: 20px;\n border-top: 1px solid #ddd;\n color: #666;\n font-size: 12px;\n }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>{{title}}</h1>\n </div>\n <div class=\"content\">\n <h2>Hello {{name}}!</h2>\n <div class=\"notification-box\">\n <p><strong>{{notificationTitle}}</strong></p>\n <p>{{message}}</p>\n </div>\n {{#if details}}\n <h3>Details:</h3>\n <ul>\n {{#each details}}\n <li><strong>{{@key}}:</strong> {{this}}</li>\n {{/each}}\n </ul>\n {{/if}}\n </div>\n <div class=\"footer\">\n <p>&copy; {{year}} Your Company. All rights reserved.</p>\n </div>\n</body>\n</html>"
33
+ }
34
+ ]
@@ -0,0 +1,9 @@
1
+ export declare enum EMAIL_TRANSPORTER {
2
+ SMTP = "SMTP"
3
+ }
4
+ export declare const EMAIL_DEFAULT_CONFIG: {
5
+ TRANSPORTER: EMAIL_TRANSPORTER;
6
+ SMTP_PORT: number;
7
+ SMTP_SECURE: boolean;
8
+ };
9
+ //# sourceMappingURL=email.constant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.constant.d.ts","sourceRoot":"","sources":["../../src/constants/email.constant.ts"],"names":[],"mappings":"AAGA,oBAAY,iBAAiB;IAC3B,IAAI,SAAS;CACd;AAKD,eAAO,MAAM,oBAAoB;;;;CAIhC,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMAIL_DEFAULT_CONFIG = exports.EMAIL_TRANSPORTER = void 0;
4
+ var EMAIL_TRANSPORTER;
5
+ (function (EMAIL_TRANSPORTER) {
6
+ EMAIL_TRANSPORTER["SMTP"] = "SMTP";
7
+ })(EMAIL_TRANSPORTER || (exports.EMAIL_TRANSPORTER = EMAIL_TRANSPORTER = {}));
8
+ exports.EMAIL_DEFAULT_CONFIG = {
9
+ TRANSPORTER: EMAIL_TRANSPORTER.SMTP,
10
+ SMTP_PORT: 587,
11
+ SMTP_SECURE: false,
12
+ };
13
+ //# sourceMappingURL=email.constant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.constant.js","sourceRoot":"","sources":["../../src/constants/email.constant.ts"],"names":[],"mappings":";;;AAGA,IAAY,iBAEX;AAFD,WAAY,iBAAiB;IAC3B,kCAAa,CAAA;AACf,CAAC,EAFW,iBAAiB,iCAAjB,iBAAiB,QAE5B;AAKY,QAAA,oBAAoB,GAAG;IAClC,WAAW,EAAE,iBAAiB,CAAC,IAAI;IACnC,SAAS,EAAE,GAAG;IACd,WAAW,EAAE,KAAK;CACnB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const EMAIL_SETTING_KEYS: {
2
+ readonly GENERAL_TRANSPORTER: "GLOBAL:EMAIL:GENERAL:TRANSPORTER";
3
+ readonly GENERAL_DEFAULT_FROM: "GLOBAL:EMAIL:GENERAL:DEFAULT_FROM";
4
+ readonly SMTP_HOST: "GLOBAL:EMAIL:SMTP:HOST";
5
+ readonly SMTP_PORT: "GLOBAL:EMAIL:SMTP:PORT";
6
+ readonly SMTP_SECURE: "GLOBAL:EMAIL:SMTP:SECURE";
7
+ readonly SMTP_USER: "GLOBAL:EMAIL:SMTP:USER";
8
+ readonly SMTP_PASSWORD: "GLOBAL:EMAIL:SMTP:PASSWORD";
9
+ };
10
+ //# sourceMappingURL=email.settings.constant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.settings.constant.d.ts","sourceRoot":"","sources":["../../src/constants/email.settings.constant.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;;;;;;;;CAUrB,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMAIL_SETTING_KEYS = void 0;
4
+ exports.EMAIL_SETTING_KEYS = {
5
+ GENERAL_TRANSPORTER: 'GLOBAL:EMAIL:GENERAL:TRANSPORTER',
6
+ GENERAL_DEFAULT_FROM: 'GLOBAL:EMAIL:GENERAL:DEFAULT_FROM',
7
+ SMTP_HOST: 'GLOBAL:EMAIL:SMTP:HOST',
8
+ SMTP_PORT: 'GLOBAL:EMAIL:SMTP:PORT',
9
+ SMTP_SECURE: 'GLOBAL:EMAIL:SMTP:SECURE',
10
+ SMTP_USER: 'GLOBAL:EMAIL:SMTP:USER',
11
+ SMTP_PASSWORD: 'GLOBAL:EMAIL:SMTP:PASSWORD',
12
+ };
13
+ //# sourceMappingURL=email.settings.constant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.settings.constant.js","sourceRoot":"","sources":["../../src/constants/email.settings.constant.ts"],"names":[],"mappings":";;;AAGa,QAAA,kBAAkB,GAAG;IAChC,mBAAmB,EAAE,kCAAkC;IACvD,oBAAoB,EAAE,mCAAmC;IAGzD,SAAS,EAAE,wBAAwB;IACnC,SAAS,EAAE,wBAAwB;IACnC,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,wBAAwB;IACnC,aAAa,EAAE,4BAA4B;CACnC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './email.constant';
2
+ export * from './email.settings.constant';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./email.constant"), exports);
18
+ __exportStar(require("./email.settings.constant"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,4DAA0C"}
@@ -0,0 +1,3 @@
1
+ export declare class EmailModule {
2
+ }
3
+ //# sourceMappingURL=email.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.module.d.ts","sourceRoot":"","sources":["../src/email.module.ts"],"names":[],"mappings":"AASA,qBA+Da,WAAW;CAAG"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.EmailModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const config_1 = require("@nestjs/config");
12
+ const typeorm_1 = require("@nestjs/typeorm");
13
+ const mailer_1 = require("@nestjs-modules/mailer");
14
+ const core_1 = require("@venturialstd/core");
15
+ const entities_1 = require("./entities");
16
+ const services_1 = require("./services");
17
+ let EmailModule = class EmailModule {
18
+ };
19
+ exports.EmailModule = EmailModule;
20
+ exports.EmailModule = EmailModule = __decorate([
21
+ (0, common_1.Module)({
22
+ imports: [
23
+ core_1.SharedModule.forRoot({}),
24
+ core_1.SettingsModule,
25
+ typeorm_1.TypeOrmModule.forFeature([entities_1.EmailLog, entities_1.EmailTemplate]),
26
+ mailer_1.MailerModule.forRootAsync({
27
+ imports: [config_1.ConfigModule],
28
+ inject: [config_1.ConfigService],
29
+ useFactory: (configService) => {
30
+ const port = Number(configService.get('SMTP_PORT', 587));
31
+ const secure = configService.get('SMTP_SECURE', 'false') === 'true';
32
+ const transportConfig = {
33
+ host: configService.get('SMTP_HOST', 'localhost'),
34
+ port,
35
+ secure,
36
+ auth: {
37
+ user: configService.get('SMTP_USER'),
38
+ pass: configService.get('SMTP_PASSWORD'),
39
+ },
40
+ requireTLS: undefined,
41
+ tls: undefined,
42
+ };
43
+ if (port === 587 && !secure) {
44
+ transportConfig.requireTLS = true;
45
+ transportConfig.tls = {
46
+ rejectUnauthorized: false,
47
+ minVersion: 'TLSv1.2',
48
+ };
49
+ }
50
+ else if (port === 465 && secure) {
51
+ transportConfig.tls = {
52
+ rejectUnauthorized: false,
53
+ minVersion: 'TLSv1.2',
54
+ };
55
+ }
56
+ else {
57
+ transportConfig.tls = {
58
+ rejectUnauthorized: false,
59
+ };
60
+ }
61
+ return {
62
+ transport: transportConfig,
63
+ defaults: {
64
+ from: configService.get('EMAIL_DEFAULT_FROM', '"No Reply" <noreply@example.com>'),
65
+ },
66
+ };
67
+ },
68
+ }),
69
+ ],
70
+ controllers: [],
71
+ providers: [services_1.EmailService, services_1.EmailLogService, services_1.EmailTemplateService],
72
+ exports: [services_1.EmailService, services_1.EmailLogService, services_1.EmailTemplateService],
73
+ })
74
+ ], EmailModule);
75
+ //# sourceMappingURL=email.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.module.js","sourceRoot":"","sources":["../src/email.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2CAA6D;AAC7D,6CAAgD;AAChD,mDAAsD;AACtD,6CAAkE;AAElE,yCAAqD;AACrD,yCAAiF;AAiE1E,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IA/DvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,mBAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,qBAAc;YACd,uBAAa,CAAC,UAAU,CAAC,CAAC,mBAAQ,EAAE,wBAAa,CAAC,CAAC;YACnD,qBAAY,CAAC,YAAY,CAAC;gBACxB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,aAA4B,EAAE,EAAE;oBAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;oBACzD,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;oBAEpE,MAAM,eAAe,GAAG;wBACtB,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC;wBACjD,IAAI;wBACJ,MAAM;wBACN,IAAI,EAAE;4BACJ,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC;4BACpC,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,eAAe,CAAC;yBACzC;wBACD,UAAU,EAAE,SAAgC;wBAC5C,GAAG,EAAE,SAKQ;qBACd,CAAC;oBAGF,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;wBAE5B,eAAe,CAAC,UAAU,GAAG,IAAI,CAAC;wBAClC,eAAe,CAAC,GAAG,GAAG;4BACpB,kBAAkB,EAAE,KAAK;4BACzB,UAAU,EAAE,SAAkB;yBAC/B,CAAC;oBACJ,CAAC;yBAAM,IAAI,IAAI,KAAK,GAAG,IAAI,MAAM,EAAE,CAAC;wBAElC,eAAe,CAAC,GAAG,GAAG;4BACpB,kBAAkB,EAAE,KAAK;4BACzB,UAAU,EAAE,SAAkB;yBAC/B,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBAEN,eAAe,CAAC,GAAG,GAAG;4BACpB,kBAAkB,EAAE,KAAK;yBAC1B,CAAC;oBACJ,CAAC;oBAED,OAAO;wBACL,SAAS,EAAE,eAAe;wBAC1B,QAAQ,EAAE;4BACR,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,oBAAoB,EAAE,kCAAkC,CAAC;yBAClF;qBACF,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;QACD,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,CAAC,uBAAY,EAAE,0BAAe,EAAE,+BAAoB,CAAC;QAChE,OAAO,EAAE,CAAC,uBAAY,EAAE,0BAAe,EAAE,+BAAoB,CAAC;KAC/D,CAAC;GACW,WAAW,CAAG"}
@@ -0,0 +1,24 @@
1
+ export declare enum EmailStatus {
2
+ PENDING = "PENDING",
3
+ SENT = "SENT",
4
+ FAILED = "FAILED"
5
+ }
6
+ export declare class EmailLog {
7
+ id: string;
8
+ to: string;
9
+ from: string | null;
10
+ cc: string | null;
11
+ bcc: string | null;
12
+ subject: string;
13
+ textContent: string | null;
14
+ htmlContent: string | null;
15
+ transporter: string;
16
+ status: EmailStatus;
17
+ errorMessage: string | null;
18
+ metadata: Record<string, unknown> | null;
19
+ hasAttachments: boolean;
20
+ sentAt: Date | null;
21
+ createdAt: Date;
22
+ updatedAt: Date;
23
+ }
24
+ //# sourceMappingURL=email-log.entity.d.ts.map