dt-common-device 13.3.14 → 13.3.16
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/dist/Integrations/twilio/twilio.service.js +0 -6
- package/dist/constants/Email.d.ts +43 -0
- package/dist/constants/Email.js +77 -0
- package/dist/emails/emailService.d.ts +16 -0
- package/dist/emails/emailService.js +343 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +4 -1
|
@@ -95,7 +95,6 @@ let TwilioService = (() => {
|
|
|
95
95
|
// -----------------------------
|
|
96
96
|
async sendSMS(data) {
|
|
97
97
|
const { propertyId, message, toNumber } = data;
|
|
98
|
-
console.log("TwilioService: sendSMS called with data:", data);
|
|
99
98
|
if (!toNumber) {
|
|
100
99
|
throw new Error("To number is required for sending SMS");
|
|
101
100
|
}
|
|
@@ -104,7 +103,6 @@ let TwilioService = (() => {
|
|
|
104
103
|
propertyId,
|
|
105
104
|
connectionProvider: IConnection_1.ConnectionProvider.Twilio,
|
|
106
105
|
});
|
|
107
|
-
console.log("-------TwilioService: queryConnections response:-----", response);
|
|
108
106
|
//need connectionId, clientSecret, metaData
|
|
109
107
|
const { clientId, clientSecret, metaData } = response[0];
|
|
110
108
|
const fromNumber = metaData?.fromNumber;
|
|
@@ -113,25 +111,21 @@ let TwilioService = (() => {
|
|
|
113
111
|
}
|
|
114
112
|
//find toNumber and sms_enabled from the property settings table based on the propertyId
|
|
115
113
|
const _settingsRes = await this.propertyRepository.getPropertyPreferences(propertyId);
|
|
116
|
-
console.log("-------TwilioService: getPropertyPreferences response:-----", _settingsRes);
|
|
117
114
|
if (!_settingsRes) {
|
|
118
115
|
throw new Error("Property settings not found");
|
|
119
116
|
}
|
|
120
117
|
const smsEnabled = _settingsRes?.settings?.notificationPreferences?.smsNotification?.enabled;
|
|
121
|
-
console.log("-------TwilioService: smsEnabled response:-----", smsEnabled);
|
|
122
118
|
if (!smsEnabled) {
|
|
123
119
|
throw new Error("SMS notifications are not enabled for this property");
|
|
124
120
|
}
|
|
125
121
|
//TODO: Need to do single tone pattern for the client
|
|
126
122
|
const client = (0, twilio_1.default)(clientId, clientSecret);
|
|
127
|
-
console.log("------TwilioService: Twilio client initialized------");
|
|
128
123
|
try {
|
|
129
124
|
const smsResponse = await client.messages.create({
|
|
130
125
|
body: message,
|
|
131
126
|
from: fromNumber,
|
|
132
127
|
to: toNumber,
|
|
133
128
|
});
|
|
134
|
-
console.log("---------TwilioService: SMS sent response:---------", smsResponse);
|
|
135
129
|
return smsResponse;
|
|
136
130
|
}
|
|
137
131
|
catch (error) {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const EMAIL_TEMPLATES: {
|
|
2
|
+
devicethread: string;
|
|
3
|
+
propertyCustom: string;
|
|
4
|
+
organizationCustom: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const getContactUsDetails: () => {
|
|
7
|
+
FROM_EMAIL_ADDRESS: string;
|
|
8
|
+
TO_EMAIL_ADDRESS: string;
|
|
9
|
+
PHONE: string;
|
|
10
|
+
} | undefined;
|
|
11
|
+
export declare const CONTACT_US_DETAILS: {
|
|
12
|
+
DEV: {
|
|
13
|
+
FROM_EMAIL_ADDRESS: string;
|
|
14
|
+
TO_EMAIL_ADDRESS: string;
|
|
15
|
+
PHONE: string;
|
|
16
|
+
};
|
|
17
|
+
QA: {
|
|
18
|
+
FROM_EMAIL_ADDRESS: string;
|
|
19
|
+
TO_EMAIL_ADDRESS: string;
|
|
20
|
+
PHONE: string;
|
|
21
|
+
};
|
|
22
|
+
EUT: {
|
|
23
|
+
FROM_EMAIL_ADDRESS: string;
|
|
24
|
+
TO_EMAIL_ADDRESS: string;
|
|
25
|
+
PHONE: string;
|
|
26
|
+
};
|
|
27
|
+
BETA: {
|
|
28
|
+
FROM_EMAIL_ADDRESS: string;
|
|
29
|
+
TO_EMAIL_ADDRESS: string;
|
|
30
|
+
PHONE: string;
|
|
31
|
+
};
|
|
32
|
+
SANDBOX: {
|
|
33
|
+
FROM_EMAIL_ADDRESS: string;
|
|
34
|
+
TO_EMAIL_ADDRESS: string;
|
|
35
|
+
PHONE: string;
|
|
36
|
+
};
|
|
37
|
+
PROD: {
|
|
38
|
+
FROM_EMAIL_ADDRESS: string;
|
|
39
|
+
TO_EMAIL_ADDRESS: string;
|
|
40
|
+
PHONE: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare const GetMaskedEmail: (email: string) => string;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetMaskedEmail = exports.CONTACT_US_DETAILS = exports.getContactUsDetails = exports.EMAIL_TEMPLATES = void 0;
|
|
4
|
+
const config_1 = require("../config/config");
|
|
5
|
+
exports.EMAIL_TEMPLATES = {
|
|
6
|
+
devicethread: `email-templates/devicethread/{{fileName}}`,
|
|
7
|
+
propertyCustom: `email-templates/custom/property/{{propertyId}}/{{fileName}}`,
|
|
8
|
+
organizationCustom: `email-templates/custom/organization/{{organizationId}}/{{fileName}}`,
|
|
9
|
+
};
|
|
10
|
+
const getContactUsDetails = () => {
|
|
11
|
+
try {
|
|
12
|
+
switch (process.env.NODE_ENV?.toLocaleLowerCase()) {
|
|
13
|
+
case 'qa-ecs': {
|
|
14
|
+
return exports.CONTACT_US_DETAILS.PROD;
|
|
15
|
+
}
|
|
16
|
+
case 'prod-ecs': {
|
|
17
|
+
return exports.CONTACT_US_DETAILS.QA;
|
|
18
|
+
}
|
|
19
|
+
case 'eut': {
|
|
20
|
+
return exports.CONTACT_US_DETAILS.EUT;
|
|
21
|
+
}
|
|
22
|
+
case 'stage': {
|
|
23
|
+
return exports.CONTACT_US_DETAILS.BETA;
|
|
24
|
+
}
|
|
25
|
+
case 'uat-ecs': {
|
|
26
|
+
return exports.CONTACT_US_DETAILS.EUT;
|
|
27
|
+
}
|
|
28
|
+
case 'green-ecs': {
|
|
29
|
+
return exports.CONTACT_US_DETAILS.PROD;
|
|
30
|
+
}
|
|
31
|
+
default: {
|
|
32
|
+
return exports.CONTACT_US_DETAILS.DEV;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
(0, config_1.getLogger)().error('GetContactUsDetails error ' + err.message);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.getContactUsDetails = getContactUsDetails;
|
|
41
|
+
exports.CONTACT_US_DETAILS = {
|
|
42
|
+
DEV: {
|
|
43
|
+
FROM_EMAIL_ADDRESS: 'dev-notifications@dthreaddev.com',
|
|
44
|
+
TO_EMAIL_ADDRESS: 'dev-support@dthreaddev.com',
|
|
45
|
+
PHONE: '(972) 945-8332',
|
|
46
|
+
},
|
|
47
|
+
QA: {
|
|
48
|
+
FROM_EMAIL_ADDRESS: 'qa-notifications@dthreaddev.com',
|
|
49
|
+
TO_EMAIL_ADDRESS: 'qa-support@dthreaddev.com',
|
|
50
|
+
PHONE: '(972) 945-8332',
|
|
51
|
+
},
|
|
52
|
+
EUT: {
|
|
53
|
+
FROM_EMAIL_ADDRESS: 'uat-notifications@devicethread.com',
|
|
54
|
+
TO_EMAIL_ADDRESS: 'uat-support@devicethread.com',
|
|
55
|
+
PHONE: '(972) 945-8332',
|
|
56
|
+
},
|
|
57
|
+
BETA: {
|
|
58
|
+
FROM_EMAIL_ADDRESS: 'beta-notifications@devicethread.com',
|
|
59
|
+
TO_EMAIL_ADDRESS: 'beta-support@devicethread.com',
|
|
60
|
+
PHONE: '(972) 945-8332',
|
|
61
|
+
},
|
|
62
|
+
SANDBOX: {
|
|
63
|
+
FROM_EMAIL_ADDRESS: 'sandbox-notifications@devicethread.com',
|
|
64
|
+
TO_EMAIL_ADDRESS: 'sandbox-support@devicethread.com',
|
|
65
|
+
PHONE: '(972) 945-8332',
|
|
66
|
+
},
|
|
67
|
+
PROD: {
|
|
68
|
+
FROM_EMAIL_ADDRESS: 'notifications@devicethread.com',
|
|
69
|
+
TO_EMAIL_ADDRESS: 'support@devicethread.com',
|
|
70
|
+
PHONE: '(972) 945-8332',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
const GetMaskedEmail = (email) => {
|
|
74
|
+
const maskedEmail = email.replace(/^(.)(.*)(.@.*)$/, (_, a, b, c) => a + b.replace(/./g, '*') + c);
|
|
75
|
+
return maskedEmail;
|
|
76
|
+
};
|
|
77
|
+
exports.GetMaskedEmail = GetMaskedEmail;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SESClient } from "@aws-sdk/client-ses";
|
|
2
|
+
export declare class EmailService {
|
|
3
|
+
private readonly s3Client;
|
|
4
|
+
private readonly sesClient;
|
|
5
|
+
private readonly propertyService;
|
|
6
|
+
constructor();
|
|
7
|
+
getTemplateForProperty(fileName: string, propertyId: string): Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput | undefined>;
|
|
8
|
+
getTemplateForOrganization(fileName: string, organizationId: string): Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
|
|
9
|
+
getTemplateFromS3(fileName: string, defaultEmail: boolean, propertyId?: string, organizationId?: string): Promise<{
|
|
10
|
+
bodyContents: string;
|
|
11
|
+
defaultEmail: boolean;
|
|
12
|
+
} | undefined>;
|
|
13
|
+
getRawHtmlTemplate(fileName: string, propertyId?: string, organizationId?: string): Promise<any>;
|
|
14
|
+
sendMail(mailData: any, pdfBuffer?: any): Promise<void>;
|
|
15
|
+
sendEmailWithAttachments(sesClient: SESClient, mailData: any, finalMessage: string, attachment: any): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
19
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
20
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
21
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
22
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
23
|
+
var _, done = false;
|
|
24
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
25
|
+
var context = {};
|
|
26
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
27
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
28
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
29
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
30
|
+
if (kind === "accessor") {
|
|
31
|
+
if (result === void 0) continue;
|
|
32
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
33
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
34
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
35
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
36
|
+
}
|
|
37
|
+
else if (_ = accept(result)) {
|
|
38
|
+
if (kind === "field") initializers.unshift(_);
|
|
39
|
+
else descriptor[key] = _;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
43
|
+
done = true;
|
|
44
|
+
};
|
|
45
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
46
|
+
var useValue = arguments.length > 2;
|
|
47
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
48
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
49
|
+
}
|
|
50
|
+
return useValue ? value : void 0;
|
|
51
|
+
};
|
|
52
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
53
|
+
var ownKeys = function(o) {
|
|
54
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
55
|
+
var ar = [];
|
|
56
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
57
|
+
return ar;
|
|
58
|
+
};
|
|
59
|
+
return ownKeys(o);
|
|
60
|
+
};
|
|
61
|
+
return function (mod) {
|
|
62
|
+
if (mod && mod.__esModule) return mod;
|
|
63
|
+
var result = {};
|
|
64
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
65
|
+
__setModuleDefault(result, mod);
|
|
66
|
+
return result;
|
|
67
|
+
};
|
|
68
|
+
})();
|
|
69
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
70
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
71
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
72
|
+
};
|
|
73
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
74
|
+
exports.EmailService = void 0;
|
|
75
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
76
|
+
const client_ses_1 = require("@aws-sdk/client-ses");
|
|
77
|
+
const fs = __importStar(require("fs"));
|
|
78
|
+
const mimetext_1 = require("mimetext");
|
|
79
|
+
const typedi_1 = __importStar(require("typedi"));
|
|
80
|
+
const Email_1 = require("../constants/Email");
|
|
81
|
+
const Property_service_1 = require("../entities/property/Property.service");
|
|
82
|
+
const config_1 = require("../config/config");
|
|
83
|
+
let EmailService = (() => {
|
|
84
|
+
let _classDecorators = [(0, typedi_1.Service)()];
|
|
85
|
+
let _classDescriptor;
|
|
86
|
+
let _classExtraInitializers = [];
|
|
87
|
+
let _classThis;
|
|
88
|
+
var EmailService = _classThis = class {
|
|
89
|
+
constructor() {
|
|
90
|
+
const credentials = {
|
|
91
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
|
|
92
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "",
|
|
93
|
+
};
|
|
94
|
+
const region = process.env.AWS_REGION ?? "us-east-1";
|
|
95
|
+
this.s3Client = new client_s3_1.S3Client({ credentials, region });
|
|
96
|
+
this.sesClient = new client_ses_1.SESClient({ credentials, region });
|
|
97
|
+
this.propertyService = typedi_1.default.get(Property_service_1.LocalPropertyService);
|
|
98
|
+
}
|
|
99
|
+
async getTemplateForProperty(fileName, propertyId) {
|
|
100
|
+
let res;
|
|
101
|
+
// let organizationData = (await prisma.propertyOrganizationRole.findFirst({
|
|
102
|
+
// where: { propertyId, type: OrganizationRoleType.OWNER_ORGANIZATION },
|
|
103
|
+
// }))!
|
|
104
|
+
try {
|
|
105
|
+
// check template on org folder
|
|
106
|
+
let organizationEmail = Email_1.EMAIL_TEMPLATES.propertyCustom
|
|
107
|
+
.replaceAll("{{fileName}}", `${fileName}`)
|
|
108
|
+
.replaceAll("{{propertyId}}", `${propertyId}`);
|
|
109
|
+
const organizationParams = {
|
|
110
|
+
Bucket: process.env.AWS_S3_ASSETS_BUCKET,
|
|
111
|
+
Key: organizationEmail,
|
|
112
|
+
};
|
|
113
|
+
res = await this.s3Client.send(new client_s3_1.GetObjectCommand(organizationParams));
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
//if not at org, check on property folder
|
|
117
|
+
if (error?.name === "NoSuchKey") {
|
|
118
|
+
let propertyEmail = Email_1.EMAIL_TEMPLATES.devicethread.replaceAll("{{fileName}}", `${fileName}`);
|
|
119
|
+
// .replaceAll('{{propertyId}}', `${propertyId}`)
|
|
120
|
+
const propertyParams = {
|
|
121
|
+
Bucket: process.env.AWS_S3_ASSETS_BUCKET,
|
|
122
|
+
Key: propertyEmail,
|
|
123
|
+
};
|
|
124
|
+
res = await this.s3Client.send(new client_s3_1.GetObjectCommand(propertyParams));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return res;
|
|
128
|
+
}
|
|
129
|
+
async getTemplateForOrganization(fileName, organizationId) {
|
|
130
|
+
let res;
|
|
131
|
+
let organizationEmail = Email_1.EMAIL_TEMPLATES.devicethread
|
|
132
|
+
.replaceAll("{{fileName}}", `${fileName}`)
|
|
133
|
+
.replaceAll("{{organizationId}}", `${organizationId}`);
|
|
134
|
+
const organizationParams = {
|
|
135
|
+
Bucket: process.env.AWS_S3_ASSETS_BUCKET,
|
|
136
|
+
Key: organizationEmail,
|
|
137
|
+
};
|
|
138
|
+
res = await this.s3Client.send(new client_s3_1.GetObjectCommand(organizationParams));
|
|
139
|
+
return res;
|
|
140
|
+
}
|
|
141
|
+
async getTemplateFromS3(fileName, defaultEmail, propertyId, organizationId) {
|
|
142
|
+
let dtEmail = Email_1.EMAIL_TEMPLATES.devicethread.replaceAll("{{fileName}}", `${fileName}`);
|
|
143
|
+
let res;
|
|
144
|
+
// try {
|
|
145
|
+
if (propertyId && defaultEmail == false) {
|
|
146
|
+
res = await this.getTemplateForProperty(fileName, propertyId);
|
|
147
|
+
//
|
|
148
|
+
}
|
|
149
|
+
else if (organizationId && defaultEmail == false) {
|
|
150
|
+
res = await this.getTemplateForOrganization(fileName, organizationId);
|
|
151
|
+
//
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
//default template
|
|
155
|
+
const params = { Bucket: process.env.AWS_S3_ASSETS_BUCKET, Key: dtEmail };
|
|
156
|
+
res = await this.s3Client.send(new client_s3_1.GetObjectCommand(params));
|
|
157
|
+
defaultEmail = true;
|
|
158
|
+
}
|
|
159
|
+
// } catch (error: any) {
|
|
160
|
+
// //default template
|
|
161
|
+
// if (error.Code === 'NoSuchKey') {
|
|
162
|
+
// const params = { Bucket: process.env.AWS_S3_ASSETS_BUCKET, Key: dtEmail }
|
|
163
|
+
// res = await s3Client.send(new GetObjectCommand(params))
|
|
164
|
+
// defaultEmail = true
|
|
165
|
+
// }
|
|
166
|
+
// }
|
|
167
|
+
const streamToString = async (stream) => {
|
|
168
|
+
const chunks = [];
|
|
169
|
+
for await (const chunk of stream) {
|
|
170
|
+
chunks.push(chunk);
|
|
171
|
+
}
|
|
172
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
173
|
+
};
|
|
174
|
+
if (res && res.Body) {
|
|
175
|
+
const bodyContents = await streamToString(res.Body);
|
|
176
|
+
return { bodyContents, defaultEmail };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async getRawHtmlTemplate(fileName, propertyId, organizationId) {
|
|
180
|
+
let dtEmail = false;
|
|
181
|
+
try {
|
|
182
|
+
// throw new Error('')
|
|
183
|
+
let body = await this.getTemplateFromS3(`${fileName}.html`, dtEmail, propertyId, organizationId);
|
|
184
|
+
if (body) {
|
|
185
|
+
if (body.defaultEmail) {
|
|
186
|
+
dtEmail = true;
|
|
187
|
+
}
|
|
188
|
+
// let footer: any = await this.getTemplateFromS3(
|
|
189
|
+
// 'footer.html',
|
|
190
|
+
// dtEmail,
|
|
191
|
+
// propertyId,
|
|
192
|
+
// organizationId,
|
|
193
|
+
// )
|
|
194
|
+
// let header: any = await this.getTemplateFromS3(
|
|
195
|
+
// 'header.html',
|
|
196
|
+
// dtEmail,
|
|
197
|
+
// propertyId,
|
|
198
|
+
// organizationId,
|
|
199
|
+
// )
|
|
200
|
+
// //
|
|
201
|
+
// let data = ''
|
|
202
|
+
// data += header.bodyContents
|
|
203
|
+
// //
|
|
204
|
+
// data = data.replace('<dt-body />', body.bodyContents)
|
|
205
|
+
// data = data.replace('<dt-footer />', footer.bodyContents)
|
|
206
|
+
// //
|
|
207
|
+
return body.bodyContents;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
//Comment above lines of code and use these to send emails from local templates
|
|
212
|
+
// let footer: any = await fs.promises.readFile(
|
|
213
|
+
// __dirname + '/../templates/footer.html',
|
|
214
|
+
// )
|
|
215
|
+
// footer = footer.toString()
|
|
216
|
+
// let header: any = await fs.promises.readFile(
|
|
217
|
+
// __dirname + '/../templates/header.html',
|
|
218
|
+
// )
|
|
219
|
+
// header = header.toString()
|
|
220
|
+
let localBody = await fs.promises.readFile(__dirname + `/../templates/${fileName}.html`);
|
|
221
|
+
localBody = localBody.toString();
|
|
222
|
+
// Replacing the custom body and footer tag with actual content
|
|
223
|
+
// header = header.replace('<dt-body />', localBody)
|
|
224
|
+
// header = header.replace('<dt-footer />', footer)
|
|
225
|
+
//
|
|
226
|
+
return localBody;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async sendMail(mailData, pdfBuffer = null) {
|
|
230
|
+
try {
|
|
231
|
+
const { toAddr, subject, message, ccAddr } = mailData;
|
|
232
|
+
let imageURL = "";
|
|
233
|
+
if (mailData.propertyId) {
|
|
234
|
+
const propertyDetail = await this.propertyService.getProperty(mailData.propertyId);
|
|
235
|
+
imageURL = propertyDetail?.imageURL ?? "";
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
imageURL = `https://api-sandbox-new.devicethread.com/dt-logo.png`;
|
|
239
|
+
}
|
|
240
|
+
const CONTACT_US_DETAILS = (0, Email_1.getContactUsDetails)();
|
|
241
|
+
const from = CONTACT_US_DETAILS?.FROM_EMAIL_ADDRESS;
|
|
242
|
+
if (!process.env.AWS_ACCESS_KEY_ID ||
|
|
243
|
+
!process.env.AWS_SECRET_ACCESS_KEY) {
|
|
244
|
+
throw new Error("AWS credentials are not set");
|
|
245
|
+
}
|
|
246
|
+
// Section below is replacing the global variables from template like contact us email, phone and current year.
|
|
247
|
+
const currentYear = new Date().getFullYear().toString();
|
|
248
|
+
// const logo: any = await GetLogo(ctx);
|
|
249
|
+
let finalMessage = message
|
|
250
|
+
.replaceAll("{{year}}", currentYear)
|
|
251
|
+
.replaceAll("{{contactUsPhone}}", `${CONTACT_US_DETAILS?.PHONE}`)
|
|
252
|
+
.replaceAll("{{contactUsEmail}}", `${CONTACT_US_DETAILS?.TO_EMAIL_ADDRESS}`)
|
|
253
|
+
.replaceAll("{{logo}}", `${imageURL}`);
|
|
254
|
+
// .replaceAll('{{logo}}', `${logo}`);
|
|
255
|
+
//
|
|
256
|
+
const params = {
|
|
257
|
+
Destination: {
|
|
258
|
+
ToAddresses: toAddr,
|
|
259
|
+
},
|
|
260
|
+
Message: {
|
|
261
|
+
Body: {
|
|
262
|
+
Html: {
|
|
263
|
+
Charset: "UTF-8",
|
|
264
|
+
Data: finalMessage,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
Subject: {
|
|
268
|
+
Charset: "UTF-8",
|
|
269
|
+
Data: subject,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
Source: from, // SENDER_ADDRESS
|
|
273
|
+
ReplyToAddresses: [CONTACT_US_DETAILS?.TO_EMAIL_ADDRESS],
|
|
274
|
+
};
|
|
275
|
+
// Add CC addresses if present
|
|
276
|
+
if (ccAddr && Array.isArray(ccAddr) && ccAddr.length > 0) {
|
|
277
|
+
params.Destination.CcAddresses = ccAddr;
|
|
278
|
+
}
|
|
279
|
+
(0, config_1.getLogger)().info(`sending email with params: ${JSON.stringify(toAddr)}`);
|
|
280
|
+
if (ccAddr && ccAddr.length > 0) {
|
|
281
|
+
(0, config_1.getLogger)().info(`CC addresses: ${JSON.stringify(ccAddr)}`);
|
|
282
|
+
}
|
|
283
|
+
mailData.from = CONTACT_US_DETAILS?.FROM_EMAIL_ADDRESS;
|
|
284
|
+
if (pdfBuffer) {
|
|
285
|
+
// this.sendEmailWithAttachments(this.sesClient, mailData, finalMessage, pdfBuffer)
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
await this.sesClient.send(new client_ses_1.SendEmailCommand(params));
|
|
289
|
+
}
|
|
290
|
+
const maskedEmailsList = toAddr.map((email) => (0, Email_1.GetMaskedEmail)(email));
|
|
291
|
+
(0, config_1.getLogger)().info(`Sending email to: ${maskedEmailsList.join(", ")}`);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
(0, config_1.getLogger)().error("sendMail: Error", error);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async sendEmailWithAttachments(sesClient, mailData, finalMessage, attachment) {
|
|
298
|
+
const { toAddr, subject, ccAddr } = mailData;
|
|
299
|
+
// const from = CONTACT_US_DETAILS?.FROM_EMAIL_ADDRESS
|
|
300
|
+
const from = mailData.from;
|
|
301
|
+
const mimeMessage = (0, mimetext_1.createMimeMessage)();
|
|
302
|
+
mimeMessage.setSender(from);
|
|
303
|
+
// Set recipients - combine to and cc for mime message
|
|
304
|
+
const allRecipients = [...toAddr];
|
|
305
|
+
if (ccAddr && Array.isArray(ccAddr) && ccAddr.length > 0) {
|
|
306
|
+
allRecipients.push(...ccAddr);
|
|
307
|
+
}
|
|
308
|
+
mimeMessage.setRecipients(allRecipients);
|
|
309
|
+
// Add CC header if CC addresses are present
|
|
310
|
+
if (ccAddr && Array.isArray(ccAddr) && ccAddr.length > 0) {
|
|
311
|
+
mimeMessage.setHeader("Cc", ccAddr.join(", "));
|
|
312
|
+
}
|
|
313
|
+
mimeMessage.setSubject(subject);
|
|
314
|
+
mimeMessage.addMessage({ contentType: "text/html", data: finalMessage });
|
|
315
|
+
if (attachment) {
|
|
316
|
+
mimeMessage.addAttachment({
|
|
317
|
+
filename: "report.pdf",
|
|
318
|
+
contentType: "application/pdf",
|
|
319
|
+
data: attachment.toString("base64"),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
const params = {
|
|
323
|
+
Destinations: allRecipients,
|
|
324
|
+
RawMessage: {
|
|
325
|
+
Data: Buffer.from(mimeMessage.asRaw(), "utf8"), // the raw message data needs to be sent as uint8array
|
|
326
|
+
},
|
|
327
|
+
Source: mimeMessage.getSender()?.addr,
|
|
328
|
+
};
|
|
329
|
+
// @ts-ignore
|
|
330
|
+
await sesClient.send(new client_ses_1.SendRawEmailCommand(params));
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
__setFunctionName(_classThis, "EmailService");
|
|
334
|
+
(() => {
|
|
335
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
336
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
337
|
+
EmailService = _classThis = _classDescriptor.value;
|
|
338
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
339
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
340
|
+
})();
|
|
341
|
+
return EmailService = _classThis;
|
|
342
|
+
})();
|
|
343
|
+
exports.EmailService = EmailService;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -73,3 +73,5 @@ __exportStar(require("./webhooks"), exports);
|
|
|
73
73
|
__exportStar(require("./Integrations"), exports);
|
|
74
74
|
//Export Twilio Service
|
|
75
75
|
__exportStar(require("./Integrations/twilio"), exports);
|
|
76
|
+
// Export Email Service
|
|
77
|
+
__exportStar(require("./emails/emailService"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dt-common-device",
|
|
3
|
-
"version": "13.3.
|
|
3
|
+
"version": "13.3.16",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -43,12 +43,15 @@
|
|
|
43
43
|
"typescript": "^5.8.3"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
+
"@aws-sdk/client-s3": "^3.835.0",
|
|
47
|
+
"@aws-sdk/client-ses": "3.1003.0",
|
|
46
48
|
"axios": "1.10.0",
|
|
47
49
|
"bullmq": "5.56.4",
|
|
48
50
|
"dt-audit-library": "1.7.1",
|
|
49
51
|
"dt-pub-sub": "^1.0.0",
|
|
50
52
|
"ioredis": "5.6.1",
|
|
51
53
|
"lodash": "^4.17.21",
|
|
54
|
+
"mimetext": "3.0.28",
|
|
52
55
|
"mongoose": "8.17.1",
|
|
53
56
|
"pg": "8.16.3",
|
|
54
57
|
"svix": "1.84.1",
|