@platform-x/hep-notification-client 1.3.0 → 1.3.2
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 +7 -7
- package/dist/jest-setup.js +28 -0
- package/dist/jest-setup.js.map +1 -0
- package/dist/src/common/controllers/common_controller.js +72 -0
- package/dist/src/common/controllers/common_controller.js.map +1 -0
- package/dist/src/common/controllers/index.js +29 -0
- package/dist/src/common/controllers/index.js.map +1 -0
- package/dist/src/common/middleware/commonMiddleware.js +141 -0
- package/dist/src/common/middleware/commonMiddleware.js.map +1 -0
- package/dist/src/common/service/requestService.js +79 -1
- package/dist/src/common/service/requestService.js.map +1 -0
- package/dist/src/common/service/twilioService.js +3 -11
- package/dist/src/common/service/twilioService.js.map +1 -0
- package/dist/src/common/util/commonUtil.js +119 -1
- package/dist/src/common/util/commonUtil.js.map +1 -0
- package/dist/src/common/util/constants.js +18 -0
- package/dist/src/common/util/constants.js.map +1 -0
- package/dist/src/common/util/errorHandler.js +4 -6
- package/dist/src/common/util/errorHandler.js.map +1 -0
- package/dist/src/common/util/httpCodes.js +26 -0
- package/dist/src/common/util/httpCodes.js.map +1 -0
- package/dist/src/common/util/logger.js +1 -1
- package/dist/src/common/util/logger.js.map +1 -0
- package/dist/src/common/util/requestTracer.js +18 -1
- package/dist/src/common/util/requestTracer.js.map +1 -0
- package/dist/src/common/util/solrConnector.js.map +1 -0
- package/dist/src/config/index.js +49 -4
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/platform-x/app.js +35 -0
- package/dist/src/platform-x/app.js.map +1 -0
- package/dist/src/platform-x/constants/index.js +2 -14
- package/dist/src/platform-x/constants/index.js.map +1 -0
- package/dist/src/platform-x/constants/style.js +98 -98
- package/dist/src/platform-x/constants/style.js.map +1 -0
- package/dist/src/platform-x/controllers/cronController.js +399 -0
- package/dist/src/platform-x/controllers/cronController.js.map +1 -0
- package/dist/src/platform-x/controllers/fileUploadController.js +76 -0
- package/dist/src/platform-x/controllers/fileUploadController.js.map +1 -0
- package/dist/src/platform-x/controllers/graphRESTControllers.js +183 -0
- package/dist/src/platform-x/controllers/graphRESTControllers.js.map +1 -0
- package/dist/src/platform-x/controllers/index.js +30 -0
- package/dist/src/platform-x/controllers/index.js.map +1 -0
- package/dist/src/platform-x/controllers/siteDomainController.js +74 -0
- package/dist/src/platform-x/controllers/siteDomainController.js.map +1 -0
- package/dist/src/platform-x/dataSource/emailDataSource.js.map +1 -0
- package/dist/src/platform-x/database/connection.js +3 -6
- package/dist/src/platform-x/database/connection.js.map +1 -0
- package/dist/src/platform-x/database/dao/formBuilder.dao.js +1 -1
- package/dist/src/platform-x/database/dao/formBuilder.dao.js.map +1 -0
- package/dist/src/platform-x/database/dao/siteDomain.dao.js +73 -0
- package/dist/src/platform-x/database/dao/siteDomain.dao.js.map +1 -0
- package/dist/src/platform-x/database/index.js.map +1 -0
- package/dist/src/platform-x/{interface/interface.js → database/interfaces/site_domain.interface.js} +1 -1
- package/dist/src/platform-x/database/interfaces/site_domain.interface.js.map +1 -0
- package/dist/src/platform-x/database/models/formBuilder.model.js.map +1 -0
- package/dist/src/platform-x/database/models/site_domains.model.js +51 -0
- package/dist/src/platform-x/database/models/site_domains.model.js.map +1 -0
- package/dist/src/platform-x/routes/index.js +19 -0
- package/dist/src/platform-x/routes/index.js.map +1 -0
- package/dist/src/platform-x/services/cron.services.js +117 -0
- package/dist/src/platform-x/services/cron.services.js.map +1 -0
- package/dist/src/platform-x/util/emailHandler.js +53 -137
- package/dist/src/platform-x/util/emailHandler.js.map +1 -0
- package/dist/src/platform-x/util/emailTemplate.js +63 -60
- package/dist/src/platform-x/util/emailTemplate.js.map +1 -0
- package/dist/src/platform-x/util/solr-data-source/SolrHttpDataSource.js +2 -0
- package/dist/src/platform-x/util/solr-data-source/SolrHttpDataSource.js.map +1 -0
- package/dist/src/server.js +38 -0
- package/dist/src/server.js.map +1 -0
- package/dist/swagger.json +247 -0
- package/dist/test/controllers/common_controller.spec.js +79 -0
- package/dist/test/controllers/common_controller.spec.js.map +1 -0
- package/dist/test/middleware/commonMiddleware.spec.js +88 -0
- package/dist/test/middleware/commonMiddleware.spec.js.map +1 -0
- package/dist/test/platform-x/controllers/graphRESTControllers.spec.js +195 -0
- package/dist/test/platform-x/controllers/graphRESTControllers.spec.js.map +1 -0
- package/dist/test/platform-x/datasource/emailDataSource.spec.js +81 -0
- package/dist/test/platform-x/datasource/emailDataSource.spec.js.map +1 -0
- package/dist/test/platform-x/util/emailHandler.spec.js +474 -0
- package/dist/test/platform-x/util/emailHandler.spec.js.map +1 -0
- package/dist/test/platform-x/util/solr-data-source/SolrHttpDataSource.spec.js +80 -0
- package/dist/test/platform-x/util/solr-data-source/SolrHttpDataSource.spec.js.map +1 -0
- package/dist/test/services/requestService.spec.js +108 -0
- package/dist/test/services/requestService.spec.js.map +1 -0
- package/dist/test/services/requestServiceGet.spec.js +43 -0
- package/dist/test/services/requestServiceGet.spec.js.map +1 -0
- package/dist/test/src/common/service/twilioService.spec.js +65 -0
- package/dist/test/src/common/service/twilioService.spec.js.map +1 -0
- package/dist/test/util/commonUtil.spec.js +110 -0
- package/dist/test/util/commonUtil.spec.js.map +1 -0
- package/dist/test/util/logger.spec.js +51 -0
- package/dist/test/util/logger.spec.js.map +1 -0
- package/dist/test/util/requestTracer.spec.js +64 -0
- package/dist/test/util/requestTracer.spec.js.map +1 -0
- package/dist/test/util/solrconnector.spec.js +145 -0
- package/dist/test/util/solrconnector.spec.js.map +1 -0
- package/package.json +66 -62
- package/postman_collection/HEP_Environment.postman_environment.json +44 -44
- package/postman_collection/hep-notification.postman_collection.json +55 -55
- package/reports/output.jtl +1 -1
- package/reports/scripts/jmeter_sendgrid.js +34 -34
- package/reports/scripts/newman_sendgrid.js +40 -40
- package/reports/scripts/sendgrid.js +40 -40
- package/reports/scripts/trivy_sendgrid.js +40 -40
- package/src/common/service/requestService.ts +87 -0
- package/{dist/src/common/service/secretKeyManager.services.js → src/common/service/secretKeyManager.services.ts} +1 -2
- package/src/common/service/twilioService.ts +58 -0
- package/src/common/util/commonUtil.ts +39 -0
- package/src/common/util/errorHandler.ts +120 -0
- package/src/common/util/logger.ts +215 -0
- package/src/common/util/requestTracer.ts +10 -0
- package/src/common/util/solrConnector.ts +319 -0
- package/src/config/index.ts +35 -0
- package/src/index.ts +34 -0
- package/src/platform-x/constants/index.ts +20 -0
- package/src/platform-x/constants/style.ts +99 -0
- package/src/platform-x/dataSource/emailDataSource.ts +34 -0
- package/src/platform-x/database/connection.ts +47 -0
- package/src/platform-x/database/dao/formBuilder.dao.ts +33 -0
- package/src/platform-x/database/index.ts +7 -0
- package/src/platform-x/database/models/formBuilder.model.ts +23 -0
- package/src/platform-x/util/emailHandler.ts +580 -0
- package/src/platform-x/util/emailTemplate.ts +66 -0
- package/src/platform-x/util/solr-data-source/SolrHttpDataSource.ts +97 -0
- package/{dist → src}/templates/orderPlaced.ejs +172 -172
- package/{dist → src}/templates/orderPlaced.html +189 -189
- package/tsconfig.json +73 -0
- package/dist/src/common/service/requestService.d.ts +0 -26
- package/dist/src/common/service/secretKeyManager.services.d.ts +0 -0
- package/dist/src/common/service/twilioService.d.ts +0 -19
- package/dist/src/common/util/commonUtil.d.ts +0 -22
- package/dist/src/common/util/errorHandler.d.ts +0 -44
- package/dist/src/common/util/logger.d.ts +0 -68
- package/dist/src/common/util/requestTracer.d.ts +0 -2
- package/dist/src/common/util/secretKeyManager.d.ts +0 -7
- package/dist/src/common/util/secretKeyManager.js +0 -58
- package/dist/src/common/util/solrConnector.d.ts +0 -35
- package/dist/src/config/index.d.ts +0 -30
- package/dist/src/index.d.ts +0 -5
- package/dist/src/index.js +0 -20
- package/dist/src/platform-x/constants/index.d.ts +0 -18
- package/dist/src/platform-x/constants/style.d.ts +0 -1
- package/dist/src/platform-x/dataSource/emailDataSource.d.ts +0 -5
- package/dist/src/platform-x/database/connection.d.ts +0 -8
- package/dist/src/platform-x/database/dao/formBuilder.dao.d.ts +0 -9
- package/dist/src/platform-x/database/index.d.ts +0 -7
- package/dist/src/platform-x/database/models/formBuilder.model.d.ts +0 -34
- package/dist/src/platform-x/interface/interface.d.ts +0 -4
- package/dist/src/platform-x/util/emailHandler.d.ts +0 -62
- package/dist/src/platform-x/util/emailTemplate.d.ts +0 -4
- package/dist/src/platform-x/util/solr-data-source/SolrHttpDataSource.d.ts +0 -26
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import { EmailDataSource } from '../dataSource/emailDataSource';
|
|
2
|
+
import * as HTMLParser from 'node-html-parser';
|
|
3
|
+
import { style } from '../constants/style';
|
|
4
|
+
import config from '../../config';
|
|
5
|
+
import { CREATE_USER_EMAIL_TEMPLATE, DynamicValues } from '../constants';
|
|
6
|
+
import { isArray } from 'lodash';
|
|
7
|
+
import { EmailTemplateHandler } from './emailTemplate';
|
|
8
|
+
const moment = require('moment-timezone');
|
|
9
|
+
const sgMail = require('@sendgrid/mail');
|
|
10
|
+
const sgHelpers = require('@sendgrid/helpers');
|
|
11
|
+
import * as ejs from 'ejs';
|
|
12
|
+
// import DOMPurify from 'dompurify'; // Include DOMPurify for sanitization
|
|
13
|
+
import FormBuilderDao from '../database/dao/formBuilder.dao';
|
|
14
|
+
import createDOMPurify from 'dompurify';
|
|
15
|
+
import { JSDOM } from 'jsdom';
|
|
16
|
+
import { Logger } from '../../common/util/logger';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { getIAMSecrets } from '../..';
|
|
19
|
+
|
|
20
|
+
const window = new JSDOM('').window;
|
|
21
|
+
const DOMPurify = createDOMPurify(window);
|
|
22
|
+
// NOSONAR-NEXT-LINE
|
|
23
|
+
interface EmailOptions {
|
|
24
|
+
email: string;
|
|
25
|
+
emailTemplate: string;
|
|
26
|
+
subject: string;
|
|
27
|
+
bcc?: string;
|
|
28
|
+
cc?: string | string[]; // Support both single CC email or array of CC emails
|
|
29
|
+
personalizations?: Personalize;
|
|
30
|
+
}
|
|
31
|
+
interface Personalize {
|
|
32
|
+
to: [ToWithSubstitutions];
|
|
33
|
+
cc?: [ToWithSubstitutions];
|
|
34
|
+
bcc?: [ToWithSubstitutions];
|
|
35
|
+
}
|
|
36
|
+
interface ToWithSubstitutions {
|
|
37
|
+
to: string;
|
|
38
|
+
substitutions?: [string];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface Recipients {
|
|
42
|
+
name: string;
|
|
43
|
+
email: string;
|
|
44
|
+
}
|
|
45
|
+
interface Substitutions {
|
|
46
|
+
name?: string;
|
|
47
|
+
document_uri?: string;
|
|
48
|
+
sender_name?: string;
|
|
49
|
+
}
|
|
50
|
+
// NOSONAR-NEXT-LINE
|
|
51
|
+
export class EmailHandler {
|
|
52
|
+
constructor() { } // NOSONAR
|
|
53
|
+
/**
|
|
54
|
+
* post - handler to do emails triggering
|
|
55
|
+
* @param emailConfig
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
public async sendEmail(emailConfig: EmailOptions) {
|
|
59
|
+
Logger.info('EmailHandler: Reached sendEmail method', 'sendEmail');
|
|
60
|
+
const secrets = await getIAMSecrets();
|
|
61
|
+
sgMail.setApiKey(secrets?.[DynamicValues?.SENDGRID_API_KEY]);
|
|
62
|
+
|
|
63
|
+
// Build personalization object
|
|
64
|
+
const personalization: any = {
|
|
65
|
+
to: [{ email: emailConfig.email }],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Add CC emails if provided
|
|
69
|
+
if (emailConfig.cc) {
|
|
70
|
+
const ccEmails = Array.isArray(emailConfig.cc) ? emailConfig.cc : [emailConfig.cc];
|
|
71
|
+
personalization.cc = ccEmails.map((email: string) => ({ email }));
|
|
72
|
+
Logger.info(`Adding CC emails to non-personalized email: ${ccEmails.join(', ')}`, 'sendEmail');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Add BCC if provided
|
|
76
|
+
if (emailConfig.bcc) {
|
|
77
|
+
personalization.bcc = [{ email: emailConfig.bcc }];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const msg = {
|
|
81
|
+
personalizations: [personalization],
|
|
82
|
+
from: { email: config.EMAIL_FROM },
|
|
83
|
+
html: emailConfig.emailTemplate,
|
|
84
|
+
subject: emailConfig.subject,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
Logger.debug('Before sending email', 'sendEmail', msg);
|
|
88
|
+
return new Promise((resolve: any, reject: any) => {
|
|
89
|
+
sgMail
|
|
90
|
+
.send(msg)
|
|
91
|
+
.then((response: any) => {
|
|
92
|
+
Logger.info('EmailHandler: Successfull Response', 'sendEmail');
|
|
93
|
+
resolve(response[0]);
|
|
94
|
+
})
|
|
95
|
+
.catch((error: any) => {
|
|
96
|
+
Logger.error('EmailHandler: Error in sendEmail', 'sendEmail', error);
|
|
97
|
+
reject(error);
|
|
98
|
+
// throw error;
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public async prepareEmailRequest(reqBody: any, emailType: any) {
|
|
104
|
+
Logger.info('Reached prepareEmailRequest', 'prepareEmailRequest');
|
|
105
|
+
try {
|
|
106
|
+
let dataSource = new EmailDataSource();
|
|
107
|
+
Logger.debug('Before preparing email request', 'prepareEmailRequest', dataSource);
|
|
108
|
+
let response = await dataSource.fetchPageModel(emailType);
|
|
109
|
+
Logger.debug('Response for preparing email request', 'prepareEmailRequest', response);
|
|
110
|
+
const start = moment.tz(reqBody.dateTime, 'UTC'); // original timezone
|
|
111
|
+
let curentTimeZone = start
|
|
112
|
+
.tz(reqBody.timezoneOffset)
|
|
113
|
+
.format('Do MMMM YYYY, h:mm a');
|
|
114
|
+
|
|
115
|
+
const root: any = HTMLParser.parse(response[0]?.hclplatformx_Body);
|
|
116
|
+
root.querySelector(
|
|
117
|
+
'#1_dynamic_text'
|
|
118
|
+
).textContent = ` ${reqBody.userName}`;
|
|
119
|
+
root.querySelector(
|
|
120
|
+
'#2_dynamic_text'
|
|
121
|
+
).textContent = DOMPurify.sanitize(`<b> ${reqBody.pageTitle} </b>`);
|
|
122
|
+
root.querySelector(
|
|
123
|
+
'#3_dynamic_text'
|
|
124
|
+
).textContent = DOMPurify.sanitize(`<b>${curentTimeZone}</b>`);
|
|
125
|
+
|
|
126
|
+
root.querySelector(
|
|
127
|
+
'#dynamic_contentType'
|
|
128
|
+
).textContent = DOMPurify.sanitize(`<b>${reqBody.contentType}</b>`);
|
|
129
|
+
root.querySelector('#dynamic_event').textContent = DOMPurify.sanitize(`<b>${reqBody.event[0] + reqBody.event.slice(1)
|
|
130
|
+
}</b>`);
|
|
131
|
+
if (reqBody?.event?.toLowerCase() === 'published') {
|
|
132
|
+
root
|
|
133
|
+
.querySelector('.dynamic_links_btn')
|
|
134
|
+
.setAttribute('href', reqBody.publishPageUrl);
|
|
135
|
+
} else {
|
|
136
|
+
root.querySelector('#viewButton').setAttribute('style', 'display:none');
|
|
137
|
+
}
|
|
138
|
+
const append: any = root.querySelector('head');
|
|
139
|
+
append.insertAdjacentHTML('beforeend', DOMPurify.sanitize(style));
|
|
140
|
+
let emailConfiguration: any = {
|
|
141
|
+
email: reqBody.emailTo,
|
|
142
|
+
emailTemplate: root.toString(),
|
|
143
|
+
subject: DOMPurify.sanitize(response[0].hclplatformx_Subject.replace('{{pageType}}', reqBody.contentType[0] + reqBody.contentType.slice(1))
|
|
144
|
+
.replace('{{publishOrUnpublish}}', reqBody.event[0] + reqBody.event.slice(1))
|
|
145
|
+
),
|
|
146
|
+
};
|
|
147
|
+
Logger.debug('Reached prepareEmailRequest - emailConfiguration', 'prepareEmailRequest', emailConfiguration);
|
|
148
|
+
let emailResponse: any = await this.pushEmails(emailConfiguration);
|
|
149
|
+
Logger.debug('Reached prepareEmailRequest - emailResponse', 'prepareEmailRequest', emailResponse);
|
|
150
|
+
return emailResponse;
|
|
151
|
+
} catch (error: any) {
|
|
152
|
+
Logger.error(
|
|
153
|
+
'EmailHandler: Error in preparing email Request',
|
|
154
|
+
'prepareEmailRequest',
|
|
155
|
+
error
|
|
156
|
+
);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* @param reqBody
|
|
163
|
+
* @param emailType
|
|
164
|
+
* @returns
|
|
165
|
+
*/
|
|
166
|
+
public async prepareSendEmailRequest(reqBody: any, emailType: any) {
|
|
167
|
+
Logger.info('Reached prepareSendEmailRequest in emailHandler', 'prepareSendEmailRequest');
|
|
168
|
+
try {
|
|
169
|
+
let dataSource = new EmailDataSource();
|
|
170
|
+
|
|
171
|
+
// disable SOLR because of connectivity issue
|
|
172
|
+
let templateData = await dataSource.fetchPageModel(emailType);
|
|
173
|
+
if (reqBody?.replacement_variables && templateData?.length) {
|
|
174
|
+
for (const key in reqBody.replacement_variables) {
|
|
175
|
+
if (key) {
|
|
176
|
+
templateData[0].hclplatformx_Body =
|
|
177
|
+
templateData[0]?.hclplatformx_Body?.replace(
|
|
178
|
+
`{{${key}}}`,
|
|
179
|
+
reqBody.replacement_variables[key]
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const root = HTMLParser.parse(templateData[0]?.hclplatformx_Body);
|
|
185
|
+
let emailConfiguration: any = {
|
|
186
|
+
email: reqBody.replacement_variables?.EMAIL,
|
|
187
|
+
emailTemplate: root ? root.toString() : '',
|
|
188
|
+
subject: CREATE_USER_EMAIL_TEMPLATE[0].subject,
|
|
189
|
+
};
|
|
190
|
+
Logger.debug('Reached prepareSendEmailRequest - emailConfiguration', 'prepareSendEmailRequest', emailConfiguration);
|
|
191
|
+
let emailResponse: any = await this.pushEmails(emailConfiguration);
|
|
192
|
+
Logger.debug('Reached prepareSendEmailRequest - emailResponse END', 'prepareSendEmailRequest', emailResponse);
|
|
193
|
+
return emailResponse;
|
|
194
|
+
} catch (error: any) {
|
|
195
|
+
Logger.error(
|
|
196
|
+
'EmailHandler: Error in preparing email Request',
|
|
197
|
+
'prepareEmailRequest',
|
|
198
|
+
error
|
|
199
|
+
);
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
*
|
|
206
|
+
* @param emailConfiguration
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
209
|
+
public async pushEmails(emailConfiguration: any) {
|
|
210
|
+
Logger.info('Reached pushEmails in emailHandler', 'pushEmails');
|
|
211
|
+
return await this.sendEmail(emailConfiguration).then(
|
|
212
|
+
async (response: any) => {
|
|
213
|
+
if (response?.statusCode === '202' || response.statusCode === 202) {
|
|
214
|
+
response.msg =
|
|
215
|
+
'Thanks for getting in touch with us. We shall contact you soon.';
|
|
216
|
+
return response;
|
|
217
|
+
} else {
|
|
218
|
+
Logger.error(
|
|
219
|
+
'solrResolver: Error in sendEmail resolver',
|
|
220
|
+
'sendEmail',
|
|
221
|
+
response
|
|
222
|
+
);
|
|
223
|
+
throw new Error('Error Sending in Email');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Function to send email with personalize data using sendgrid
|
|
231
|
+
* @param emailConfig
|
|
232
|
+
* @returns
|
|
233
|
+
*/
|
|
234
|
+
public async sendEmailWithPersonalizations(emailConfig: any, email_from?: any) {
|
|
235
|
+
Logger.info(
|
|
236
|
+
`EmailHandler: Reached sendEmailWithPersonalizations method with emailConfig: ${JSON.stringify(
|
|
237
|
+
emailConfig
|
|
238
|
+
)}`, 'sendEmailWithPersonalizations'
|
|
239
|
+
);
|
|
240
|
+
Logger.info(`EMAIL_FROM-------> ${email_from}`, 'sendEmailWithPersonalizations');
|
|
241
|
+
const Mail = sgHelpers.classes.Mail;
|
|
242
|
+
// let email_from = isCFF ? config?.CFF_MAIL_FROM : config?.EMAIL_FROM;
|
|
243
|
+
Logger.info('sendEmailWithPersonalizations : Email From:', JSON.stringify(email_from));
|
|
244
|
+
const Personalization = sgHelpers.classes.Personalization;
|
|
245
|
+
const secrets = await getIAMSecrets();
|
|
246
|
+
sgMail.setApiKey(secrets?.[DynamicValues?.SENDGRID_API_KEY]);
|
|
247
|
+
const mail = new Mail();
|
|
248
|
+
mail.setFrom(email_from);
|
|
249
|
+
mail.setSubject(emailConfig.subject);
|
|
250
|
+
mail.addTextContent(emailConfig.emailTemplate);
|
|
251
|
+
mail.addHtmlContent(emailConfig.emailTemplate);
|
|
252
|
+
// Set personalizations as per the emailConfig
|
|
253
|
+
if (
|
|
254
|
+
emailConfig?.personalizations &&
|
|
255
|
+
emailConfig?.personalizations.to.length
|
|
256
|
+
) {
|
|
257
|
+
const { to, cc } = emailConfig?.personalizations;
|
|
258
|
+
|
|
259
|
+
// Create separate personalization for each TO recipient with their unique substitutions
|
|
260
|
+
to.forEach((toData: ToWithSubstitutions, index: number) => {
|
|
261
|
+
const personalization = new Personalization();
|
|
262
|
+
personalization.addTo(toData.to);
|
|
263
|
+
|
|
264
|
+
// Add CC emails to EACH personalization (CC gets email for each TO recipient)
|
|
265
|
+
if (cc && cc.length > 0) {
|
|
266
|
+
cc.forEach((ccData: ToWithSubstitutions) => {
|
|
267
|
+
personalization.addCc(ccData.to);
|
|
268
|
+
Logger.info(`Adding CC email ${ccData.to} to personalization ${index + 1} for TO: ${toData.to}`, 'sendEmailWithPersonalizations');
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Add unique substitutions for each TO recipient
|
|
273
|
+
if (toData?.substitutions) {
|
|
274
|
+
for (const key in toData?.substitutions) {
|
|
275
|
+
if (key) {
|
|
276
|
+
personalization?.addSubstitution(key, toData?.substitutions[key]);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
mail.addPersonalization(personalization);
|
|
282
|
+
Logger.info(`Personalization ${index + 1} created for TO: ${toData.to} with ${cc?.length || 0} CC recipients`, 'sendEmailWithPersonalizations');
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Handle attachments
|
|
286
|
+
if (emailConfig?.attachments && Array.isArray(emailConfig.attachments)) {
|
|
287
|
+
emailConfig.attachments.forEach((attachment: any) => {
|
|
288
|
+
mail.addAttachment({
|
|
289
|
+
content: attachment.base64, // base64 string
|
|
290
|
+
filename: attachment.filename,
|
|
291
|
+
type: attachment.type || 'application/octet-stream',
|
|
292
|
+
disposition: 'attachment',
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
Logger.info('sendEmailWithPersonalizations: Email Request:', JSON.stringify(emailConfig));
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
// set to email for non personalized email with CC support
|
|
299
|
+
const personalization = new Personalization();
|
|
300
|
+
personalization.addTo(emailConfig.email);
|
|
301
|
+
|
|
302
|
+
// Add CC emails if provided in non-personalized mode
|
|
303
|
+
if (emailConfig.cc) {
|
|
304
|
+
const ccEmails = Array.isArray(emailConfig.cc) ? emailConfig.cc : [emailConfig.cc];
|
|
305
|
+
ccEmails.forEach((ccEmail: string) => {
|
|
306
|
+
personalization.addCc(ccEmail);
|
|
307
|
+
Logger.info(`Adding CC email to non-personalized email: ${ccEmail}`, 'sendEmailWithPersonalizations');
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
Logger.info('sendEmailWithPersonalizations : Email personalizations:', JSON.stringify(personalization));
|
|
312
|
+
mail.addPersonalization(personalization);
|
|
313
|
+
}
|
|
314
|
+
return new Promise((resolve: any, reject: any) => {
|
|
315
|
+
sgMail
|
|
316
|
+
.send(mail)
|
|
317
|
+
.then((response: any) => {
|
|
318
|
+
Logger.info(
|
|
319
|
+
`EmailHandler: Successful Response from sendEmailWithPersonalizations: ${JSON.stringify(
|
|
320
|
+
response
|
|
321
|
+
)}`, 'sendEmailWithPersonalizations'
|
|
322
|
+
);
|
|
323
|
+
resolve(response[0]);
|
|
324
|
+
})
|
|
325
|
+
.catch((error: any) => {
|
|
326
|
+
Logger.error(
|
|
327
|
+
`EmailHandler: Error in sendEmailWithPersonalizations: ${JSON.stringify(
|
|
328
|
+
error
|
|
329
|
+
)}`,
|
|
330
|
+
'sendEmail',
|
|
331
|
+
error
|
|
332
|
+
);
|
|
333
|
+
reject(error);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Utility method to prepare CC emails in standardized format
|
|
340
|
+
* @param ccEmails - Can be string, array of strings, or Recipients array
|
|
341
|
+
* @returns Array of email strings
|
|
342
|
+
*/
|
|
343
|
+
private prepareCCEmails(ccEmails: string | string[] | Recipients[]): string[] {
|
|
344
|
+
if (!ccEmails) return [];
|
|
345
|
+
|
|
346
|
+
if (typeof ccEmails === 'string') {
|
|
347
|
+
return [ccEmails];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (Array.isArray(ccEmails)) {
|
|
351
|
+
return ccEmails.map((cc: any) => {
|
|
352
|
+
if (typeof cc === 'string') return cc;
|
|
353
|
+
if (cc.email) return cc.email; // Recipients object
|
|
354
|
+
return cc.to || cc; // ToWithSubstitutions object
|
|
355
|
+
}).filter(email => email && typeof email === 'string');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* prepare personalize email request to send email through sendgrid
|
|
363
|
+
* @param reqBody
|
|
364
|
+
* @returns
|
|
365
|
+
*/
|
|
366
|
+
public async sendPersonalizeEmailRequest(reqBody: any) {
|
|
367
|
+
try {
|
|
368
|
+
let { email_type, replacement_variables, recipients, cc_recipients, isCFF = config?.EMAIL_FROM, sender_info = {} } = reqBody;
|
|
369
|
+
Logger.info(
|
|
370
|
+
`EmailHandler: reached in sendPersonalizeEmailRequest with emailType: ${email_type} and ${isCFF}`, 'sendPersonalizeEmailRequest'
|
|
371
|
+
);
|
|
372
|
+
// disable SOLR because of connectivity issue
|
|
373
|
+
Logger.debug('Reached sendPersonalizeEmailRequest in emailHandler', 'sendPersonalizeEmailRequest');
|
|
374
|
+
const { name, email,documentpath } = sender_info;
|
|
375
|
+
let templateData: any = await this.fetchEmailTemplateData(reqBody,documentpath);
|
|
376
|
+
Logger.debug('Reached sendPersonalizeEmailRequest in emailHandler', 'sendPersonalizeEmailRequest', templateData);
|
|
377
|
+
let recipientsData = {} as Personalize;
|
|
378
|
+
if (isArray(recipients)) {
|
|
379
|
+
const to = [] as unknown as [ToWithSubstitutions];
|
|
380
|
+
recipients.forEach((recipient: Recipients) => {
|
|
381
|
+
const substitutions = {
|
|
382
|
+
...replacement_variables,
|
|
383
|
+
recipient_name: recipient?.name,
|
|
384
|
+
};
|
|
385
|
+
to.push({
|
|
386
|
+
to: recipient?.email,
|
|
387
|
+
substitutions,
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
recipientsData = {
|
|
391
|
+
to,
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// Add CC recipients if they exist
|
|
395
|
+
if (cc_recipients && isArray(cc_recipients)) {
|
|
396
|
+
const cc = [] as unknown as [ToWithSubstitutions];
|
|
397
|
+
cc_recipients.forEach((ccRecipient: Recipients) => {
|
|
398
|
+
cc.push({
|
|
399
|
+
to: ccRecipient?.email,
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
recipientsData.cc = cc;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (templateData && Object.keys(templateData)?.length !== 0) {
|
|
406
|
+
const root = HTMLParser.parse(templateData?.body);
|
|
407
|
+
isCFF = templateData?.email_from && templateData?.email_from !== '' ? templateData?.email_from : isCFF;
|
|
408
|
+
const emailConfiguration = {
|
|
409
|
+
email: reqBody.replacement_variables?.EMAIL,
|
|
410
|
+
emailTemplate: root ? root.toString() : '',
|
|
411
|
+
subject: templateData?.subject,
|
|
412
|
+
personalizations: recipientsData,
|
|
413
|
+
attachments: reqBody?.attachments,
|
|
414
|
+
};
|
|
415
|
+
// let is_cff: boolean = (isCFF && isCFF === true) ? true : false;
|
|
416
|
+
Logger.info(`sendPersonalizeEmailRequest -${JSON.stringify(emailConfiguration)}`, 'sendPersonalizeEmailRequest');
|
|
417
|
+
const senderFrom = email && name ? { email, name } : isCFF;
|
|
418
|
+
Logger.info(`sendPersonalizeEmailRequest - senderFrom: ${JSON.stringify(senderFrom)}`, 'sendPersonalizeEmailRequest');
|
|
419
|
+
return await this.sendEmailWithPersonalizations(emailConfiguration, senderFrom).then(
|
|
420
|
+
async (response: any) => {
|
|
421
|
+
if (response.statusCode === 202) {
|
|
422
|
+
response.msg =
|
|
423
|
+
'Thanks for getting in touch with us. We shall contact you soon.';
|
|
424
|
+
Logger.info(`sendPersonalizeEmailRequest - response: ${JSON.stringify(response)}`, 'sendPersonalizeEmailRequest');
|
|
425
|
+
return response;
|
|
426
|
+
} else {
|
|
427
|
+
Logger.error(
|
|
428
|
+
`EmailHandler: Error in sendEmailWithPersonalizations response - ${JSON.stringify(
|
|
429
|
+
response
|
|
430
|
+
)}`,
|
|
431
|
+
'sendEmailWithPersonalizations',
|
|
432
|
+
response
|
|
433
|
+
);
|
|
434
|
+
throw new Error('Error Sending in Email');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
} catch (error: any) {
|
|
440
|
+
Logger.error(
|
|
441
|
+
'EmailHandler: Error in preparing email Request',
|
|
442
|
+
'prepareEmailRequest',
|
|
443
|
+
error
|
|
444
|
+
);
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
public async sendPlaceOrderEmail(reqBody: any) {
|
|
450
|
+
Logger.info('Redached sendPlaceOrderEmail', 'sendPlaceOrderEmail');
|
|
451
|
+
try {
|
|
452
|
+
let dataSource = new EmailDataSource();
|
|
453
|
+
await dataSource.fetchPageModel('orderPlaced');
|
|
454
|
+
|
|
455
|
+
const start = moment.tz(reqBody.dateTime, 'UTC'); // original timezone
|
|
456
|
+
start.tz(reqBody.timezoneOffset).format('Do MMMM YYYY, h:mm a');
|
|
457
|
+
|
|
458
|
+
let str = await EmailTemplateHandler.prepareEmailTemplate(reqBody);
|
|
459
|
+
let root: any = HTMLParser.parse(str);
|
|
460
|
+
root.querySelector('#1_dynamic_text').textContent = `${reqBody.userName}`;
|
|
461
|
+
root.querySelector(
|
|
462
|
+
'#2_dynamic_text'
|
|
463
|
+
).textContent = DOMPurify.sanitize(`<b> ${reqBody.total_price} </b>`);
|
|
464
|
+
root.querySelector(
|
|
465
|
+
'#3_dynamic_text'
|
|
466
|
+
).textContent = DOMPurify.sanitize(`<b>${reqBody.currency_code}</b>`);
|
|
467
|
+
root.querySelector(
|
|
468
|
+
'#4_dynamic_text'
|
|
469
|
+
).textContent = DOMPurify.sanitize(`<b>${reqBody.shipping_address.streetName} ${reqBody.shipping_address.city} ${reqBody.shipping_address.state} ${reqBody.shipping_address.country}${reqBody.shipping_address.postalCode} </b>`);
|
|
470
|
+
root.querySelector(
|
|
471
|
+
'#5_dynamic_text'
|
|
472
|
+
).textContent = DOMPurify.sanitize(`<b>${reqBody.total_tax}</b>`);
|
|
473
|
+
root.querySelector(
|
|
474
|
+
'#6_dynamic_text'
|
|
475
|
+
).textContent = DOMPurify.sanitize(`<b>${reqBody.orderNumber}</b>`);
|
|
476
|
+
const apeend: any = root.querySelector('head');
|
|
477
|
+
apeend.insertAdjacentHTML('beforeend', DOMPurify.sanitize(style));
|
|
478
|
+
|
|
479
|
+
let emailConfiguration: any = {
|
|
480
|
+
email: reqBody.emailTo,
|
|
481
|
+
emailTemplate: root.toString(),
|
|
482
|
+
subject: 'Order Confirmation',
|
|
483
|
+
};
|
|
484
|
+
let emailResponse: any = await this.pushEmails(emailConfiguration);
|
|
485
|
+
return emailResponse;
|
|
486
|
+
} catch (error: any) {
|
|
487
|
+
Logger.error(
|
|
488
|
+
'EmailHandler: Error in preparing email Request',
|
|
489
|
+
'prepareEmailRequest',
|
|
490
|
+
error
|
|
491
|
+
);
|
|
492
|
+
throw error;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
public async sendPlaceOrderEmailv1(reqBody: any) {
|
|
496
|
+
Logger.info('Redached sendPlaceOrderEmailv1', 'sendPlaceOrderEmailv1');
|
|
497
|
+
try {
|
|
498
|
+
let dataSource = new EmailDataSource();
|
|
499
|
+
await dataSource.fetchPageModel('orderPlaced');
|
|
500
|
+
const start = moment.tz(reqBody.dateTime, 'UTC'); // original timezone
|
|
501
|
+
let curentTimeZone = start;
|
|
502
|
+
curentTimeZone.tz(reqBody.timezoneOffset).format('Do MMMM YYYY, h:mm a');
|
|
503
|
+
const emailTemplate = path.resolve(__dirname, '../../../templates/orderPlaced.ejs');
|
|
504
|
+
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>.',emailTemplate);
|
|
505
|
+
let billingStr = '';
|
|
506
|
+
billingStr +=
|
|
507
|
+
Object.keys(reqBody.billing_address).length !== 0
|
|
508
|
+
? `${reqBody.billing_address.street_name}` ||
|
|
509
|
+
'' + `${reqBody.billing_address.city}` ||
|
|
510
|
+
'' + `${reqBody.billing_address.state}` ||
|
|
511
|
+
'' + `${reqBody.billing_address.country}` ||
|
|
512
|
+
'' + `${reqBody.billing_address.postal_code}` ||
|
|
513
|
+
''
|
|
514
|
+
: '';
|
|
515
|
+
let shippingStr = '';
|
|
516
|
+
shippingStr +=
|
|
517
|
+
Object.keys(reqBody.shipping_address).length !== 0
|
|
518
|
+
? `${reqBody.shipping_address.street_name}` ||
|
|
519
|
+
'' + `${reqBody.shipping_address.city}` ||
|
|
520
|
+
'' + ` ${reqBody.shipping_address.state}` ||
|
|
521
|
+
'' + ` ${reqBody.shipping_address.country}` ||
|
|
522
|
+
'' + `${reqBody.shipping_address.postal_code}` ||
|
|
523
|
+
''
|
|
524
|
+
: '';
|
|
525
|
+
let templateData = await ejs.renderFile(emailTemplate, {
|
|
526
|
+
userName: reqBody.userName,
|
|
527
|
+
orderNumber: reqBody.orderNumber,
|
|
528
|
+
completeAddressStr: billingStr || shippingStr,
|
|
529
|
+
total_tax: `${reqBody.total_tax}`,
|
|
530
|
+
total_price: `${reqBody.total_price}`,
|
|
531
|
+
data: reqBody.line_item,
|
|
532
|
+
});
|
|
533
|
+
if (templateData) {
|
|
534
|
+
let emailConfiguration: any = {
|
|
535
|
+
email: reqBody.emailTo,
|
|
536
|
+
emailTemplate: templateData,
|
|
537
|
+
subject: 'Order Confirmation',
|
|
538
|
+
};
|
|
539
|
+
let emailResponse: any = await this.pushEmails(emailConfiguration);
|
|
540
|
+
return emailResponse;
|
|
541
|
+
} else {
|
|
542
|
+
return 'Error while rendering template';
|
|
543
|
+
}
|
|
544
|
+
} catch (error: any) {
|
|
545
|
+
Logger.error(
|
|
546
|
+
'EmailHandler: Error in preparing email Request',
|
|
547
|
+
'prepareEmailRequest',
|
|
548
|
+
error
|
|
549
|
+
);
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
private async fetchEmailTemplateData(reqBody: any,documentpath?:string) {
|
|
555
|
+
try {
|
|
556
|
+
Logger.info('EmailHandler: Reached fetchEmailTemplateData', 'fetchEmailTemplateData');
|
|
557
|
+
let { email_type } = reqBody;
|
|
558
|
+
let dataSource = new EmailDataSource();
|
|
559
|
+
let templateData: any = {};
|
|
560
|
+
if (config?.MULTISITE_WITH_SOLR === 'true') {
|
|
561
|
+
let templateSolrRes: any = await dataSource.fetchPageModel(email_type,documentpath);
|
|
562
|
+
if (templateSolrRes?.length > 0) {
|
|
563
|
+
templateData.body = templateSolrRes?.[0]?.hclplatformx_Body || '';
|
|
564
|
+
templateData.subject = templateSolrRes?.[0]?.hclplatformx_Subject || '';
|
|
565
|
+
templateData.email_from = templateSolrRes?.[0]?.hclplatformx_To || '';
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
let templateRes: any = await new FormBuilderDao().fetch('email_templates', { name: email_type });
|
|
570
|
+
templateData.body = templateRes?.[0]?.body;
|
|
571
|
+
templateData.subject = templateRes?.[0]?.subject;
|
|
572
|
+
templateData.email_from = templateRes?.[0]?.to || '';
|
|
573
|
+
}
|
|
574
|
+
return templateData;
|
|
575
|
+
} catch (error: any) {
|
|
576
|
+
Logger.error('EmailHandler: Error in fetchEmailTemplateData', 'fetchEmailTemplateData', error);
|
|
577
|
+
throw error;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class EmailTemplateHandler {
|
|
2
|
+
constructor() {}
|
|
3
|
+
public static async prepareEmailTemplate(reqBody: any) {
|
|
4
|
+
let str = `<!DOCTYPE html>\r\n
|
|
5
|
+
<html>
|
|
6
|
+
\r\n
|
|
7
|
+
<head>\r\n </head>
|
|
8
|
+
\r\n
|
|
9
|
+
<body>
|
|
10
|
+
\r\n
|
|
11
|
+
<div>
|
|
12
|
+
\r\n
|
|
13
|
+
<div class=\"main_div\">
|
|
14
|
+
\r\n
|
|
15
|
+
<table>
|
|
16
|
+
\r\n
|
|
17
|
+
<tr>
|
|
18
|
+
\r\n
|
|
19
|
+
<td>
|
|
20
|
+
\r\n
|
|
21
|
+
<div class=\"table_div\">
|
|
22
|
+
\r\n
|
|
23
|
+
<table class=\"table_2\">
|
|
24
|
+
\r\n
|
|
25
|
+
<tr>
|
|
26
|
+
\r\n
|
|
27
|
+
<td valign=\"top\" class=\"w-400\">\r\n <img\r\n src=\"https://storage.googleapis.com/platx/dev/Setting/platform-x-logo-color%402x.png\"\r\n alt=\"logo\"\r\n class=\"w_h_30\"\r\n />\r\n </td>
|
|
28
|
+
\r\n
|
|
29
|
+
</tr>
|
|
30
|
+
\r\n
|
|
31
|
+
</table>
|
|
32
|
+
\r\n
|
|
33
|
+
<p class=\"username\">Hi <span id=\"1_dynamic_text\">{{username}}</span>,</p>
|
|
34
|
+
\r\n
|
|
35
|
+
<p class=\"main_text\">Your order <span id=\"6_dynamic_text\"><b>{{ordernumber}}</b></span> has been successfully placed for amount <span id=\"2_dynamic_text\"><b>{{totalAmt}}</b></span><span id=\"3_dynamic_text\"><b>{{currency}}</b></span>.</p>
|
|
36
|
+
\r\n
|
|
37
|
+
<p class=\"main_text\">Address Details<span id=\"4_dynamic_text\"><b>{{addressStr}}</b></span></p>
|
|
38
|
+
\r\n
|
|
39
|
+
<p class=\"main_text\">Calculated Tax on your order is <span id=\"5_dynamic_text\"><b>{{totaltax}}</b></span>
|
|
40
|
+
<div class=\"border\">
|
|
41
|
+
</div>
|
|
42
|
+
\r\n
|
|
43
|
+
<div>
|
|
44
|
+
\r\n
|
|
45
|
+
<p class=\"sub_text\">This emailer is copyright to Platform-X. All rights reserved.</p>
|
|
46
|
+
\r\n
|
|
47
|
+
</div>
|
|
48
|
+
\r\n
|
|
49
|
+
</div>
|
|
50
|
+
\r\n
|
|
51
|
+
</td>
|
|
52
|
+
\r\n
|
|
53
|
+
</tr>
|
|
54
|
+
\r\n
|
|
55
|
+
</table>
|
|
56
|
+
\r\n
|
|
57
|
+
</div>
|
|
58
|
+
\r\n
|
|
59
|
+
</div>
|
|
60
|
+
\r\n
|
|
61
|
+
</body>
|
|
62
|
+
\r\n
|
|
63
|
+
</html>`;
|
|
64
|
+
return str;
|
|
65
|
+
}
|
|
66
|
+
}
|