@mbc-cqrs-serverless/core 1.0.22 → 1.0.23
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.
|
@@ -51,3 +51,36 @@ export interface EmailNotification {
|
|
|
51
51
|
/** Optional file attachments */
|
|
52
52
|
attachments?: Attachment[];
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Configuration for SES Inline Templates.
|
|
56
|
+
* The subject and body are defined here rather than in the AWS Console.
|
|
57
|
+
*/
|
|
58
|
+
export interface InlineTemplateContent {
|
|
59
|
+
/** The subject line, can include tags like {{name}} */
|
|
60
|
+
subject: string;
|
|
61
|
+
/** The HTML body, can include tags like {{name}} */
|
|
62
|
+
html: string;
|
|
63
|
+
/** Optional plain text body for clients that don't render HTML */
|
|
64
|
+
text?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Notification payload for sending emails via Inline Templates.
|
|
68
|
+
*/
|
|
69
|
+
export interface TemplatedEmailNotification {
|
|
70
|
+
/** Sender email address (uses default if not specified) */
|
|
71
|
+
fromAddr?: string;
|
|
72
|
+
/** List of recipient email addresses */
|
|
73
|
+
toAddrs: string[];
|
|
74
|
+
/** Optional CC recipients */
|
|
75
|
+
ccAddrs?: string[];
|
|
76
|
+
/** Optional BCC recipients */
|
|
77
|
+
bccAddrs?: string[];
|
|
78
|
+
/** Optional reply-to addresses */
|
|
79
|
+
replyToAddrs?: string[];
|
|
80
|
+
/** The template structure (Subject, HTML, Text) */
|
|
81
|
+
template: InlineTemplateContent;
|
|
82
|
+
/** The actual data to inject into the template variables. e.g. { name: "Alex", verificationCode: "12345" } */
|
|
83
|
+
data: Record<string, any>;
|
|
84
|
+
/** Optional configuration set name to handle open/click tracking events */
|
|
85
|
+
configurationSetName?: string;
|
|
86
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { SendEmailCommandOutput } from '@aws-sdk/client-sesv2';
|
|
1
2
|
import { ConfigService } from '@nestjs/config';
|
|
2
|
-
import { EmailNotification } from '../interfaces';
|
|
3
|
+
import { EmailNotification, TemplatedEmailNotification } from '../interfaces';
|
|
3
4
|
declare const CLIENT_INSTANCE: unique symbol;
|
|
4
5
|
export declare class EmailService {
|
|
5
6
|
private readonly config;
|
|
@@ -7,5 +8,14 @@ export declare class EmailService {
|
|
|
7
8
|
private readonly [CLIENT_INSTANCE];
|
|
8
9
|
constructor(config: ConfigService);
|
|
9
10
|
sendEmail(msg: EmailNotification): Promise<any>;
|
|
11
|
+
/**
|
|
12
|
+
* Sends an email using SES v2 Inline Templates.
|
|
13
|
+
* @remarks
|
|
14
|
+
* Supports a hybrid mode for local development:
|
|
15
|
+
* - PRODUCTION: Uses AWS SES Native Inline Templates.
|
|
16
|
+
* - OFFLINE/LOCAL: Falls back to 'Simple' email with manual variable substitution
|
|
17
|
+
* to bypass limitations of local emulators (like serverless-offline-ses-v2).
|
|
18
|
+
*/
|
|
19
|
+
sendInlineTemplateEmail(msg: TemplatedEmailNotification): Promise<SendEmailCommandOutput | undefined>;
|
|
10
20
|
}
|
|
11
21
|
export {};
|
|
@@ -89,6 +89,84 @@ let EmailService = EmailService_1 = class EmailService {
|
|
|
89
89
|
throw error;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Sends an email using SES v2 Inline Templates.
|
|
94
|
+
* @remarks
|
|
95
|
+
* Supports a hybrid mode for local development:
|
|
96
|
+
* - PRODUCTION: Uses AWS SES Native Inline Templates.
|
|
97
|
+
* - OFFLINE/LOCAL: Falls back to 'Simple' email with manual variable substitution
|
|
98
|
+
* to bypass limitations of local emulators (like serverless-offline-ses-v2).
|
|
99
|
+
*/
|
|
100
|
+
async sendInlineTemplateEmail(msg) {
|
|
101
|
+
// 1. Validation: Fail early if no recipients
|
|
102
|
+
if (!msg.toAddrs.length && !msg.ccAddrs?.length && !msg.bccAddrs?.length) {
|
|
103
|
+
this.logger.warn('Email skipped: No recipients provided.');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const fromAddress = msg.fromAddr || this.config.get('SES_FROM_EMAIL');
|
|
108
|
+
const isOffline = process.env.IS_OFFLINE === 'true' || process.env.IS_OFFLINE === '1';
|
|
109
|
+
// 2. Privacy-safe logging
|
|
110
|
+
this.logger.log(`Sending inline template email to ${msg.toAddrs.length} recipient(s). Mode: ${isOffline ? 'LOCAL_EMULATION' : 'AWS_NATIVE'}`);
|
|
111
|
+
let contentPayload;
|
|
112
|
+
if (isOffline) {
|
|
113
|
+
// --- LOCAL FALLBACK LOGIC ---
|
|
114
|
+
// Emulators often crash with Inline Templates. We manually compile the template here.
|
|
115
|
+
this.logger.warn('⚠️ IS_OFFLINE detected: Switching to manual template compilation for local testing.');
|
|
116
|
+
const replaceVariables = (text, data) => {
|
|
117
|
+
if (!text)
|
|
118
|
+
return '';
|
|
119
|
+
return text.replace(/\{\{(\w+)\}\}/g, (_, key) => data[key] || `{{${key}}}`);
|
|
120
|
+
};
|
|
121
|
+
contentPayload = {
|
|
122
|
+
Simple: {
|
|
123
|
+
Subject: { Data: replaceVariables(msg.template.subject, msg.data) },
|
|
124
|
+
Body: {
|
|
125
|
+
Html: { Data: replaceVariables(msg.template.html, msg.data) },
|
|
126
|
+
Text: msg.template.text
|
|
127
|
+
? { Data: replaceVariables(msg.template.text, msg.data) }
|
|
128
|
+
: undefined,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// --- PRODUCTION AWS LOGIC ---
|
|
135
|
+
// Use native SES v2 Inline Template features
|
|
136
|
+
contentPayload = {
|
|
137
|
+
Template: {
|
|
138
|
+
TemplateContent: {
|
|
139
|
+
Subject: msg.template.subject,
|
|
140
|
+
Html: msg.template.html,
|
|
141
|
+
...(msg.template.text && { Text: msg.template.text }),
|
|
142
|
+
},
|
|
143
|
+
// Ensure data is valid JSON string
|
|
144
|
+
TemplateData: JSON.stringify(msg.data || {}),
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const command = new client_sesv2_1.SendEmailCommand({
|
|
149
|
+
FromEmailAddress: fromAddress,
|
|
150
|
+
Destination: {
|
|
151
|
+
ToAddresses: msg.toAddrs,
|
|
152
|
+
CcAddresses: msg.ccAddrs,
|
|
153
|
+
BccAddresses: msg.bccAddrs,
|
|
154
|
+
},
|
|
155
|
+
ReplyToAddresses: msg.replyToAddrs,
|
|
156
|
+
ConfigurationSetName: msg.configurationSetName,
|
|
157
|
+
Content: contentPayload,
|
|
158
|
+
});
|
|
159
|
+
const result = await this[CLIENT_INSTANCE].send(command);
|
|
160
|
+
this.logger.log(`Template email sent successfully: ${result.MessageId}`);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.logger.error(`Failed to send inline template email.
|
|
165
|
+
ConfigSet: ${msg.configurationSetName || 'None'}
|
|
166
|
+
Recipients (Count): ${msg.toAddrs.length}`, error.stack);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
92
170
|
};
|
|
93
171
|
exports.EmailService = EmailService;
|
|
94
172
|
exports.EmailService = EmailService = EmailService_1 = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../src/notifications/email.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../src/notifications/email.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mbc-cqrs-serverless/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "CQRS and event base core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mbc",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"serverless-step-functions-local": "^0.5.1",
|
|
89
89
|
"supertest": "^7.0.0"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "f3c0c307de80ecd61550cdcac9ac8bdc9f79269d"
|
|
92
92
|
}
|