@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.
Files changed (151) hide show
  1. package/README.md +7 -7
  2. package/dist/jest-setup.js +28 -0
  3. package/dist/jest-setup.js.map +1 -0
  4. package/dist/src/common/controllers/common_controller.js +72 -0
  5. package/dist/src/common/controllers/common_controller.js.map +1 -0
  6. package/dist/src/common/controllers/index.js +29 -0
  7. package/dist/src/common/controllers/index.js.map +1 -0
  8. package/dist/src/common/middleware/commonMiddleware.js +141 -0
  9. package/dist/src/common/middleware/commonMiddleware.js.map +1 -0
  10. package/dist/src/common/service/requestService.js +79 -1
  11. package/dist/src/common/service/requestService.js.map +1 -0
  12. package/dist/src/common/service/twilioService.js +3 -11
  13. package/dist/src/common/service/twilioService.js.map +1 -0
  14. package/dist/src/common/util/commonUtil.js +119 -1
  15. package/dist/src/common/util/commonUtil.js.map +1 -0
  16. package/dist/src/common/util/constants.js +18 -0
  17. package/dist/src/common/util/constants.js.map +1 -0
  18. package/dist/src/common/util/errorHandler.js +4 -6
  19. package/dist/src/common/util/errorHandler.js.map +1 -0
  20. package/dist/src/common/util/httpCodes.js +26 -0
  21. package/dist/src/common/util/httpCodes.js.map +1 -0
  22. package/dist/src/common/util/logger.js +1 -1
  23. package/dist/src/common/util/logger.js.map +1 -0
  24. package/dist/src/common/util/requestTracer.js +18 -1
  25. package/dist/src/common/util/requestTracer.js.map +1 -0
  26. package/dist/src/common/util/solrConnector.js.map +1 -0
  27. package/dist/src/config/index.js +49 -4
  28. package/dist/src/config/index.js.map +1 -0
  29. package/dist/src/platform-x/app.js +35 -0
  30. package/dist/src/platform-x/app.js.map +1 -0
  31. package/dist/src/platform-x/constants/index.js +2 -14
  32. package/dist/src/platform-x/constants/index.js.map +1 -0
  33. package/dist/src/platform-x/constants/style.js +98 -98
  34. package/dist/src/platform-x/constants/style.js.map +1 -0
  35. package/dist/src/platform-x/controllers/cronController.js +399 -0
  36. package/dist/src/platform-x/controllers/cronController.js.map +1 -0
  37. package/dist/src/platform-x/controllers/fileUploadController.js +76 -0
  38. package/dist/src/platform-x/controllers/fileUploadController.js.map +1 -0
  39. package/dist/src/platform-x/controllers/graphRESTControllers.js +183 -0
  40. package/dist/src/platform-x/controllers/graphRESTControllers.js.map +1 -0
  41. package/dist/src/platform-x/controllers/index.js +30 -0
  42. package/dist/src/platform-x/controllers/index.js.map +1 -0
  43. package/dist/src/platform-x/controllers/siteDomainController.js +74 -0
  44. package/dist/src/platform-x/controllers/siteDomainController.js.map +1 -0
  45. package/dist/src/platform-x/dataSource/emailDataSource.js.map +1 -0
  46. package/dist/src/platform-x/database/connection.js +3 -6
  47. package/dist/src/platform-x/database/connection.js.map +1 -0
  48. package/dist/src/platform-x/database/dao/formBuilder.dao.js +1 -1
  49. package/dist/src/platform-x/database/dao/formBuilder.dao.js.map +1 -0
  50. package/dist/src/platform-x/database/dao/siteDomain.dao.js +73 -0
  51. package/dist/src/platform-x/database/dao/siteDomain.dao.js.map +1 -0
  52. package/dist/src/platform-x/database/index.js.map +1 -0
  53. package/dist/src/platform-x/{interface/interface.js → database/interfaces/site_domain.interface.js} +1 -1
  54. package/dist/src/platform-x/database/interfaces/site_domain.interface.js.map +1 -0
  55. package/dist/src/platform-x/database/models/formBuilder.model.js.map +1 -0
  56. package/dist/src/platform-x/database/models/site_domains.model.js +51 -0
  57. package/dist/src/platform-x/database/models/site_domains.model.js.map +1 -0
  58. package/dist/src/platform-x/routes/index.js +19 -0
  59. package/dist/src/platform-x/routes/index.js.map +1 -0
  60. package/dist/src/platform-x/services/cron.services.js +117 -0
  61. package/dist/src/platform-x/services/cron.services.js.map +1 -0
  62. package/dist/src/platform-x/util/emailHandler.js +53 -137
  63. package/dist/src/platform-x/util/emailHandler.js.map +1 -0
  64. package/dist/src/platform-x/util/emailTemplate.js +63 -60
  65. package/dist/src/platform-x/util/emailTemplate.js.map +1 -0
  66. package/dist/src/platform-x/util/solr-data-source/SolrHttpDataSource.js +2 -0
  67. package/dist/src/platform-x/util/solr-data-source/SolrHttpDataSource.js.map +1 -0
  68. package/dist/src/server.js +38 -0
  69. package/dist/src/server.js.map +1 -0
  70. package/dist/swagger.json +247 -0
  71. package/dist/test/controllers/common_controller.spec.js +79 -0
  72. package/dist/test/controllers/common_controller.spec.js.map +1 -0
  73. package/dist/test/middleware/commonMiddleware.spec.js +88 -0
  74. package/dist/test/middleware/commonMiddleware.spec.js.map +1 -0
  75. package/dist/test/platform-x/controllers/graphRESTControllers.spec.js +195 -0
  76. package/dist/test/platform-x/controllers/graphRESTControllers.spec.js.map +1 -0
  77. package/dist/test/platform-x/datasource/emailDataSource.spec.js +81 -0
  78. package/dist/test/platform-x/datasource/emailDataSource.spec.js.map +1 -0
  79. package/dist/test/platform-x/util/emailHandler.spec.js +474 -0
  80. package/dist/test/platform-x/util/emailHandler.spec.js.map +1 -0
  81. package/dist/test/platform-x/util/solr-data-source/SolrHttpDataSource.spec.js +80 -0
  82. package/dist/test/platform-x/util/solr-data-source/SolrHttpDataSource.spec.js.map +1 -0
  83. package/dist/test/services/requestService.spec.js +108 -0
  84. package/dist/test/services/requestService.spec.js.map +1 -0
  85. package/dist/test/services/requestServiceGet.spec.js +43 -0
  86. package/dist/test/services/requestServiceGet.spec.js.map +1 -0
  87. package/dist/test/src/common/service/twilioService.spec.js +65 -0
  88. package/dist/test/src/common/service/twilioService.spec.js.map +1 -0
  89. package/dist/test/util/commonUtil.spec.js +110 -0
  90. package/dist/test/util/commonUtil.spec.js.map +1 -0
  91. package/dist/test/util/logger.spec.js +51 -0
  92. package/dist/test/util/logger.spec.js.map +1 -0
  93. package/dist/test/util/requestTracer.spec.js +64 -0
  94. package/dist/test/util/requestTracer.spec.js.map +1 -0
  95. package/dist/test/util/solrconnector.spec.js +145 -0
  96. package/dist/test/util/solrconnector.spec.js.map +1 -0
  97. package/package.json +66 -62
  98. package/postman_collection/HEP_Environment.postman_environment.json +44 -44
  99. package/postman_collection/hep-notification.postman_collection.json +55 -55
  100. package/reports/output.jtl +1 -1
  101. package/reports/scripts/jmeter_sendgrid.js +34 -34
  102. package/reports/scripts/newman_sendgrid.js +40 -40
  103. package/reports/scripts/sendgrid.js +40 -40
  104. package/reports/scripts/trivy_sendgrid.js +40 -40
  105. package/src/common/service/requestService.ts +87 -0
  106. package/{dist/src/common/service/secretKeyManager.services.js → src/common/service/secretKeyManager.services.ts} +1 -2
  107. package/src/common/service/twilioService.ts +58 -0
  108. package/src/common/util/commonUtil.ts +39 -0
  109. package/src/common/util/errorHandler.ts +120 -0
  110. package/src/common/util/logger.ts +215 -0
  111. package/src/common/util/requestTracer.ts +10 -0
  112. package/src/common/util/solrConnector.ts +319 -0
  113. package/src/config/index.ts +35 -0
  114. package/src/index.ts +34 -0
  115. package/src/platform-x/constants/index.ts +20 -0
  116. package/src/platform-x/constants/style.ts +99 -0
  117. package/src/platform-x/dataSource/emailDataSource.ts +34 -0
  118. package/src/platform-x/database/connection.ts +47 -0
  119. package/src/platform-x/database/dao/formBuilder.dao.ts +33 -0
  120. package/src/platform-x/database/index.ts +7 -0
  121. package/src/platform-x/database/models/formBuilder.model.ts +23 -0
  122. package/src/platform-x/util/emailHandler.ts +580 -0
  123. package/src/platform-x/util/emailTemplate.ts +66 -0
  124. package/src/platform-x/util/solr-data-source/SolrHttpDataSource.ts +97 -0
  125. package/{dist → src}/templates/orderPlaced.ejs +172 -172
  126. package/{dist → src}/templates/orderPlaced.html +189 -189
  127. package/tsconfig.json +73 -0
  128. package/dist/src/common/service/requestService.d.ts +0 -26
  129. package/dist/src/common/service/secretKeyManager.services.d.ts +0 -0
  130. package/dist/src/common/service/twilioService.d.ts +0 -19
  131. package/dist/src/common/util/commonUtil.d.ts +0 -22
  132. package/dist/src/common/util/errorHandler.d.ts +0 -44
  133. package/dist/src/common/util/logger.d.ts +0 -68
  134. package/dist/src/common/util/requestTracer.d.ts +0 -2
  135. package/dist/src/common/util/secretKeyManager.d.ts +0 -7
  136. package/dist/src/common/util/secretKeyManager.js +0 -58
  137. package/dist/src/common/util/solrConnector.d.ts +0 -35
  138. package/dist/src/config/index.d.ts +0 -30
  139. package/dist/src/index.d.ts +0 -5
  140. package/dist/src/index.js +0 -20
  141. package/dist/src/platform-x/constants/index.d.ts +0 -18
  142. package/dist/src/platform-x/constants/style.d.ts +0 -1
  143. package/dist/src/platform-x/dataSource/emailDataSource.d.ts +0 -5
  144. package/dist/src/platform-x/database/connection.d.ts +0 -8
  145. package/dist/src/platform-x/database/dao/formBuilder.dao.d.ts +0 -9
  146. package/dist/src/platform-x/database/index.d.ts +0 -7
  147. package/dist/src/platform-x/database/models/formBuilder.model.d.ts +0 -34
  148. package/dist/src/platform-x/interface/interface.d.ts +0 -4
  149. package/dist/src/platform-x/util/emailHandler.d.ts +0 -62
  150. package/dist/src/platform-x/util/emailTemplate.d.ts +0 -4
  151. 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
+ }