@8ms/helpers 2.2.9 → 2.2.12
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/.github/workflows/deploy_npmjs.yml +3 -0
- package/_class/BaseClass.js +43 -52
- package/_class/BaseNamespace.js +17 -20
- package/_class/index.js +2 -7
- package/adverity/getJobs.js +7 -11
- package/adverity/index.js +51 -54
- package/adverity/server.js +1 -5
- package/api/ApiResponseClass.js +84 -88
- package/api/functions.js +13 -22
- package/api/index.js +3 -19
- package/api/types.js +5 -9
- package/array/index.js +3 -11
- package/atInternet/index.js +10 -13
- package/aws/ec2/AwsEc2Namespace.js +34 -74
- package/aws/ec2/server.js +5 -9
- package/aws/ecs/AwsEcsNamespace.js +110 -150
- package/aws/ecs/server.js +5 -9
- package/aws/glue/AwsGlueNamespace.js +26 -66
- package/aws/glue/server.js +5 -9
- package/aws/isResponse200.js +3 -7
- package/aws/lambda/AwsLambdaNamespace.js +62 -102
- package/aws/lambda/server.js +6 -11
- package/aws/s3/AwsS3Namespace.js +347 -390
- package/aws/s3/payload.js +29 -32
- package/aws/s3/server.js +9 -14
- package/aws/server.js +5 -10
- package/aws/ses/AwsSesNamespace.js +36 -76
- package/aws/ses/SimpleEmail.js +267 -304
- package/aws/ses/server.js +6 -11
- package/aws/sqs/AwsSqsNamespace.js +49 -89
- package/aws/sqs/server.js +5 -9
- package/aws/ssm/AwsSsmNamespace.js +43 -79
- package/aws/ssm/server.js +5 -9
- package/axios/deleteRequest.js +8 -15
- package/axios/get.js +8 -15
- package/axios/index.js +3 -9
- package/axios/post.js +8 -15
- package/boolean/index.js +3 -10
- package/brightData/serpApi/buildGoogleSerpUrl.js +1 -5
- package/brightData/serpApi/buildGoogleTrendsUrl.js +1 -5
- package/brightData/serpApi/getAsyncRequestId.js +8 -12
- package/brightData/serpApi/getAsyncResults.js +8 -12
- package/brightData/serpApi/getRealtime.js +3 -7
- package/brightData/serpApi/server.js +6 -14
- package/brightData/server.js +2 -7
- package/brightData/webScraperIde/getBatch.js +3 -7
- package/brightData/webScraperIde/getRealtime.js +11 -15
- package/brightData/webScraperIde/server.js +2 -7
- package/cache/server.js +2 -7
- package/cache/test/cache.test.js +4 -6
- package/crud/index.js +1 -4
- package/crypto/getDecrypt.js +2 -39
- package/crypto/getEncrypt.js +2 -39
- package/crypto/getRandom.js +1 -5
- package/crypto/getSha256.js +4 -41
- package/crypto/index.js +4 -11
- package/date/calculation.js +70 -99
- package/date/financialYear.js +16 -23
- package/date/format.js +40 -61
- package/date/index.js +4 -20
- package/date/type.js +4 -7
- package/environment/index.js +15 -25
- package/eskimi/getAgeGroup.js +3 -7
- package/eskimi/getData.js +3 -7
- package/eskimi/getDevice.js +3 -7
- package/eskimi/getGender.js +3 -7
- package/eskimi/server.js +23 -26
- package/file/index.js +8 -46
- package/geo/countries.js +1 -4
- package/geo/index.js +2 -7
- package/geo/languages.js +1 -4
- package/google/bigQuery/GoogleBigQueryNamespace.js +108 -148
- package/google/bigQuery/loadData.js +1 -5
- package/google/bigQuery/server.js +8 -14
- package/google/server.js +1 -5
- package/google/sheets/GoogleSheetsNamespace.js +34 -74
- package/google/sheets/getAssociatedData.js +1 -5
- package/google/sheets/server.js +8 -14
- package/google/storage/GoogleCloudStorageNamespace.js +62 -102
- package/google/storage/server.js +6 -10
- package/googleAds/GoogleAdsNamespace.js +28 -68
- package/googleAds/keywordPlanner/server.js +32 -35
- package/googleAds/server.js +6 -10
- package/googlePageSpeed/GooglePageSpeedNamespace.js +21 -28
- package/googlePageSpeed/server.js +8 -12
- package/googleSearchIncidents/server.js +28 -32
- package/greenDomain/server.js +17 -21
- package/inngest/server.js +1 -4
- package/json/getJsonNewline.js +3 -7
- package/json/index.js +2 -7
- package/json/isJson.js +1 -5
- package/littleWarden/LittleWardenNamespace.js +24 -31
- package/littleWarden/getUrlStatus.js +3 -7
- package/littleWarden/server.js +14 -22
- package/lumar/api/buildRequest.js +14 -18
- package/lumar/api/getData.js +3 -7
- package/lumar/api/initClient.js +3 -7
- package/lumar/api/server.js +6 -12
- package/lumar/graphql/columns.js +1 -4
- package/lumar/graphql/getData.js +3 -7
- package/lumar/graphql/initClient.js +3 -7
- package/lumar/graphql/queries/crawl.js +1 -2
- package/lumar/graphql/queries/getCrawls.js +1 -3
- package/lumar/graphql/queries/getReportDifferences.js +3 -5
- package/lumar/graphql/queries/getRows.js +1 -3
- package/lumar/graphql/queries/getTotals.js +1 -3
- package/lumar/graphql/queries/row.js +1 -2
- package/lumar/graphql/reportTemplates.js +1 -4
- package/lumar/graphql/server.js +7 -15
- package/myTarget/server.js +3 -7
- package/nextAuth/index.js +2 -6
- package/nextAuth/isSessionReady.js +1 -5
- package/nextJs/client/LazyLoad.js +5 -12
- package/nextJs/client.js +1 -5
- package/nextJs/index.js +2 -7
- package/number/format.js +3 -7
- package/number/formatCurrency.js +1 -5
- package/number/getDecimal.js +3 -7
- package/number/getNumber.js +3 -7
- package/number/getPercentIncrease.js +4 -8
- package/number/getSafeDivide.js +6 -10
- package/number/index.js +6 -15
- package/object/index.js +1 -5
- package/object/replaceKeys.js +3 -7
- package/onePassword/OnePasswordNamespace.js +36 -76
- package/onePassword/server.js +3 -7
- package/openAi/OpenAiNamespace.js +32 -39
- package/openAi/server.js +6 -10
- package/package.json +224 -122
- package/prisma/PrismaNamespace.js +53 -93
- package/prisma/getDecimal.js +5 -12
- package/prisma/server.js +4 -9
- package/scripts/generate-exports.js +50 -0
- package/snapchat/SnapchatNamespace.js +20 -27
- package/snapchat/server.js +6 -10
- package/sorting/byNumberAscending.js +1 -5
- package/sorting/byNumberDescending.js +1 -5
- package/sorting/byStringAscending.js +1 -5
- package/sorting/byStringDescending.js +1 -5
- package/sorting/index.js +4 -11
- package/stream/server.js +1 -5
- package/stream/sort.js +1 -5
- package/string/getCapitalised.js +3 -7
- package/string/getClean.js +17 -21
- package/string/getFolder.js +3 -10
- package/string/getProperCase.js +4 -8
- package/string/getString.js +8 -15
- package/string/getStringFromStream.js +1 -5
- package/string/getUnescaped.js +3 -10
- package/string/getWithoutAccents.js +1 -5
- package/string/getWithoutHtmlTags.js +1 -5
- package/string/getWithoutPunctuation.js +1 -5
- package/string/getWithoutUnderscores.js +1 -5
- package/string/getWithoutWhitespaces.js +1 -5
- package/string/index.js +12 -27
- package/string/reservedWords.js +5 -9
- package/swr/index.js +9 -18
- package/upTimeRobot/UpTimeRobotNamespace.js +32 -42
- package/upTimeRobot/server.js +11 -15
- package/url/index.js +12 -23
- package/url/server.js +1 -5
- package/url/writeUrlContents.js +6 -46
- package/util/defaultTo.js +5 -12
- package/util/getBrotliCompressed.js +3 -10
- package/util/getBrotliDecompressed.js +3 -10
- package/util/getClean.js +5 -9
- package/util/getError.js +1 -5
- package/util/getGzipCompressed.js +3 -10
- package/util/getGzipDecompressed.js +3 -10
- package/util/getWithoutHash.js +1 -5
- package/util/getWithoutParameter.js +1 -5
- package/util/index.js +7 -17
- package/util/isUndefined.js +3 -7
- package/util/promiseChunks.js +6 -10
- package/util/server.js +4 -11
- package/util/sleep.js +1 -5
- package/webWorker/index.js +1 -4
- package/xml/getXml.js +3 -7
package/aws/ses/SimpleEmail.js
CHANGED
|
@@ -1,311 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.SimpleEmail = void 0;
|
|
40
|
-
const uniq_1 = __importDefault(require("lodash/uniq"));
|
|
41
|
-
const _class_1 = require("../../_class");
|
|
1
|
+
import uniq from "lodash/uniq";
|
|
2
|
+
import { BaseClass } from "../../_class";
|
|
42
3
|
/**
|
|
43
4
|
* Class to build and send an AWS SES email.
|
|
44
5
|
*/
|
|
45
|
-
class SimpleEmail extends
|
|
6
|
+
export class SimpleEmail extends BaseClass {
|
|
7
|
+
from;
|
|
8
|
+
to = [];
|
|
9
|
+
cc = [];
|
|
10
|
+
bcc = [];
|
|
11
|
+
html;
|
|
12
|
+
subject;
|
|
13
|
+
attachments = [];
|
|
46
14
|
constructor({ bcc, cc, from, html, subject, to, attachments }) {
|
|
47
15
|
super();
|
|
48
|
-
this.to = [];
|
|
49
|
-
this.cc = [];
|
|
50
|
-
this.bcc = [];
|
|
51
|
-
this.attachments = [];
|
|
52
|
-
this.setFrom = (from) => {
|
|
53
|
-
return this._setValue("from", from);
|
|
54
|
-
};
|
|
55
|
-
this.setHtml = (html) => {
|
|
56
|
-
return this._setValue("html", html);
|
|
57
|
-
};
|
|
58
|
-
this.setSubject = (subject) => {
|
|
59
|
-
return this._setValue("subject", subject);
|
|
60
|
-
};
|
|
61
|
-
this.setAttachments = (attachments) => {
|
|
62
|
-
return this._setValue("attachments", attachments);
|
|
63
|
-
};
|
|
64
|
-
this.addAttachment = (attachment) => {
|
|
65
|
-
this.attachments.push(attachment);
|
|
66
|
-
return this;
|
|
67
|
-
};
|
|
68
|
-
this.addAttachmentFromdata = (filename, data, contentType) => {
|
|
69
|
-
return this.addAttachment({
|
|
70
|
-
filename,
|
|
71
|
-
data,
|
|
72
|
-
contentType: contentType || this._getContentTypeFromFilename(filename)
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
|
-
this.addAttachmentFromUrl = (filename, url, contentType) => {
|
|
76
|
-
return this.addAttachment({
|
|
77
|
-
filename,
|
|
78
|
-
url,
|
|
79
|
-
contentType: contentType || this._getContentTypeFromFilename(filename)
|
|
80
|
-
});
|
|
81
|
-
};
|
|
82
|
-
this.clearAttachments = () => {
|
|
83
|
-
this.attachments = [];
|
|
84
|
-
return this;
|
|
85
|
-
};
|
|
86
|
-
this.pushBcc = (recipient) => {
|
|
87
|
-
return this._push("bcc", recipient);
|
|
88
|
-
};
|
|
89
|
-
this.pushCc = (recipient) => {
|
|
90
|
-
return this._push("cc", recipient);
|
|
91
|
-
};
|
|
92
|
-
this.pushTo = (recipient) => {
|
|
93
|
-
return this._push("to", recipient);
|
|
94
|
-
};
|
|
95
|
-
this.setBcc = (recipient) => {
|
|
96
|
-
return this._setArray("bcc", recipient);
|
|
97
|
-
};
|
|
98
|
-
this.setCc = (recipient) => {
|
|
99
|
-
return this._setArray("cc", recipient);
|
|
100
|
-
};
|
|
101
|
-
this.setTo = (recipient) => {
|
|
102
|
-
return this._setArray("to", recipient);
|
|
103
|
-
};
|
|
104
|
-
this.getSendParam = async () => {
|
|
105
|
-
// For emails with attachments, we need to use SendRawEmail instead of SendEmail
|
|
106
|
-
if (this.attachments.length > 0) {
|
|
107
|
-
return await this._getRawEmailParams();
|
|
108
|
-
}
|
|
109
|
-
// https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/ses-examples-sending-email.html
|
|
110
|
-
const params = {
|
|
111
|
-
Destination: {
|
|
112
|
-
BccAddresses: this._filterRecipients("bcc"),
|
|
113
|
-
CcAddresses: this._filterRecipients("cc"),
|
|
114
|
-
ToAddresses: this._filterRecipients("to"),
|
|
115
|
-
},
|
|
116
|
-
Message: {
|
|
117
|
-
Body: {
|
|
118
|
-
Html: {
|
|
119
|
-
Charset: "UTF-8",
|
|
120
|
-
Data: this.html,
|
|
121
|
-
},
|
|
122
|
-
Text: {
|
|
123
|
-
Charset: "UTF-8",
|
|
124
|
-
Data: this.html,
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
Subject: {
|
|
128
|
-
Charset: "UTF-8",
|
|
129
|
-
Data: this.subject,
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
Source: this.from,
|
|
133
|
-
};
|
|
134
|
-
return params;
|
|
135
|
-
};
|
|
136
|
-
this._getRawEmailParams = async () => {
|
|
137
|
-
const boundary = `----=_NextPart_${Date.now()}_${Math.random()
|
|
138
|
-
.toString(36)
|
|
139
|
-
.substr(2, 9)}`;
|
|
140
|
-
// Build recipients list
|
|
141
|
-
const allRecipients = [
|
|
142
|
-
...this._filterRecipients("to"),
|
|
143
|
-
...this._filterRecipients("cc"),
|
|
144
|
-
...this._filterRecipients("bcc")
|
|
145
|
-
];
|
|
146
|
-
// Build email headers
|
|
147
|
-
let rawMessage = "";
|
|
148
|
-
rawMessage += `From: ${this.from}\r\n`;
|
|
149
|
-
if (this._filterRecipients("to").length > 0) {
|
|
150
|
-
rawMessage += `To: ${this._filterRecipients("to")
|
|
151
|
-
.join(", ")}\r\n`;
|
|
152
|
-
}
|
|
153
|
-
if (this._filterRecipients("cc").length > 0) {
|
|
154
|
-
rawMessage += `Cc: ${this._filterRecipients("cc")
|
|
155
|
-
.join(", ")}\r\n`;
|
|
156
|
-
}
|
|
157
|
-
rawMessage += `Subject: ${this.subject}\r\n`;
|
|
158
|
-
rawMessage += `MIME-Version: 1.0\r\n`;
|
|
159
|
-
rawMessage += `Content-Type: multipart/mixed; boundary="${boundary}"\r\n\r\n`;
|
|
160
|
-
// Add HTML body
|
|
161
|
-
rawMessage += `--${boundary}\r\n`;
|
|
162
|
-
rawMessage += `Content-Type: text/html; charset=UTF-8\r\n`;
|
|
163
|
-
rawMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
|
|
164
|
-
rawMessage += `${this.html}\r\n\r\n`;
|
|
165
|
-
// Add attachments
|
|
166
|
-
for (const attachment of this.attachments) {
|
|
167
|
-
const isTextFile = this._isTextFile(attachment.contentType || this._getContentTypeFromFilename(attachment.filename));
|
|
168
|
-
rawMessage += `--${boundary}\r\n`;
|
|
169
|
-
rawMessage += `Content-Type: ${attachment.contentType || "application/octet-stream"}\r\n`;
|
|
170
|
-
rawMessage += `Content-Disposition: attachment; filename="${attachment.filename}"\r\n`;
|
|
171
|
-
if (isTextFile) {
|
|
172
|
-
rawMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
|
|
173
|
-
const textData = await this._getAttachmentTextData(attachment);
|
|
174
|
-
rawMessage += `${textData}\r\n\r\n`;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
rawMessage += `Content-Transfer-Encoding: base64\r\n\r\n`;
|
|
178
|
-
const attachmentData = await this._getAttachmentData(attachment);
|
|
179
|
-
rawMessage += `${attachmentData}\r\n\r\n`;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
rawMessage += `--${boundary}--\r\n`;
|
|
183
|
-
return {
|
|
184
|
-
Destinations: allRecipients,
|
|
185
|
-
RawMessage: {
|
|
186
|
-
Data: rawMessage
|
|
187
|
-
},
|
|
188
|
-
Source: this.from
|
|
189
|
-
};
|
|
190
|
-
};
|
|
191
|
-
this._isTextFile = (contentType) => {
|
|
192
|
-
const textTypes = [
|
|
193
|
-
"text/csv",
|
|
194
|
-
"text/plain",
|
|
195
|
-
"text/html",
|
|
196
|
-
"application/json",
|
|
197
|
-
"application/xml",
|
|
198
|
-
"text/xml"
|
|
199
|
-
];
|
|
200
|
-
return textTypes.some(type => contentType.startsWith(type));
|
|
201
|
-
};
|
|
202
|
-
this._getAttachmentTextData = async (attachment) => {
|
|
203
|
-
// If data is already provided as base64, decode it first
|
|
204
|
-
if (attachment.data) {
|
|
205
|
-
// Remove data URL prefix if present (e.g., "data:text/csv;base64,")
|
|
206
|
-
const base64Data = attachment.data.replace(/^data:[^;]+;base64,/, "");
|
|
207
|
-
// Check if it's actually base64 encoded
|
|
208
|
-
if (this._isBase64(base64Data)) {
|
|
209
|
-
return Buffer.from(base64Data, "base64")
|
|
210
|
-
.toString("utf-8");
|
|
211
|
-
}
|
|
212
|
-
// If not base64, assume it's already plain text
|
|
213
|
-
return attachment.data;
|
|
214
|
-
}
|
|
215
|
-
// If URL is provided, fetch the data as text
|
|
216
|
-
if (attachment.url) {
|
|
217
|
-
const fetch = await Promise.resolve().then(() => __importStar(require("node-fetch"))).then(mod => mod.default);
|
|
218
|
-
const response = await fetch(attachment.url);
|
|
219
|
-
return await response.text();
|
|
220
|
-
}
|
|
221
|
-
throw new Error(`No valid data source provided for attachment: ${attachment.filename}`);
|
|
222
|
-
};
|
|
223
|
-
this._getAttachmentData = async (attachment) => {
|
|
224
|
-
// If data is already provided as base64
|
|
225
|
-
if (attachment.data) {
|
|
226
|
-
// Remove data URL prefix if present (e.g., "data:image/png;base64,")
|
|
227
|
-
const cleanData = attachment.data.replace(/^data:[^;]+;base64,/, "");
|
|
228
|
-
// Check if it's actually base64 encoded
|
|
229
|
-
if (this._isBase64(cleanData)) {
|
|
230
|
-
return cleanData;
|
|
231
|
-
}
|
|
232
|
-
// If not base64, encode it
|
|
233
|
-
return Buffer.from(attachment.data, "utf-8")
|
|
234
|
-
.toString("base64");
|
|
235
|
-
}
|
|
236
|
-
// If URL is provided, fetch the data
|
|
237
|
-
if (attachment.url) {
|
|
238
|
-
const fetch = await Promise.resolve().then(() => __importStar(require("node-fetch"))).then(mod => mod.default);
|
|
239
|
-
const response = await fetch(attachment.url);
|
|
240
|
-
const buffer = await response.buffer();
|
|
241
|
-
return buffer.toString("base64");
|
|
242
|
-
}
|
|
243
|
-
throw new Error(`No valid data source provided for attachment: ${attachment.filename}`);
|
|
244
|
-
};
|
|
245
|
-
this._isBase64 = (str) => {
|
|
246
|
-
try {
|
|
247
|
-
return Buffer.from(str, "base64")
|
|
248
|
-
.toString("base64") === str;
|
|
249
|
-
}
|
|
250
|
-
catch {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
this._getContentTypeFromFilename = (filename) => {
|
|
255
|
-
const extension = filename.split(".")
|
|
256
|
-
.pop()
|
|
257
|
-
?.toLowerCase();
|
|
258
|
-
const mimeTypes = {
|
|
259
|
-
// Images
|
|
260
|
-
"jpg": "image/jpeg",
|
|
261
|
-
"jpeg": "image/jpeg",
|
|
262
|
-
"png": "image/png",
|
|
263
|
-
"gif": "image/gif",
|
|
264
|
-
"svg": "image/svg+xml",
|
|
265
|
-
"webp": "image/webp",
|
|
266
|
-
"bmp": "image/bmp",
|
|
267
|
-
"ico": "image/x-icon",
|
|
268
|
-
// Documents
|
|
269
|
-
"pdf": "application/pdf",
|
|
270
|
-
"doc": "application/msword",
|
|
271
|
-
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
272
|
-
"xls": "application/vnd.ms-excel",
|
|
273
|
-
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
274
|
-
"ppt": "application/vnd.ms-powerpoint",
|
|
275
|
-
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
276
|
-
// Data
|
|
277
|
-
"csv": "text/csv",
|
|
278
|
-
"tsv": "text/tab-separated-values",
|
|
279
|
-
"json": "application/json",
|
|
280
|
-
"xml": "application/xml",
|
|
281
|
-
"txt": "text/plain",
|
|
282
|
-
// Archives
|
|
283
|
-
"zip": "application/zip",
|
|
284
|
-
"rar": "application/x-rar-compressed",
|
|
285
|
-
"7z": "application/x-7z-compressed",
|
|
286
|
-
"tar": "application/x-tar",
|
|
287
|
-
"gz": "application/gzip",
|
|
288
|
-
// Audio/Video
|
|
289
|
-
"mp3": "audio/mpeg",
|
|
290
|
-
"wav": "audio/wav",
|
|
291
|
-
"mp4": "video/mp4",
|
|
292
|
-
"avi": "video/x-msvideo",
|
|
293
|
-
"mov": "video/quicktime",
|
|
294
|
-
};
|
|
295
|
-
return mimeTypes[extension || ""] || "application/octet-stream";
|
|
296
|
-
};
|
|
297
|
-
this._filterRecipients = (field) => {
|
|
298
|
-
// Remove all undefined and null values
|
|
299
|
-
let response = this[field].filter(recipient => recipient && null !== recipient);
|
|
300
|
-
// Clean all the values
|
|
301
|
-
response = response.map(recipient => recipient.toLowerCase()
|
|
302
|
-
.trim());
|
|
303
|
-
// Remove all empty values
|
|
304
|
-
response = response.filter(recipient => "" !== recipient);
|
|
305
|
-
// Return only unique values
|
|
306
|
-
response = (0, uniq_1.default)(response);
|
|
307
|
-
return response;
|
|
308
|
-
};
|
|
309
16
|
if (bcc) {
|
|
310
17
|
this.setBcc(bcc);
|
|
311
18
|
}
|
|
@@ -329,5 +36,261 @@ class SimpleEmail extends _class_1.BaseClass {
|
|
|
329
36
|
}
|
|
330
37
|
return this;
|
|
331
38
|
}
|
|
39
|
+
setFrom = (from) => {
|
|
40
|
+
return this._setValue("from", from);
|
|
41
|
+
};
|
|
42
|
+
setHtml = (html) => {
|
|
43
|
+
return this._setValue("html", html);
|
|
44
|
+
};
|
|
45
|
+
setSubject = (subject) => {
|
|
46
|
+
return this._setValue("subject", subject);
|
|
47
|
+
};
|
|
48
|
+
setAttachments = (attachments) => {
|
|
49
|
+
return this._setValue("attachments", attachments);
|
|
50
|
+
};
|
|
51
|
+
addAttachment = (attachment) => {
|
|
52
|
+
this.attachments.push(attachment);
|
|
53
|
+
return this;
|
|
54
|
+
};
|
|
55
|
+
addAttachmentFromdata = (filename, data, contentType) => {
|
|
56
|
+
return this.addAttachment({
|
|
57
|
+
filename,
|
|
58
|
+
data,
|
|
59
|
+
contentType: contentType || this._getContentTypeFromFilename(filename)
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
addAttachmentFromUrl = (filename, url, contentType) => {
|
|
63
|
+
return this.addAttachment({
|
|
64
|
+
filename,
|
|
65
|
+
url,
|
|
66
|
+
contentType: contentType || this._getContentTypeFromFilename(filename)
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
clearAttachments = () => {
|
|
70
|
+
this.attachments = [];
|
|
71
|
+
return this;
|
|
72
|
+
};
|
|
73
|
+
pushBcc = (recipient) => {
|
|
74
|
+
return this._push("bcc", recipient);
|
|
75
|
+
};
|
|
76
|
+
pushCc = (recipient) => {
|
|
77
|
+
return this._push("cc", recipient);
|
|
78
|
+
};
|
|
79
|
+
pushTo = (recipient) => {
|
|
80
|
+
return this._push("to", recipient);
|
|
81
|
+
};
|
|
82
|
+
setBcc = (recipient) => {
|
|
83
|
+
return this._setArray("bcc", recipient);
|
|
84
|
+
};
|
|
85
|
+
setCc = (recipient) => {
|
|
86
|
+
return this._setArray("cc", recipient);
|
|
87
|
+
};
|
|
88
|
+
setTo = (recipient) => {
|
|
89
|
+
return this._setArray("to", recipient);
|
|
90
|
+
};
|
|
91
|
+
getSendParam = async () => {
|
|
92
|
+
// For emails with attachments, we need to use SendRawEmail instead of SendEmail
|
|
93
|
+
if (this.attachments.length > 0) {
|
|
94
|
+
return await this._getRawEmailParams();
|
|
95
|
+
}
|
|
96
|
+
// https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/ses-examples-sending-email.html
|
|
97
|
+
const params = {
|
|
98
|
+
Destination: {
|
|
99
|
+
BccAddresses: this._filterRecipients("bcc"),
|
|
100
|
+
CcAddresses: this._filterRecipients("cc"),
|
|
101
|
+
ToAddresses: this._filterRecipients("to"),
|
|
102
|
+
},
|
|
103
|
+
Message: {
|
|
104
|
+
Body: {
|
|
105
|
+
Html: {
|
|
106
|
+
Charset: "UTF-8",
|
|
107
|
+
Data: this.html,
|
|
108
|
+
},
|
|
109
|
+
Text: {
|
|
110
|
+
Charset: "UTF-8",
|
|
111
|
+
Data: this.html,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
Subject: {
|
|
115
|
+
Charset: "UTF-8",
|
|
116
|
+
Data: this.subject,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
Source: this.from,
|
|
120
|
+
};
|
|
121
|
+
return params;
|
|
122
|
+
};
|
|
123
|
+
_getRawEmailParams = async () => {
|
|
124
|
+
const boundary = `----=_NextPart_${Date.now()}_${Math.random()
|
|
125
|
+
.toString(36)
|
|
126
|
+
.substr(2, 9)}`;
|
|
127
|
+
// Build recipients list
|
|
128
|
+
const allRecipients = [
|
|
129
|
+
...this._filterRecipients("to"),
|
|
130
|
+
...this._filterRecipients("cc"),
|
|
131
|
+
...this._filterRecipients("bcc")
|
|
132
|
+
];
|
|
133
|
+
// Build email headers
|
|
134
|
+
let rawMessage = "";
|
|
135
|
+
rawMessage += `From: ${this.from}\r\n`;
|
|
136
|
+
if (this._filterRecipients("to").length > 0) {
|
|
137
|
+
rawMessage += `To: ${this._filterRecipients("to")
|
|
138
|
+
.join(", ")}\r\n`;
|
|
139
|
+
}
|
|
140
|
+
if (this._filterRecipients("cc").length > 0) {
|
|
141
|
+
rawMessage += `Cc: ${this._filterRecipients("cc")
|
|
142
|
+
.join(", ")}\r\n`;
|
|
143
|
+
}
|
|
144
|
+
rawMessage += `Subject: ${this.subject}\r\n`;
|
|
145
|
+
rawMessage += `MIME-Version: 1.0\r\n`;
|
|
146
|
+
rawMessage += `Content-Type: multipart/mixed; boundary="${boundary}"\r\n\r\n`;
|
|
147
|
+
// Add HTML body
|
|
148
|
+
rawMessage += `--${boundary}\r\n`;
|
|
149
|
+
rawMessage += `Content-Type: text/html; charset=UTF-8\r\n`;
|
|
150
|
+
rawMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
|
|
151
|
+
rawMessage += `${this.html}\r\n\r\n`;
|
|
152
|
+
// Add attachments
|
|
153
|
+
for (const attachment of this.attachments) {
|
|
154
|
+
const isTextFile = this._isTextFile(attachment.contentType || this._getContentTypeFromFilename(attachment.filename));
|
|
155
|
+
rawMessage += `--${boundary}\r\n`;
|
|
156
|
+
rawMessage += `Content-Type: ${attachment.contentType || "application/octet-stream"}\r\n`;
|
|
157
|
+
rawMessage += `Content-Disposition: attachment; filename="${attachment.filename}"\r\n`;
|
|
158
|
+
if (isTextFile) {
|
|
159
|
+
rawMessage += `Content-Transfer-Encoding: 7bit\r\n\r\n`;
|
|
160
|
+
const textData = await this._getAttachmentTextData(attachment);
|
|
161
|
+
rawMessage += `${textData}\r\n\r\n`;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
rawMessage += `Content-Transfer-Encoding: base64\r\n\r\n`;
|
|
165
|
+
const attachmentData = await this._getAttachmentData(attachment);
|
|
166
|
+
rawMessage += `${attachmentData}\r\n\r\n`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
rawMessage += `--${boundary}--\r\n`;
|
|
170
|
+
return {
|
|
171
|
+
Destinations: allRecipients,
|
|
172
|
+
RawMessage: {
|
|
173
|
+
Data: rawMessage
|
|
174
|
+
},
|
|
175
|
+
Source: this.from
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
_isTextFile = (contentType) => {
|
|
179
|
+
const textTypes = [
|
|
180
|
+
"text/csv",
|
|
181
|
+
"text/plain",
|
|
182
|
+
"text/html",
|
|
183
|
+
"application/json",
|
|
184
|
+
"application/xml",
|
|
185
|
+
"text/xml"
|
|
186
|
+
];
|
|
187
|
+
return textTypes.some(type => contentType.startsWith(type));
|
|
188
|
+
};
|
|
189
|
+
_getAttachmentTextData = async (attachment) => {
|
|
190
|
+
// If data is already provided as base64, decode it first
|
|
191
|
+
if (attachment.data) {
|
|
192
|
+
// Remove data URL prefix if present (e.g., "data:text/csv;base64,")
|
|
193
|
+
const base64Data = attachment.data.replace(/^data:[^;]+;base64,/, "");
|
|
194
|
+
// Check if it's actually base64 encoded
|
|
195
|
+
if (this._isBase64(base64Data)) {
|
|
196
|
+
return Buffer.from(base64Data, "base64")
|
|
197
|
+
.toString("utf-8");
|
|
198
|
+
}
|
|
199
|
+
// If not base64, assume it's already plain text
|
|
200
|
+
return attachment.data;
|
|
201
|
+
}
|
|
202
|
+
// If URL is provided, fetch the data as text
|
|
203
|
+
if (attachment.url) {
|
|
204
|
+
const fetch = await import("node-fetch").then(mod => mod.default);
|
|
205
|
+
const response = await fetch(attachment.url);
|
|
206
|
+
return await response.text();
|
|
207
|
+
}
|
|
208
|
+
throw new Error(`No valid data source provided for attachment: ${attachment.filename}`);
|
|
209
|
+
};
|
|
210
|
+
_getAttachmentData = async (attachment) => {
|
|
211
|
+
// If data is already provided as base64
|
|
212
|
+
if (attachment.data) {
|
|
213
|
+
// Remove data URL prefix if present (e.g., "data:image/png;base64,")
|
|
214
|
+
const cleanData = attachment.data.replace(/^data:[^;]+;base64,/, "");
|
|
215
|
+
// Check if it's actually base64 encoded
|
|
216
|
+
if (this._isBase64(cleanData)) {
|
|
217
|
+
return cleanData;
|
|
218
|
+
}
|
|
219
|
+
// If not base64, encode it
|
|
220
|
+
return Buffer.from(attachment.data, "utf-8")
|
|
221
|
+
.toString("base64");
|
|
222
|
+
}
|
|
223
|
+
// If URL is provided, fetch the data
|
|
224
|
+
if (attachment.url) {
|
|
225
|
+
const fetch = await import("node-fetch").then(mod => mod.default);
|
|
226
|
+
const response = await fetch(attachment.url);
|
|
227
|
+
const buffer = await response.buffer();
|
|
228
|
+
return buffer.toString("base64");
|
|
229
|
+
}
|
|
230
|
+
throw new Error(`No valid data source provided for attachment: ${attachment.filename}`);
|
|
231
|
+
};
|
|
232
|
+
_isBase64 = (str) => {
|
|
233
|
+
try {
|
|
234
|
+
return Buffer.from(str, "base64")
|
|
235
|
+
.toString("base64") === str;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
_getContentTypeFromFilename = (filename) => {
|
|
242
|
+
const extension = filename.split(".")
|
|
243
|
+
.pop()
|
|
244
|
+
?.toLowerCase();
|
|
245
|
+
const mimeTypes = {
|
|
246
|
+
// Images
|
|
247
|
+
"jpg": "image/jpeg",
|
|
248
|
+
"jpeg": "image/jpeg",
|
|
249
|
+
"png": "image/png",
|
|
250
|
+
"gif": "image/gif",
|
|
251
|
+
"svg": "image/svg+xml",
|
|
252
|
+
"webp": "image/webp",
|
|
253
|
+
"bmp": "image/bmp",
|
|
254
|
+
"ico": "image/x-icon",
|
|
255
|
+
// Documents
|
|
256
|
+
"pdf": "application/pdf",
|
|
257
|
+
"doc": "application/msword",
|
|
258
|
+
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
259
|
+
"xls": "application/vnd.ms-excel",
|
|
260
|
+
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
261
|
+
"ppt": "application/vnd.ms-powerpoint",
|
|
262
|
+
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
263
|
+
// Data
|
|
264
|
+
"csv": "text/csv",
|
|
265
|
+
"tsv": "text/tab-separated-values",
|
|
266
|
+
"json": "application/json",
|
|
267
|
+
"xml": "application/xml",
|
|
268
|
+
"txt": "text/plain",
|
|
269
|
+
// Archives
|
|
270
|
+
"zip": "application/zip",
|
|
271
|
+
"rar": "application/x-rar-compressed",
|
|
272
|
+
"7z": "application/x-7z-compressed",
|
|
273
|
+
"tar": "application/x-tar",
|
|
274
|
+
"gz": "application/gzip",
|
|
275
|
+
// Audio/Video
|
|
276
|
+
"mp3": "audio/mpeg",
|
|
277
|
+
"wav": "audio/wav",
|
|
278
|
+
"mp4": "video/mp4",
|
|
279
|
+
"avi": "video/x-msvideo",
|
|
280
|
+
"mov": "video/quicktime",
|
|
281
|
+
};
|
|
282
|
+
return mimeTypes[extension || ""] || "application/octet-stream";
|
|
283
|
+
};
|
|
284
|
+
_filterRecipients = (field) => {
|
|
285
|
+
// Remove all undefined and null values
|
|
286
|
+
let response = this[field].filter(recipient => recipient && null !== recipient);
|
|
287
|
+
// Clean all the values
|
|
288
|
+
response = response.map(recipient => recipient.toLowerCase()
|
|
289
|
+
.trim());
|
|
290
|
+
// Remove all empty values
|
|
291
|
+
response = response.filter(recipient => "" !== recipient);
|
|
292
|
+
// Return only unique values
|
|
293
|
+
response = uniq(response);
|
|
294
|
+
return response;
|
|
295
|
+
};
|
|
332
296
|
}
|
|
333
|
-
exports.SimpleEmail = SimpleEmail;
|
package/aws/ses/server.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.SimpleEmail = exports.awsSesClient = void 0;
|
|
4
|
-
const AwsSesNamespace_1 = require("./AwsSesNamespace");
|
|
5
|
-
const server_1 = require("../server");
|
|
1
|
+
import { AwsSesNamespace } from "./AwsSesNamespace";
|
|
2
|
+
import { getConfig } from "../server";
|
|
6
3
|
const awsSesNamespaces = new Map();
|
|
7
|
-
const awsSesClient = async (key = "default", config, vaultId, itemId) => {
|
|
4
|
+
export const awsSesClient = async (key = "default", config, vaultId, itemId) => {
|
|
8
5
|
if (awsSesNamespaces.has(key)) {
|
|
9
6
|
return awsSesNamespaces.get(key);
|
|
10
7
|
}
|
|
11
|
-
const instanceConfig = await
|
|
12
|
-
const namespace = new
|
|
8
|
+
const instanceConfig = await getConfig(key, config, vaultId, itemId);
|
|
9
|
+
const namespace = new AwsSesNamespace(key, instanceConfig);
|
|
13
10
|
awsSesNamespaces.set(key, namespace);
|
|
14
11
|
return namespace;
|
|
15
12
|
};
|
|
16
|
-
|
|
17
|
-
var SimpleEmail_1 = require("./SimpleEmail");
|
|
18
|
-
Object.defineProperty(exports, "SimpleEmail", { enumerable: true, get: function () { return SimpleEmail_1.SimpleEmail; } });
|
|
13
|
+
export { SimpleEmail } from "./SimpleEmail";
|