@allthings/cloud-toolkit 5.2.1-beta.1 → 5.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -8
- package/dist/lib.cjs.js +59 -1
- package/dist/lib.esm.mjs +58 -2
- package/dist/ses.cjs.js +59 -1
- package/dist/ses.esm.mjs +58 -2
- package/dist/src/aws/emailHeaders.d.ts +17 -0
- package/dist/src/aws/index.d.ts +2 -1
- package/dist/src/aws/ses.d.ts +17 -1
- package/dist/src/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,9 +13,54 @@ Standardizes the setup of aws, Datadog and other things
|
|
|
13
13
|
|
|
14
14
|
### ses
|
|
15
15
|
|
|
16
|
-
| function
|
|
17
|
-
|
|
|
18
|
-
| sendMail
|
|
16
|
+
| function | parameters | description |
|
|
17
|
+
| ------------ | ---------- | ------------------------------------------------------------------------ |
|
|
18
|
+
| sendMail | options | Sends an email via SES or provided SMTP config |
|
|
19
|
+
| emailHeaders | options | Builds the deliverability headers for one message, for `options.headers` |
|
|
20
|
+
|
|
21
|
+
`emailHeaders` is opt-in and pure: a message only carries these headers when a
|
|
22
|
+
caller builds them. Every header is omitted when the value it needs is not given.
|
|
23
|
+
|
|
24
|
+
| header | from |
|
|
25
|
+
| ------------------------------------------ | ------------------------------------------------------- |
|
|
26
|
+
| `Auto-Submitted: auto-generated` | `suppressAutoResponses` (default true) |
|
|
27
|
+
| `X-Auto-Response-Suppress: OOF, AutoReply` | `suppressAutoResponses` (default true) |
|
|
28
|
+
| `Content-Language` | `contentLanguage` |
|
|
29
|
+
| `Feedback-ID` | `feedbackId` |
|
|
30
|
+
| `List-Id` | `listId` |
|
|
31
|
+
| `List-Unsubscribe` | `unsubscribeUrl`, `unsubscribeMailto` |
|
|
32
|
+
| `List-Unsubscribe-Post` | `oneClickUnsubscribe` (default true, https target only) |
|
|
33
|
+
| `Precedence: bulk` | `bulk` (default false) |
|
|
34
|
+
| `X-Entity-Ref-ID` | `entityReferenceId` |
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { emailHeaders, ses } from '@allthings/cloud-toolkit/ses'
|
|
38
|
+
|
|
39
|
+
await ses({}).sendMail({
|
|
40
|
+
from: 'noreply@allthings.me',
|
|
41
|
+
headers: emailHeaders({
|
|
42
|
+
contentLanguage: 'de-DE',
|
|
43
|
+
entityReferenceId: notificationId,
|
|
44
|
+
listId: 'AppNotificationDigest.notifications.allthings.me',
|
|
45
|
+
unsubscribeUrl: `${siteUrl}/settings`,
|
|
46
|
+
// the URL cannot answer an unauthenticated POST yet
|
|
47
|
+
oneClickUnsubscribe: false,
|
|
48
|
+
}),
|
|
49
|
+
html,
|
|
50
|
+
subject,
|
|
51
|
+
text,
|
|
52
|
+
to,
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The two suppression headers stop out of office autoresponders from replying to a
|
|
57
|
+
`noreply@` address. `X-Auto-Response-Suppress` is deliberately `OOF, AutoReply`
|
|
58
|
+
rather than `All`, so delivery status notifications keep reaching SES and its
|
|
59
|
+
suppression list stays accurate.
|
|
60
|
+
|
|
61
|
+
`Precedence: bulk` is off by default. Only legacy `vacation(1)` style responders
|
|
62
|
+
act on it, Gmail and Microsoft ignore it, and some filters read it as a mild
|
|
63
|
+
negative — so leave it off for anything that has to arrive.
|
|
19
64
|
|
|
20
65
|
### lambda
|
|
21
66
|
|
|
@@ -37,11 +82,11 @@ Standardizes the setup of aws, Datadog and other things
|
|
|
37
82
|
|
|
38
83
|
### sqs
|
|
39
84
|
|
|
40
|
-
| function | parameters
|
|
41
|
-
| --------------- |
|
|
42
|
-
| deleteQueueItem | queueUrl<br/>receiptHandle
|
|
43
|
-
| getQueueItems | queueUrl<br/>maxNumberOfMessages (optional)
|
|
44
|
-
| getQueueUrl | queueName
|
|
85
|
+
| function | parameters | description |
|
|
86
|
+
| --------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
87
|
+
| deleteQueueItem | queueUrl<br/>receiptHandle | Deletes item from queue |
|
|
88
|
+
| getQueueItems | queueUrl<br/>maxNumberOfMessages (optional) | Retrieves items from queue |
|
|
89
|
+
| getQueueUrl | queueName | Returns queue url which is needed for all other requests |
|
|
45
90
|
| sendMessage | queueUrl<br/>message<br/>fifoSettings(optional)<br/>messageAttributes(optional)<br/>messageDelay(optional) | Creates an item in the queue |
|
|
46
91
|
|
|
47
92
|
### logger
|
package/dist/lib.cjs.js
CHANGED
|
@@ -904,6 +904,44 @@ const dynamodb = (userConfig) => {
|
|
|
904
904
|
};
|
|
905
905
|
};
|
|
906
906
|
|
|
907
|
+
const AUTO_RESPONSE_SUPPRESSION_HEADERS = {
|
|
908
|
+
'Auto-Submitted': 'auto-generated',
|
|
909
|
+
'X-Auto-Response-Suppress': 'OOF, AutoReply',
|
|
910
|
+
};
|
|
911
|
+
const nonBlank = (value) => value?.trim() ? value.trim() : undefined;
|
|
912
|
+
const bareTarget = (value) => nonBlank(nonBlank(value)?.replace(/^[\s<]+|[\s>]+$/g, ''));
|
|
913
|
+
const angleBracketed = (value) => `<${value}>`;
|
|
914
|
+
const asMailto = (value) => /^mailto:/i.test(value) ? value : `mailto:${value}`;
|
|
915
|
+
const emailHeaders = ({ bulk = false, contentLanguage, entityReferenceId, feedbackId, listId, oneClickUnsubscribe = true, suppressAutoResponses = true, unsubscribeMailto, unsubscribeUrl, } = {}) => {
|
|
916
|
+
const language = nonBlank(contentLanguage);
|
|
917
|
+
const feedback = nonBlank(feedbackId);
|
|
918
|
+
const list = bareTarget(listId);
|
|
919
|
+
const entityReference = nonBlank(entityReferenceId);
|
|
920
|
+
const httpsUnsubscribe = bareTarget(unsubscribeUrl);
|
|
921
|
+
const mailtoUnsubscribe = bareTarget(unsubscribeMailto);
|
|
922
|
+
const unsubscribeTargets = [
|
|
923
|
+
...(httpsUnsubscribe ? [angleBracketed(httpsUnsubscribe)] : []),
|
|
924
|
+
...(mailtoUnsubscribe ? [angleBracketed(asMailto(mailtoUnsubscribe))] : []),
|
|
925
|
+
];
|
|
926
|
+
const supportsOneClick = oneClickUnsubscribe &&
|
|
927
|
+
httpsUnsubscribe !== undefined &&
|
|
928
|
+
/^https:/i.test(httpsUnsubscribe);
|
|
929
|
+
return {
|
|
930
|
+
...(suppressAutoResponses ? AUTO_RESPONSE_SUPPRESSION_HEADERS : {}),
|
|
931
|
+
...(language ? { 'Content-Language': language } : {}),
|
|
932
|
+
...(feedback ? { 'Feedback-ID': feedback } : {}),
|
|
933
|
+
...(list ? { 'List-Id': angleBracketed(list) } : {}),
|
|
934
|
+
...(unsubscribeTargets.length > 0
|
|
935
|
+
? { 'List-Unsubscribe': unsubscribeTargets.join(', ') }
|
|
936
|
+
: {}),
|
|
937
|
+
...(supportsOneClick
|
|
938
|
+
? { 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' }
|
|
939
|
+
: {}),
|
|
940
|
+
...(bulk ? { Precedence: 'bulk' } : {}),
|
|
941
|
+
...(entityReference ? { 'X-Entity-Ref-ID': entityReference } : {}),
|
|
942
|
+
};
|
|
943
|
+
};
|
|
944
|
+
|
|
907
945
|
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
908
946
|
try {
|
|
909
947
|
const invokeCommand = new clientLambda.InvokeCommand({
|
|
@@ -1010,6 +1048,24 @@ const parameterStore = (userConfig) => {
|
|
|
1010
1048
|
const DEFAULT_CLIENT_CONFIG = {
|
|
1011
1049
|
clientConfig: { region: 'eu-west-1' },
|
|
1012
1050
|
};
|
|
1051
|
+
const toMailOptions = (options) => ({
|
|
1052
|
+
attachments: options.attachments,
|
|
1053
|
+
bcc: options.bcc,
|
|
1054
|
+
cc: options.cc,
|
|
1055
|
+
envelope: options.envelope,
|
|
1056
|
+
from: options.from,
|
|
1057
|
+
headers: options.headers,
|
|
1058
|
+
html: options.html,
|
|
1059
|
+
inReplyTo: options.inReplyTo,
|
|
1060
|
+
messageId: options.messageId,
|
|
1061
|
+
references: options.references,
|
|
1062
|
+
replyTo: options.replyTo,
|
|
1063
|
+
sender: options.sender,
|
|
1064
|
+
ses: options.ses,
|
|
1065
|
+
subject: options.subject,
|
|
1066
|
+
text: options.text,
|
|
1067
|
+
to: options.to,
|
|
1068
|
+
});
|
|
1013
1069
|
const sendMail = async (config, transport, options, responseCallback) => {
|
|
1014
1070
|
try {
|
|
1015
1071
|
if (!options.html && !options.text) {
|
|
@@ -1024,7 +1080,7 @@ const sendMail = async (config, transport, options, responseCallback) => {
|
|
|
1024
1080
|
}
|
|
1025
1081
|
return false;
|
|
1026
1082
|
}
|
|
1027
|
-
const transportResponse = await transport.sendMail(options);
|
|
1083
|
+
const transportResponse = await transport.sendMail(toMailOptions(options));
|
|
1028
1084
|
if (responseCallback) {
|
|
1029
1085
|
await responseCallback(transportResponse);
|
|
1030
1086
|
}
|
|
@@ -1190,6 +1246,7 @@ Object.defineProperty(exports, "Logger", {
|
|
|
1190
1246
|
enumerable: true,
|
|
1191
1247
|
get: function () { return winston.Logger; }
|
|
1192
1248
|
});
|
|
1249
|
+
exports.AUTO_RESPONSE_SUPPRESSION_HEADERS = AUTO_RESPONSE_SUPPRESSION_HEADERS;
|
|
1193
1250
|
exports.ClientError = ClientError;
|
|
1194
1251
|
exports.DEFAULT_PARAMETER_STORE_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG$1;
|
|
1195
1252
|
exports.DEFAULT_SES_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG;
|
|
@@ -1200,6 +1257,7 @@ exports.atob = atob;
|
|
|
1200
1257
|
exports.btoa = btoa;
|
|
1201
1258
|
exports.deepFlatten = deepFlatten;
|
|
1202
1259
|
exports.dynamodb = dynamodb;
|
|
1260
|
+
exports.emailHeaders = emailHeaders;
|
|
1203
1261
|
exports.flatten = flatten;
|
|
1204
1262
|
exports.lambda = lambda;
|
|
1205
1263
|
exports.logger = logger;
|
package/dist/lib.esm.mjs
CHANGED
|
@@ -882,6 +882,44 @@ const dynamodb = (userConfig) => {
|
|
|
882
882
|
};
|
|
883
883
|
};
|
|
884
884
|
|
|
885
|
+
const AUTO_RESPONSE_SUPPRESSION_HEADERS = {
|
|
886
|
+
'Auto-Submitted': 'auto-generated',
|
|
887
|
+
'X-Auto-Response-Suppress': 'OOF, AutoReply',
|
|
888
|
+
};
|
|
889
|
+
const nonBlank = (value) => value?.trim() ? value.trim() : undefined;
|
|
890
|
+
const bareTarget = (value) => nonBlank(nonBlank(value)?.replace(/^[\s<]+|[\s>]+$/g, ''));
|
|
891
|
+
const angleBracketed = (value) => `<${value}>`;
|
|
892
|
+
const asMailto = (value) => /^mailto:/i.test(value) ? value : `mailto:${value}`;
|
|
893
|
+
const emailHeaders = ({ bulk = false, contentLanguage, entityReferenceId, feedbackId, listId, oneClickUnsubscribe = true, suppressAutoResponses = true, unsubscribeMailto, unsubscribeUrl, } = {}) => {
|
|
894
|
+
const language = nonBlank(contentLanguage);
|
|
895
|
+
const feedback = nonBlank(feedbackId);
|
|
896
|
+
const list = bareTarget(listId);
|
|
897
|
+
const entityReference = nonBlank(entityReferenceId);
|
|
898
|
+
const httpsUnsubscribe = bareTarget(unsubscribeUrl);
|
|
899
|
+
const mailtoUnsubscribe = bareTarget(unsubscribeMailto);
|
|
900
|
+
const unsubscribeTargets = [
|
|
901
|
+
...(httpsUnsubscribe ? [angleBracketed(httpsUnsubscribe)] : []),
|
|
902
|
+
...(mailtoUnsubscribe ? [angleBracketed(asMailto(mailtoUnsubscribe))] : []),
|
|
903
|
+
];
|
|
904
|
+
const supportsOneClick = oneClickUnsubscribe &&
|
|
905
|
+
httpsUnsubscribe !== undefined &&
|
|
906
|
+
/^https:/i.test(httpsUnsubscribe);
|
|
907
|
+
return {
|
|
908
|
+
...(suppressAutoResponses ? AUTO_RESPONSE_SUPPRESSION_HEADERS : {}),
|
|
909
|
+
...(language ? { 'Content-Language': language } : {}),
|
|
910
|
+
...(feedback ? { 'Feedback-ID': feedback } : {}),
|
|
911
|
+
...(list ? { 'List-Id': angleBracketed(list) } : {}),
|
|
912
|
+
...(unsubscribeTargets.length > 0
|
|
913
|
+
? { 'List-Unsubscribe': unsubscribeTargets.join(', ') }
|
|
914
|
+
: {}),
|
|
915
|
+
...(supportsOneClick
|
|
916
|
+
? { 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' }
|
|
917
|
+
: {}),
|
|
918
|
+
...(bulk ? { Precedence: 'bulk' } : {}),
|
|
919
|
+
...(entityReference ? { 'X-Entity-Ref-ID': entityReference } : {}),
|
|
920
|
+
};
|
|
921
|
+
};
|
|
922
|
+
|
|
885
923
|
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
886
924
|
try {
|
|
887
925
|
const invokeCommand = new InvokeCommand({
|
|
@@ -988,6 +1026,24 @@ const parameterStore = (userConfig) => {
|
|
|
988
1026
|
const DEFAULT_CLIENT_CONFIG = {
|
|
989
1027
|
clientConfig: { region: 'eu-west-1' },
|
|
990
1028
|
};
|
|
1029
|
+
const toMailOptions = (options) => ({
|
|
1030
|
+
attachments: options.attachments,
|
|
1031
|
+
bcc: options.bcc,
|
|
1032
|
+
cc: options.cc,
|
|
1033
|
+
envelope: options.envelope,
|
|
1034
|
+
from: options.from,
|
|
1035
|
+
headers: options.headers,
|
|
1036
|
+
html: options.html,
|
|
1037
|
+
inReplyTo: options.inReplyTo,
|
|
1038
|
+
messageId: options.messageId,
|
|
1039
|
+
references: options.references,
|
|
1040
|
+
replyTo: options.replyTo,
|
|
1041
|
+
sender: options.sender,
|
|
1042
|
+
ses: options.ses,
|
|
1043
|
+
subject: options.subject,
|
|
1044
|
+
text: options.text,
|
|
1045
|
+
to: options.to,
|
|
1046
|
+
});
|
|
991
1047
|
const sendMail = async (config, transport, options, responseCallback) => {
|
|
992
1048
|
try {
|
|
993
1049
|
if (!options.html && !options.text) {
|
|
@@ -1002,7 +1058,7 @@ const sendMail = async (config, transport, options, responseCallback) => {
|
|
|
1002
1058
|
}
|
|
1003
1059
|
return false;
|
|
1004
1060
|
}
|
|
1005
|
-
const transportResponse = await transport.sendMail(options);
|
|
1061
|
+
const transportResponse = await transport.sendMail(toMailOptions(options));
|
|
1006
1062
|
if (responseCallback) {
|
|
1007
1063
|
await responseCallback(transportResponse);
|
|
1008
1064
|
}
|
|
@@ -1164,4 +1220,4 @@ const logger = (config) => {
|
|
|
1164
1220
|
});
|
|
1165
1221
|
};
|
|
1166
1222
|
|
|
1167
|
-
export { ClientError, DEFAULT_CLIENT_CONFIG$1 as DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, ServerError, alagarr, asyncReduce, atob, btoa, deepFlatten, dynamodb, flatten, lambda, logger, parameterStore, partial, ses, splitEvery, sqs, times, until };
|
|
1223
|
+
export { AUTO_RESPONSE_SUPPRESSION_HEADERS, ClientError, DEFAULT_CLIENT_CONFIG$1 as DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, ServerError, alagarr, asyncReduce, atob, btoa, deepFlatten, dynamodb, emailHeaders, flatten, lambda, logger, parameterStore, partial, ses, splitEvery, sqs, times, until };
|
package/dist/ses.cjs.js
CHANGED
|
@@ -3,9 +3,65 @@
|
|
|
3
3
|
var clientSesv2 = require('@aws-sdk/client-sesv2');
|
|
4
4
|
var nodemailer = require('nodemailer');
|
|
5
5
|
|
|
6
|
+
const AUTO_RESPONSE_SUPPRESSION_HEADERS = {
|
|
7
|
+
'Auto-Submitted': 'auto-generated',
|
|
8
|
+
'X-Auto-Response-Suppress': 'OOF, AutoReply',
|
|
9
|
+
};
|
|
10
|
+
const nonBlank = (value) => value?.trim() ? value.trim() : undefined;
|
|
11
|
+
const bareTarget = (value) => nonBlank(nonBlank(value)?.replace(/^[\s<]+|[\s>]+$/g, ''));
|
|
12
|
+
const angleBracketed = (value) => `<${value}>`;
|
|
13
|
+
const asMailto = (value) => /^mailto:/i.test(value) ? value : `mailto:${value}`;
|
|
14
|
+
const emailHeaders = ({ bulk = false, contentLanguage, entityReferenceId, feedbackId, listId, oneClickUnsubscribe = true, suppressAutoResponses = true, unsubscribeMailto, unsubscribeUrl, } = {}) => {
|
|
15
|
+
const language = nonBlank(contentLanguage);
|
|
16
|
+
const feedback = nonBlank(feedbackId);
|
|
17
|
+
const list = bareTarget(listId);
|
|
18
|
+
const entityReference = nonBlank(entityReferenceId);
|
|
19
|
+
const httpsUnsubscribe = bareTarget(unsubscribeUrl);
|
|
20
|
+
const mailtoUnsubscribe = bareTarget(unsubscribeMailto);
|
|
21
|
+
const unsubscribeTargets = [
|
|
22
|
+
...(httpsUnsubscribe ? [angleBracketed(httpsUnsubscribe)] : []),
|
|
23
|
+
...(mailtoUnsubscribe ? [angleBracketed(asMailto(mailtoUnsubscribe))] : []),
|
|
24
|
+
];
|
|
25
|
+
const supportsOneClick = oneClickUnsubscribe &&
|
|
26
|
+
httpsUnsubscribe !== undefined &&
|
|
27
|
+
/^https:/i.test(httpsUnsubscribe);
|
|
28
|
+
return {
|
|
29
|
+
...(suppressAutoResponses ? AUTO_RESPONSE_SUPPRESSION_HEADERS : {}),
|
|
30
|
+
...(language ? { 'Content-Language': language } : {}),
|
|
31
|
+
...(feedback ? { 'Feedback-ID': feedback } : {}),
|
|
32
|
+
...(list ? { 'List-Id': angleBracketed(list) } : {}),
|
|
33
|
+
...(unsubscribeTargets.length > 0
|
|
34
|
+
? { 'List-Unsubscribe': unsubscribeTargets.join(', ') }
|
|
35
|
+
: {}),
|
|
36
|
+
...(supportsOneClick
|
|
37
|
+
? { 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' }
|
|
38
|
+
: {}),
|
|
39
|
+
...(bulk ? { Precedence: 'bulk' } : {}),
|
|
40
|
+
...(entityReference ? { 'X-Entity-Ref-ID': entityReference } : {}),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
6
44
|
const DEFAULT_CLIENT_CONFIG = {
|
|
7
45
|
clientConfig: { region: 'eu-west-1' },
|
|
8
46
|
};
|
|
47
|
+
const toMailOptions = (options) => ({
|
|
48
|
+
attachments: options.attachments,
|
|
49
|
+
bcc: options.bcc,
|
|
50
|
+
cc: options.cc,
|
|
51
|
+
envelope: options.envelope,
|
|
52
|
+
from: options.from,
|
|
53
|
+
headers: options.headers,
|
|
54
|
+
html: options.html,
|
|
55
|
+
inReplyTo: options.inReplyTo,
|
|
56
|
+
messageId: options.messageId,
|
|
57
|
+
references: options.references,
|
|
58
|
+
replyTo: options.replyTo,
|
|
59
|
+
sender: options.sender,
|
|
60
|
+
ses: options.ses,
|
|
61
|
+
subject: options.subject,
|
|
62
|
+
text: options.text,
|
|
63
|
+
to: options.to,
|
|
64
|
+
});
|
|
9
65
|
const sendMail = async (config, transport, options, responseCallback) => {
|
|
10
66
|
try {
|
|
11
67
|
if (!options.html && !options.text) {
|
|
@@ -20,7 +76,7 @@ const sendMail = async (config, transport, options, responseCallback) => {
|
|
|
20
76
|
}
|
|
21
77
|
return false;
|
|
22
78
|
}
|
|
23
|
-
const transportResponse = await transport.sendMail(options);
|
|
79
|
+
const transportResponse = await transport.sendMail(toMailOptions(options));
|
|
24
80
|
if (responseCallback) {
|
|
25
81
|
await responseCallback(transportResponse);
|
|
26
82
|
}
|
|
@@ -56,5 +112,7 @@ const ses = (userConfig) => {
|
|
|
56
112
|
};
|
|
57
113
|
};
|
|
58
114
|
|
|
115
|
+
exports.AUTO_RESPONSE_SUPPRESSION_HEADERS = AUTO_RESPONSE_SUPPRESSION_HEADERS;
|
|
59
116
|
exports.DEFAULT_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG;
|
|
117
|
+
exports.emailHeaders = emailHeaders;
|
|
60
118
|
exports.ses = ses;
|
package/dist/ses.esm.mjs
CHANGED
|
@@ -1,9 +1,65 @@
|
|
|
1
1
|
import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2';
|
|
2
2
|
import { createTransport } from 'nodemailer';
|
|
3
3
|
|
|
4
|
+
const AUTO_RESPONSE_SUPPRESSION_HEADERS = {
|
|
5
|
+
'Auto-Submitted': 'auto-generated',
|
|
6
|
+
'X-Auto-Response-Suppress': 'OOF, AutoReply',
|
|
7
|
+
};
|
|
8
|
+
const nonBlank = (value) => value?.trim() ? value.trim() : undefined;
|
|
9
|
+
const bareTarget = (value) => nonBlank(nonBlank(value)?.replace(/^[\s<]+|[\s>]+$/g, ''));
|
|
10
|
+
const angleBracketed = (value) => `<${value}>`;
|
|
11
|
+
const asMailto = (value) => /^mailto:/i.test(value) ? value : `mailto:${value}`;
|
|
12
|
+
const emailHeaders = ({ bulk = false, contentLanguage, entityReferenceId, feedbackId, listId, oneClickUnsubscribe = true, suppressAutoResponses = true, unsubscribeMailto, unsubscribeUrl, } = {}) => {
|
|
13
|
+
const language = nonBlank(contentLanguage);
|
|
14
|
+
const feedback = nonBlank(feedbackId);
|
|
15
|
+
const list = bareTarget(listId);
|
|
16
|
+
const entityReference = nonBlank(entityReferenceId);
|
|
17
|
+
const httpsUnsubscribe = bareTarget(unsubscribeUrl);
|
|
18
|
+
const mailtoUnsubscribe = bareTarget(unsubscribeMailto);
|
|
19
|
+
const unsubscribeTargets = [
|
|
20
|
+
...(httpsUnsubscribe ? [angleBracketed(httpsUnsubscribe)] : []),
|
|
21
|
+
...(mailtoUnsubscribe ? [angleBracketed(asMailto(mailtoUnsubscribe))] : []),
|
|
22
|
+
];
|
|
23
|
+
const supportsOneClick = oneClickUnsubscribe &&
|
|
24
|
+
httpsUnsubscribe !== undefined &&
|
|
25
|
+
/^https:/i.test(httpsUnsubscribe);
|
|
26
|
+
return {
|
|
27
|
+
...(suppressAutoResponses ? AUTO_RESPONSE_SUPPRESSION_HEADERS : {}),
|
|
28
|
+
...(language ? { 'Content-Language': language } : {}),
|
|
29
|
+
...(feedback ? { 'Feedback-ID': feedback } : {}),
|
|
30
|
+
...(list ? { 'List-Id': angleBracketed(list) } : {}),
|
|
31
|
+
...(unsubscribeTargets.length > 0
|
|
32
|
+
? { 'List-Unsubscribe': unsubscribeTargets.join(', ') }
|
|
33
|
+
: {}),
|
|
34
|
+
...(supportsOneClick
|
|
35
|
+
? { 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' }
|
|
36
|
+
: {}),
|
|
37
|
+
...(bulk ? { Precedence: 'bulk' } : {}),
|
|
38
|
+
...(entityReference ? { 'X-Entity-Ref-ID': entityReference } : {}),
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
4
42
|
const DEFAULT_CLIENT_CONFIG = {
|
|
5
43
|
clientConfig: { region: 'eu-west-1' },
|
|
6
44
|
};
|
|
45
|
+
const toMailOptions = (options) => ({
|
|
46
|
+
attachments: options.attachments,
|
|
47
|
+
bcc: options.bcc,
|
|
48
|
+
cc: options.cc,
|
|
49
|
+
envelope: options.envelope,
|
|
50
|
+
from: options.from,
|
|
51
|
+
headers: options.headers,
|
|
52
|
+
html: options.html,
|
|
53
|
+
inReplyTo: options.inReplyTo,
|
|
54
|
+
messageId: options.messageId,
|
|
55
|
+
references: options.references,
|
|
56
|
+
replyTo: options.replyTo,
|
|
57
|
+
sender: options.sender,
|
|
58
|
+
ses: options.ses,
|
|
59
|
+
subject: options.subject,
|
|
60
|
+
text: options.text,
|
|
61
|
+
to: options.to,
|
|
62
|
+
});
|
|
7
63
|
const sendMail = async (config, transport, options, responseCallback) => {
|
|
8
64
|
try {
|
|
9
65
|
if (!options.html && !options.text) {
|
|
@@ -18,7 +74,7 @@ const sendMail = async (config, transport, options, responseCallback) => {
|
|
|
18
74
|
}
|
|
19
75
|
return false;
|
|
20
76
|
}
|
|
21
|
-
const transportResponse = await transport.sendMail(options);
|
|
77
|
+
const transportResponse = await transport.sendMail(toMailOptions(options));
|
|
22
78
|
if (responseCallback) {
|
|
23
79
|
await responseCallback(transportResponse);
|
|
24
80
|
}
|
|
@@ -54,4 +110,4 @@ const ses = (userConfig) => {
|
|
|
54
110
|
};
|
|
55
111
|
};
|
|
56
112
|
|
|
57
|
-
export { DEFAULT_CLIENT_CONFIG, ses };
|
|
113
|
+
export { AUTO_RESPONSE_SUPPRESSION_HEADERS, DEFAULT_CLIENT_CONFIG, emailHeaders, ses };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Headers } from 'nodemailer/lib/mailer';
|
|
2
|
+
export declare const AUTO_RESPONSE_SUPPRESSION_HEADERS: {
|
|
3
|
+
readonly 'Auto-Submitted': "auto-generated";
|
|
4
|
+
readonly 'X-Auto-Response-Suppress': "OOF, AutoReply";
|
|
5
|
+
};
|
|
6
|
+
export interface IEmailHeaderOptions {
|
|
7
|
+
readonly bulk?: boolean;
|
|
8
|
+
readonly contentLanguage?: string;
|
|
9
|
+
readonly entityReferenceId?: string;
|
|
10
|
+
readonly feedbackId?: string;
|
|
11
|
+
readonly listId?: string;
|
|
12
|
+
readonly oneClickUnsubscribe?: boolean;
|
|
13
|
+
readonly suppressAutoResponses?: boolean;
|
|
14
|
+
readonly unsubscribeMailto?: string;
|
|
15
|
+
readonly unsubscribeUrl?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const emailHeaders: ({ bulk, contentLanguage, entityReferenceId, feedbackId, listId, oneClickUnsubscribe, suppressAutoResponses, unsubscribeMailto, unsubscribeUrl, }?: IEmailHeaderOptions) => Headers;
|
package/dist/src/aws/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { dynamodb, IDynamoDBConfig, IDynamoDBInstance, IUnprocessedItems, TBatchWriteItems, TDeleteItem, TGetItem, TPutItem, TQueryTable, TScanTable, TUpdateItem, } from './dynamodb';
|
|
2
|
+
export { AUTO_RESPONSE_SUPPRESSION_HEADERS, emailHeaders, IEmailHeaderOptions, } from './emailHeaders';
|
|
2
3
|
export { ILambda, ILambdaInstance, lambda, TInvokeLambda } from './lambda';
|
|
3
4
|
export { DEFAULT_CLIENT_CONFIG as DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, IParameterStore, IParameterStoreInstance, parameterStore, TGetSecret, TGetSecrets, } from './parameterStore';
|
|
4
|
-
export { DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, IEmailAttachment, IEmailOptions, ISES, ISESInstance, ses, TSendMail, } from './ses';
|
|
5
|
+
export { DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, IEmailAttachment, IEmailEnvelope, IEmailOptions, IEmailSESOptions, ISES, ISESInstance, ses, TSendMail, } from './ses';
|
|
5
6
|
export { ISQS, ISQSInstance, sqs, TDeleteQueueItem, TGetQueueItems, TGetQueueUrl, TSendMessage, } from './sqs';
|
package/dist/src/aws/ses.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SESv2ClientConfig } from '@aws-sdk/client-sesv2';
|
|
1
|
+
import { SendEmailCommandInput, SESv2ClientConfig } from '@aws-sdk/client-sesv2';
|
|
2
2
|
import { Headers } from 'nodemailer/lib/mailer';
|
|
3
3
|
import { Logger } from 'winston';
|
|
4
4
|
export interface ISES {
|
|
@@ -16,14 +16,29 @@ export interface IEmailAttachment {
|
|
|
16
16
|
readonly contentType: string;
|
|
17
17
|
readonly filename: string;
|
|
18
18
|
}
|
|
19
|
+
export interface IEmailEnvelope {
|
|
20
|
+
readonly from?: string;
|
|
21
|
+
readonly to?: string | readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export interface IEmailSESOptions {
|
|
24
|
+
readonly ConfigurationSetName?: SendEmailCommandInput['ConfigurationSetName'];
|
|
25
|
+
readonly EmailTags?: SendEmailCommandInput['EmailTags'];
|
|
26
|
+
readonly FeedbackForwardingEmailAddress?: SendEmailCommandInput['FeedbackForwardingEmailAddress'];
|
|
27
|
+
}
|
|
19
28
|
export interface IEmailOptions {
|
|
20
29
|
readonly attachments?: readonly IEmailAttachment[];
|
|
21
30
|
readonly bcc?: string | readonly string[];
|
|
22
31
|
readonly cc?: string | readonly string[];
|
|
32
|
+
readonly envelope?: IEmailEnvelope;
|
|
23
33
|
readonly from: string;
|
|
24
34
|
readonly headers?: Headers;
|
|
25
35
|
readonly html?: string;
|
|
36
|
+
readonly inReplyTo?: string;
|
|
37
|
+
readonly messageId?: string;
|
|
38
|
+
readonly references?: string | readonly string[];
|
|
26
39
|
readonly replyTo?: string | readonly string[];
|
|
40
|
+
readonly sender?: string;
|
|
41
|
+
readonly ses?: IEmailSESOptions;
|
|
27
42
|
readonly subject: string;
|
|
28
43
|
readonly text?: string;
|
|
29
44
|
readonly to: string | readonly string[];
|
|
@@ -33,3 +48,4 @@ export interface ISESInstance {
|
|
|
33
48
|
sendMail: TSendMail;
|
|
34
49
|
}
|
|
35
50
|
export declare const ses: (userConfig: ISES) => ISESInstance;
|
|
51
|
+
export { AUTO_RESPONSE_SUPPRESSION_HEADERS, emailHeaders, IEmailHeaderOptions, } from './emailHeaders';
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Alagarr, alagarr, ClientError, HandlerFunction, IInterfaceAlagarrOptions, IInterfaceHeaders, IInterfaceQueryParameters, IInterfaceRequest, IInterfaceResponse, ServerError, } from './alagarr';
|
|
2
|
-
export { DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_SES_CLIENT_CONFIG, dynamodb, IDynamoDBConfig, IDynamoDBInstance, IEmailAttachment, IEmailOptions, ILambda, ILambdaInstance, IParameterStore, IParameterStoreInstance, ISES, ISESInstance, ISQS, ISQSInstance, IUnprocessedItems, lambda, parameterStore, ses, sqs, TBatchWriteItems, TDeleteItem, TDeleteQueueItem, TGetItem, TGetQueueItems, TGetQueueUrl, TGetSecret, TGetSecrets, TInvokeLambda, TPutItem, TQueryTable, TScanTable, TSendMail, TSendMessage, TUpdateItem, } from './aws';
|
|
2
|
+
export { AUTO_RESPONSE_SUPPRESSION_HEADERS, DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_SES_CLIENT_CONFIG, dynamodb, emailHeaders, IDynamoDBConfig, IDynamoDBInstance, IEmailAttachment, IEmailEnvelope, IEmailHeaderOptions, IEmailOptions, IEmailSESOptions, ILambda, ILambdaInstance, IParameterStore, IParameterStoreInstance, ISES, ISESInstance, ISQS, ISQSInstance, IUnprocessedItems, lambda, parameterStore, ses, sqs, TBatchWriteItems, TDeleteItem, TDeleteQueueItem, TGetItem, TGetQueueItems, TGetQueueUrl, TGetSecret, TGetSecrets, TInvokeLambda, TPutItem, TQueryTable, TScanTable, TSendMail, TSendMessage, TUpdateItem, } from './aws';
|
|
3
3
|
export { atob, btoa } from './base64';
|
|
4
4
|
export { logger } from './logger/logger';
|
|
5
5
|
export { asyncReduce, deepFlatten, flatten, List, partial, splitEvery, times, until, } from './utils';
|