@bitblit/ratchet-aws 4.0.80-alpha
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/cjs/batch/aws-batch-background-processor.js +44 -0
- package/dist/cjs/batch/aws-batch-ratchet.js +55 -0
- package/dist/cjs/build/ratchet-aws-info.js +18 -0
- package/dist/cjs/cache/dynamo-db-storage-provider.js +111 -0
- package/dist/cjs/cache/s3-storage-provider.js +44 -0
- package/dist/cjs/cache/simple-cache-object-wrapper.js +2 -0
- package/dist/cjs/cache/simple-cache-read-options.js +2 -0
- package/dist/cjs/cache/simple-cache-storage-provider.js +2 -0
- package/dist/cjs/cache/simple-cache.js +66 -0
- package/dist/cjs/cloudwatch/cloud-watch-log-group-ratchet.js +73 -0
- package/dist/cjs/cloudwatch/cloud-watch-logs-ratchet.js +173 -0
- package/dist/cjs/cloudwatch/cloud-watch-metrics-ratchet.js +57 -0
- package/dist/cjs/daemon/daemon-like.js +2 -0
- package/dist/cjs/daemon/daemon-process-create-options.js +2 -0
- package/dist/cjs/daemon/daemon-process-state-public-token.js +2 -0
- package/dist/cjs/daemon/daemon-process-state.js +2 -0
- package/dist/cjs/daemon/daemon-util.js +152 -0
- package/dist/cjs/daemon/daemon.js +126 -0
- package/dist/cjs/dao/prototype-dao-config.js +2 -0
- package/dist/cjs/dao/prototype-dao-db.js +2 -0
- package/dist/cjs/dao/prototype-dao-provider.js +2 -0
- package/dist/cjs/dao/prototype-dao.js +88 -0
- package/dist/cjs/dao/s3-prototype-dao-provider.js +28 -0
- package/dist/cjs/dao/s3-simple-dao.js +78 -0
- package/dist/cjs/dao/simple-dao-item.js +2 -0
- package/dist/cjs/dynamodb/dynamo-ratchet-like.js +2 -0
- package/dist/cjs/dynamodb/dynamo-ratchet.js +667 -0
- package/dist/cjs/dynamodb/dynamo-table-ratchet.js +91 -0
- package/dist/cjs/dynamodb/hash-spreader.js +62 -0
- package/dist/cjs/ec2/ec2-ratchet.js +107 -0
- package/dist/cjs/environment/cascade-environment-service-provider.js +27 -0
- package/dist/cjs/environment/env-var-environment-service-provider.js +33 -0
- package/dist/cjs/environment/environment-service-config.js +2 -0
- package/dist/cjs/environment/environment-service-provider.js +2 -0
- package/dist/cjs/environment/environment-service.js +52 -0
- package/dist/cjs/environment/fixed-environment-service-provider.js +24 -0
- package/dist/cjs/environment/s3-environment-service-provider.js +29 -0
- package/dist/cjs/environment/ssm-environment-service-provider.js +61 -0
- package/dist/cjs/expiring-code/dynamo-expiring-code-provider.js +26 -0
- package/dist/cjs/expiring-code/expiring-code-params.js +2 -0
- package/dist/cjs/expiring-code/expiring-code-provider.js +2 -0
- package/dist/cjs/expiring-code/expiring-code-ratchet.js +37 -0
- package/dist/cjs/expiring-code/expiring-code.js +2 -0
- package/dist/cjs/expiring-code/s3-expiring-code-provider.js +49 -0
- package/dist/cjs/iam/aws-credentials-ratchet.js +21 -0
- package/dist/cjs/index.js +81 -0
- package/dist/cjs/lambda/lambda-event-detector.js +42 -0
- package/dist/cjs/lambda/lambda-event-type-guards.js +28 -0
- package/dist/cjs/model/cloud-watch-metrics-minute-level-dynamo-count-request.js +2 -0
- package/dist/cjs/model/cloud-watch-metrics-unit.js +33 -0
- package/dist/cjs/model/dynamo/doc-put-item-command-input.js +2 -0
- package/dist/cjs/model/dynamo/doc-query-command-input.js +2 -0
- package/dist/cjs/model/dynamo/doc-scan-command-input.js +2 -0
- package/dist/cjs/model/dynamo/doc-update-item-command-input.js +2 -0
- package/dist/cjs/model/dynamo-count-result.js +2 -0
- package/dist/cjs/route53/route-53-ratchet.js +57 -0
- package/dist/cjs/runtime-parameter/cached-stored-runtime-parameter.js +2 -0
- package/dist/cjs/runtime-parameter/dynamo-runtime-parameter-provider.js +38 -0
- package/dist/cjs/runtime-parameter/global-variable-override-runtime-parameter-provider.js +54 -0
- package/dist/cjs/runtime-parameter/memory-runtime-parameter-provider.js +30 -0
- package/dist/cjs/runtime-parameter/runtime-parameter-provider.js +2 -0
- package/dist/cjs/runtime-parameter/runtime-parameter-ratchet.js +74 -0
- package/dist/cjs/runtime-parameter/stored-runtime-parameter.js +2 -0
- package/dist/cjs/s3/s3-cache-ratchet.js +332 -0
- package/dist/cjs/s3/s3-cache-to-local-disk-ratchet.js +105 -0
- package/dist/cjs/s3/s3-location-sync-ratchet.js +142 -0
- package/dist/cjs/s3/s3-ratchet.js +26 -0
- package/dist/cjs/ses/email-attachment.js +2 -0
- package/dist/cjs/ses/mailer-config.js +2 -0
- package/dist/cjs/ses/mailer-like.js +2 -0
- package/dist/cjs/ses/mailer.js +208 -0
- package/dist/cjs/ses/ratchet-template-renderer.js +2 -0
- package/dist/cjs/ses/ready-to-send-email.js +2 -0
- package/dist/cjs/ses/remote-handlebars-template-renderer.js +79 -0
- package/dist/cjs/ses/resolved-ready-to-send-email.js +2 -0
- package/dist/cjs/sns/sns-ratchet.js +47 -0
- package/dist/cjs/sync-lock/dynamo-db-sync-lock.js +69 -0
- package/dist/cjs/sync-lock/memory-sync-lock.js +40 -0
- package/dist/cjs/sync-lock/sync-lock-provider.js +2 -0
- package/dist/es/batch/aws-batch-background-processor.js +40 -0
- package/dist/es/batch/aws-batch-ratchet.js +51 -0
- package/dist/es/build/ratchet-aws-info.js +14 -0
- package/dist/es/cache/dynamo-db-storage-provider.js +107 -0
- package/dist/es/cache/s3-storage-provider.js +40 -0
- package/dist/es/cache/simple-cache-object-wrapper.js +1 -0
- package/dist/es/cache/simple-cache-read-options.js +1 -0
- package/dist/es/cache/simple-cache-storage-provider.js +1 -0
- package/dist/es/cache/simple-cache.js +62 -0
- package/dist/es/cloudwatch/cloud-watch-log-group-ratchet.js +69 -0
- package/dist/es/cloudwatch/cloud-watch-logs-ratchet.js +169 -0
- package/dist/es/cloudwatch/cloud-watch-metrics-ratchet.js +53 -0
- package/dist/es/daemon/daemon-like.js +1 -0
- package/dist/es/daemon/daemon-process-create-options.js +1 -0
- package/dist/es/daemon/daemon-process-state-public-token.js +1 -0
- package/dist/es/daemon/daemon-process-state.js +1 -0
- package/dist/es/daemon/daemon-util.js +148 -0
- package/dist/es/daemon/daemon.js +122 -0
- package/dist/es/dao/prototype-dao-config.js +1 -0
- package/dist/es/dao/prototype-dao-db.js +1 -0
- package/dist/es/dao/prototype-dao-provider.js +1 -0
- package/dist/es/dao/prototype-dao.js +84 -0
- package/dist/es/dao/s3-prototype-dao-provider.js +24 -0
- package/dist/es/dao/s3-simple-dao.js +74 -0
- package/dist/es/dao/simple-dao-item.js +1 -0
- package/dist/es/dynamodb/dynamo-ratchet-like.js +1 -0
- package/dist/es/dynamodb/dynamo-ratchet.js +663 -0
- package/dist/es/dynamodb/dynamo-table-ratchet.js +87 -0
- package/dist/es/dynamodb/hash-spreader.js +58 -0
- package/dist/es/ec2/ec2-ratchet.js +103 -0
- package/dist/es/environment/cascade-environment-service-provider.js +23 -0
- package/dist/es/environment/env-var-environment-service-provider.js +29 -0
- package/dist/es/environment/environment-service-config.js +1 -0
- package/dist/es/environment/environment-service-provider.js +1 -0
- package/dist/es/environment/environment-service.js +48 -0
- package/dist/es/environment/fixed-environment-service-provider.js +20 -0
- package/dist/es/environment/s3-environment-service-provider.js +25 -0
- package/dist/es/environment/ssm-environment-service-provider.js +56 -0
- package/dist/es/expiring-code/dynamo-expiring-code-provider.js +22 -0
- package/dist/es/expiring-code/expiring-code-params.js +1 -0
- package/dist/es/expiring-code/expiring-code-provider.js +1 -0
- package/dist/es/expiring-code/expiring-code-ratchet.js +33 -0
- package/dist/es/expiring-code/expiring-code.js +1 -0
- package/dist/es/expiring-code/s3-expiring-code-provider.js +45 -0
- package/dist/es/iam/aws-credentials-ratchet.js +17 -0
- package/dist/es/index.js +78 -0
- package/dist/es/lambda/lambda-event-detector.js +38 -0
- package/dist/es/lambda/lambda-event-type-guards.js +24 -0
- package/dist/es/model/cloud-watch-metrics-minute-level-dynamo-count-request.js +1 -0
- package/dist/es/model/cloud-watch-metrics-unit.js +30 -0
- package/dist/es/model/dynamo/doc-put-item-command-input.js +1 -0
- package/dist/es/model/dynamo/doc-query-command-input.js +1 -0
- package/dist/es/model/dynamo/doc-scan-command-input.js +1 -0
- package/dist/es/model/dynamo/doc-update-item-command-input.js +1 -0
- package/dist/es/model/dynamo-count-result.js +1 -0
- package/dist/es/route53/route-53-ratchet.js +53 -0
- package/dist/es/runtime-parameter/cached-stored-runtime-parameter.js +1 -0
- package/dist/es/runtime-parameter/dynamo-runtime-parameter-provider.js +34 -0
- package/dist/es/runtime-parameter/global-variable-override-runtime-parameter-provider.js +49 -0
- package/dist/es/runtime-parameter/memory-runtime-parameter-provider.js +26 -0
- package/dist/es/runtime-parameter/runtime-parameter-provider.js +1 -0
- package/dist/es/runtime-parameter/runtime-parameter-ratchet.js +70 -0
- package/dist/es/runtime-parameter/stored-runtime-parameter.js +1 -0
- package/dist/es/s3/s3-cache-ratchet.js +328 -0
- package/dist/es/s3/s3-cache-to-local-disk-ratchet.js +100 -0
- package/dist/es/s3/s3-location-sync-ratchet.js +137 -0
- package/dist/es/s3/s3-ratchet.js +22 -0
- package/dist/es/ses/email-attachment.js +1 -0
- package/dist/es/ses/mailer-config.js +1 -0
- package/dist/es/ses/mailer-like.js +1 -0
- package/dist/es/ses/mailer.js +204 -0
- package/dist/es/ses/ratchet-template-renderer.js +1 -0
- package/dist/es/ses/ready-to-send-email.js +1 -0
- package/dist/es/ses/remote-handlebars-template-renderer.js +74 -0
- package/dist/es/ses/resolved-ready-to-send-email.js +1 -0
- package/dist/es/sns/sns-ratchet.js +43 -0
- package/dist/es/sync-lock/dynamo-db-sync-lock.js +65 -0
- package/dist/es/sync-lock/memory-sync-lock.js +36 -0
- package/dist/es/sync-lock/sync-lock-provider.js +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.es.tsbuildinfo +1 -0
- package/dist/tsconfig.types.tsbuildinfo +1 -0
- package/dist/types/batch/aws-batch-background-processor.d.ts +12 -0
- package/dist/types/batch/aws-batch-ratchet.d.ts +16 -0
- package/dist/types/build/ratchet-aws-info.d.ts +5 -0
- package/dist/types/cache/dynamo-db-storage-provider.d.ts +25 -0
- package/dist/types/cache/s3-storage-provider.d.ts +14 -0
- package/dist/types/cache/simple-cache-object-wrapper.d.ts +7 -0
- package/dist/types/cache/simple-cache-read-options.d.ts +5 -0
- package/dist/types/cache/simple-cache-storage-provider.d.ts +8 -0
- package/dist/types/cache/simple-cache.d.ts +14 -0
- package/dist/types/cloudwatch/cloud-watch-log-group-ratchet.d.ts +9 -0
- package/dist/types/cloudwatch/cloud-watch-logs-ratchet.d.ts +14 -0
- package/dist/types/cloudwatch/cloud-watch-metrics-ratchet.d.ts +10 -0
- package/dist/types/daemon/daemon-like.d.ts +17 -0
- package/dist/types/daemon/daemon-process-create-options.d.ts +7 -0
- package/dist/types/daemon/daemon-process-state-public-token.d.ts +4 -0
- package/dist/types/daemon/daemon-process-state.d.ts +13 -0
- package/dist/types/daemon/daemon-util.d.ts +24 -0
- package/dist/types/daemon/daemon.d.ts +33 -0
- package/dist/types/dao/prototype-dao-config.d.ts +8 -0
- package/dist/types/dao/prototype-dao-db.d.ts +4 -0
- package/dist/types/dao/prototype-dao-provider.d.ts +5 -0
- package/dist/types/dao/prototype-dao.d.ts +15 -0
- package/dist/types/dao/s3-prototype-dao-provider.d.ts +10 -0
- package/dist/types/dao/s3-simple-dao.d.ts +15 -0
- package/dist/types/dao/simple-dao-item.d.ts +5 -0
- package/dist/types/dynamodb/dynamo-ratchet-like.d.ts +27 -0
- package/dist/types/dynamodb/dynamo-ratchet.d.ts +36 -0
- package/dist/types/dynamodb/dynamo-table-ratchet.d.ts +11 -0
- package/dist/types/dynamodb/hash-spreader.d.ts +15 -0
- package/dist/types/ec2/ec2-ratchet.d.ts +25 -0
- package/dist/types/environment/cascade-environment-service-provider.d.ts +9 -0
- package/dist/types/environment/env-var-environment-service-provider.d.ts +10 -0
- package/dist/types/environment/environment-service-config.d.ts +7 -0
- package/dist/types/environment/environment-service-provider.d.ts +7 -0
- package/dist/types/environment/environment-service.d.ts +14 -0
- package/dist/types/environment/fixed-environment-service-provider.d.ts +10 -0
- package/dist/types/environment/s3-environment-service-provider.d.ts +18 -0
- package/dist/types/environment/ssm-environment-service-provider.d.ts +12 -0
- package/dist/types/expiring-code/dynamo-expiring-code-provider.d.ts +12 -0
- package/dist/types/expiring-code/expiring-code-params.d.ts +7 -0
- package/dist/types/expiring-code/expiring-code-provider.d.ts +5 -0
- package/dist/types/expiring-code/expiring-code-ratchet.d.ts +13 -0
- package/dist/types/expiring-code/expiring-code.d.ts +6 -0
- package/dist/types/expiring-code/s3-expiring-code-provider.d.ts +17 -0
- package/dist/types/iam/aws-credentials-ratchet.d.ts +9 -0
- package/dist/types/index.d.ts +81 -0
- package/dist/types/lambda/lambda-event-detector.d.ts +14 -0
- package/dist/types/lambda/lambda-event-type-guards.d.ts +10 -0
- package/dist/types/model/cloud-watch-metrics-minute-level-dynamo-count-request.d.ts +12 -0
- package/dist/types/model/cloud-watch-metrics-unit.d.ts +29 -0
- package/dist/types/model/dynamo/doc-put-item-command-input.d.ts +4 -0
- package/dist/types/model/dynamo/doc-query-command-input.d.ts +5 -0
- package/dist/types/model/dynamo/doc-scan-command-input.d.ts +5 -0
- package/dist/types/model/dynamo/doc-update-item-command-input.d.ts +5 -0
- package/dist/types/model/dynamo-count-result.d.ts +5 -0
- package/dist/types/route53/route-53-ratchet.d.ts +7 -0
- package/dist/types/runtime-parameter/cached-stored-runtime-parameter.d.ts +4 -0
- package/dist/types/runtime-parameter/dynamo-runtime-parameter-provider.d.ts +11 -0
- package/dist/types/runtime-parameter/global-variable-override-runtime-parameter-provider.d.ts +24 -0
- package/dist/types/runtime-parameter/memory-runtime-parameter-provider.d.ts +13 -0
- package/dist/types/runtime-parameter/runtime-parameter-provider.d.ts +11 -0
- package/dist/types/runtime-parameter/runtime-parameter-ratchet.d.ts +15 -0
- package/dist/types/runtime-parameter/stored-runtime-parameter.d.ts +6 -0
- package/dist/types/s3/s3-cache-ratchet.d.ts +38 -0
- package/dist/types/s3/s3-cache-to-local-disk-ratchet.d.ts +21 -0
- package/dist/types/s3/s3-location-sync-ratchet.d.ts +21 -0
- package/dist/types/s3/s3-ratchet.d.ts +5 -0
- package/dist/types/ses/email-attachment.d.ts +23 -0
- package/dist/types/ses/mailer-config.d.ts +15 -0
- package/dist/types/ses/mailer-like.d.ts +18 -0
- package/dist/types/ses/mailer.d.ts +26 -0
- package/dist/types/ses/ratchet-template-renderer.d.ts +8 -0
- package/dist/types/ses/ready-to-send-email.d.ts +66 -0
- package/dist/types/ses/remote-handlebars-template-renderer.d.ts +15 -0
- package/dist/types/ses/resolved-ready-to-send-email.d.ts +16 -0
- package/dist/types/sns/sns-ratchet.d.ts +8 -0
- package/dist/types/sync-lock/dynamo-db-sync-lock.d.ts +10 -0
- package/dist/types/sync-lock/memory-sync-lock.d.ts +11 -0
- package/dist/types/sync-lock/sync-lock-provider.d.ts +5 -0
- package/package.json +112 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Logger } from '@bitblit/ratchet-common';
|
|
2
|
+
import { SendRawEmailCommand } from '@aws-sdk/client-ses';
|
|
3
|
+
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
4
|
+
import { ErrorRatchet } from '@bitblit/ratchet-common';
|
|
5
|
+
import { DateTime } from 'luxon';
|
|
6
|
+
import { Base64Ratchet } from '@bitblit/ratchet-common';
|
|
7
|
+
import { RequireRatchet } from '@bitblit/ratchet-common';
|
|
8
|
+
export class Mailer {
|
|
9
|
+
constructor(ses, config = {}) {
|
|
10
|
+
this.ses = ses;
|
|
11
|
+
this.config = config;
|
|
12
|
+
RequireRatchet.notNullOrUndefined(this.ses);
|
|
13
|
+
if (!!config.archive && !config.archive.getDefaultBucket()) {
|
|
14
|
+
throw new Error('If archive specified, must set a default bucket');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async fillEmailBody(rts, context, htmlTemplateName, txtTemplateName = null, layoutName = null, partialNames = null) {
|
|
18
|
+
RequireRatchet.notNullOrUndefined(htmlTemplateName);
|
|
19
|
+
if (!this.config.templateRenderer) {
|
|
20
|
+
ErrorRatchet.throwFormattedErr('Cannot use fill body if template renderer not set');
|
|
21
|
+
}
|
|
22
|
+
rts.htmlMessage = await this.config.templateRenderer.renderTemplate(htmlTemplateName, context, layoutName, partialNames);
|
|
23
|
+
rts.txtMessage = !!txtTemplateName ? await this.config.templateRenderer.renderTemplate(txtTemplateName, context) : null;
|
|
24
|
+
return rts;
|
|
25
|
+
}
|
|
26
|
+
async fillEmailBodyAndSend(rts, context, htmlTemplateName, txtTemplateName = null, layoutName = null, partialNames = null) {
|
|
27
|
+
const newVal = await this.fillEmailBody(rts, context, htmlTemplateName, txtTemplateName, layoutName, partialNames);
|
|
28
|
+
const rval = await this.sendEmail(newVal);
|
|
29
|
+
return rval;
|
|
30
|
+
}
|
|
31
|
+
filterEmailsToValid(emails) {
|
|
32
|
+
const rval = (emails || []).filter((e) => {
|
|
33
|
+
if (!this.config.allowedDestinationEmails || this.config.allowedDestinationEmails.length == 0) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const match = this.config.allowedDestinationEmails.find((s) => s.test(e));
|
|
38
|
+
return !!match;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return rval;
|
|
42
|
+
}
|
|
43
|
+
async archiveEmailIfConfigured(rts) {
|
|
44
|
+
let rval = false;
|
|
45
|
+
if (!!rts && !!this.config.archive && !rts.doNotArchive) {
|
|
46
|
+
Logger.debug('Archiving outbound email to : %j', rts.destinationAddresses);
|
|
47
|
+
let targetPath = StringRatchet.trimToEmpty(this.config.archivePrefix);
|
|
48
|
+
if (!targetPath.endsWith('/')) {
|
|
49
|
+
targetPath += '/';
|
|
50
|
+
}
|
|
51
|
+
const now = DateTime.utc();
|
|
52
|
+
targetPath +=
|
|
53
|
+
'year=' +
|
|
54
|
+
now.toFormat('yyyy') +
|
|
55
|
+
'/month=' +
|
|
56
|
+
now.toFormat('MM') +
|
|
57
|
+
'/day=' +
|
|
58
|
+
now.toFormat('dd') +
|
|
59
|
+
'/hour=' +
|
|
60
|
+
now.toFormat('HH') +
|
|
61
|
+
'/' +
|
|
62
|
+
now.toFormat('mm_ss__SSS');
|
|
63
|
+
targetPath += '.json';
|
|
64
|
+
try {
|
|
65
|
+
await this.config.archive.writeObjectToCacheFile(targetPath, rts);
|
|
66
|
+
rval = true;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
Logger.warn('Failed to archive email %s %j : %s', targetPath, rts, err);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return rval;
|
|
73
|
+
}
|
|
74
|
+
applyLimitsToBodySizesIfAnyInPlace(rts) {
|
|
75
|
+
if (this.config.maxMessageBodySizeInBytes) {
|
|
76
|
+
const txtSize = StringRatchet.trimToEmpty(rts.txtMessage).length;
|
|
77
|
+
const htmlSize = StringRatchet.trimToEmpty(rts.htmlMessage).length;
|
|
78
|
+
const totalSize = txtSize + htmlSize;
|
|
79
|
+
if (totalSize > this.config.maxMessageBodySizeInBytes) {
|
|
80
|
+
Logger.warn('Max message size is %d but size is %d - converting', this.config.maxMessageBodySizeInBytes, totalSize);
|
|
81
|
+
rts.attachments = rts.attachments || [];
|
|
82
|
+
if (StringRatchet.trimToNull(rts.txtMessage)) {
|
|
83
|
+
const txtAttach = {
|
|
84
|
+
filename: 'original-txt-body.txt',
|
|
85
|
+
contentType: 'text/plain',
|
|
86
|
+
base64Data: Base64Ratchet.generateBase64VersionOfString(rts.txtMessage),
|
|
87
|
+
};
|
|
88
|
+
rts.attachments.push(txtAttach);
|
|
89
|
+
}
|
|
90
|
+
if (StringRatchet.trimToNull(rts.htmlMessage)) {
|
|
91
|
+
const htmlAttach = {
|
|
92
|
+
filename: 'original-html-body.html',
|
|
93
|
+
contentType: 'text/html',
|
|
94
|
+
base64Data: Base64Ratchet.generateBase64VersionOfString(rts.htmlMessage),
|
|
95
|
+
};
|
|
96
|
+
rts.attachments.push(htmlAttach);
|
|
97
|
+
}
|
|
98
|
+
rts.htmlMessage = null;
|
|
99
|
+
rts.txtMessage = 'The message was too large and was converted to attachment(s). Please see attached files for content';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
applyLimitsToAttachmentSizesIfAnyInPlace(rts) {
|
|
104
|
+
if (this.config.maxAttachmentSizeInBase64Bytes) {
|
|
105
|
+
const filtered = [];
|
|
106
|
+
if (rts.attachments) {
|
|
107
|
+
rts.attachments.forEach((a) => {
|
|
108
|
+
if (a.base64Data && a.base64Data.length < this.config.maxAttachmentSizeInBase64Bytes) {
|
|
109
|
+
filtered.push(a);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
Logger.warn('Removing too-large attachment : %s : %s : %d', a.filename, a.contentType, a.base64Data.length);
|
|
113
|
+
filtered.push({
|
|
114
|
+
filename: 'attachment-removed-notice-' + StringRatchet.createRandomHexString(4) + '.txt',
|
|
115
|
+
contentType: 'text/plain',
|
|
116
|
+
base64Data: Base64Ratchet.generateBase64VersionOfString('Attachment ' +
|
|
117
|
+
a.filename +
|
|
118
|
+
' of type ' +
|
|
119
|
+
a.contentType +
|
|
120
|
+
' was removed since it was ' +
|
|
121
|
+
a.base64Data.length +
|
|
122
|
+
' bytes but max allowed is ' +
|
|
123
|
+
this.config.maxAttachmentSizeInBase64Bytes),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
rts.attachments = filtered;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async sendEmail(inRts) {
|
|
132
|
+
RequireRatchet.notNullOrUndefined(inRts, 'RTS must be defined');
|
|
133
|
+
RequireRatchet.notNullOrUndefined(inRts.destinationAddresses, 'Destination addresses must be defined');
|
|
134
|
+
let rval = null;
|
|
135
|
+
let toAddresses = this.filterEmailsToValid(inRts.destinationAddresses);
|
|
136
|
+
const autoBcc = inRts.doNotAutoBcc ? [] : this.config.autoBccAddresses || [];
|
|
137
|
+
const bccAddresses = (inRts.bccAddresses || []).concat(autoBcc);
|
|
138
|
+
if (toAddresses.length === 0 && bccAddresses.length > 0) {
|
|
139
|
+
Logger.debug('Destination emails filtered to none but BCC defined, copying BCC');
|
|
140
|
+
toAddresses = bccAddresses;
|
|
141
|
+
}
|
|
142
|
+
const rts = Object.assign({}, inRts);
|
|
143
|
+
rts.srcDestinationAddresses = inRts.destinationAddresses;
|
|
144
|
+
rts.srcBccAddresses = inRts.bccAddresses;
|
|
145
|
+
rts.destinationAddresses = toAddresses;
|
|
146
|
+
rts.bccAddresses = bccAddresses;
|
|
147
|
+
this.applyLimitsToBodySizesIfAnyInPlace(rts);
|
|
148
|
+
this.applyLimitsToAttachmentSizesIfAnyInPlace(rts);
|
|
149
|
+
await this.archiveEmailIfConfigured(rts);
|
|
150
|
+
if (rts.destinationAddresses.length === 0) {
|
|
151
|
+
Logger.info('After cleaning email lists, no destination addresses left - not sending email');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const toLine = 'To: ' + rts.destinationAddresses.join(', ') + '\n';
|
|
155
|
+
const bccLine = !!rts.bccAddresses && rts.bccAddresses.length > 0 ? 'Bcc: ' + rts.bccAddresses.join(', ') + '\n' : '';
|
|
156
|
+
try {
|
|
157
|
+
const from = rts.fromAddress || this.config.defaultSendingAddress;
|
|
158
|
+
const boundary = 'NextPart';
|
|
159
|
+
const altBoundary = 'AltPart';
|
|
160
|
+
let rawMail = 'From: ' + from + '\n';
|
|
161
|
+
rawMail += toLine;
|
|
162
|
+
rawMail += bccLine;
|
|
163
|
+
rawMail += 'Subject: ' + rts.subject + '\n';
|
|
164
|
+
rawMail += 'MIME-Version: 1.0\n';
|
|
165
|
+
rawMail += 'Content-Type: multipart/mixed; boundary="' + boundary + '"\n';
|
|
166
|
+
rawMail += '\n\n--' + boundary + '\n';
|
|
167
|
+
rawMail += 'Content-Type: multipart/alternative; boundary="' + altBoundary + '"\n';
|
|
168
|
+
if (!!StringRatchet.trimToNull(rts.htmlMessage)) {
|
|
169
|
+
rawMail += '\n\n--' + altBoundary + '\n';
|
|
170
|
+
rawMail += 'Content-Type: text/html; charset="UTF-8"\n\n';
|
|
171
|
+
rawMail += rts.htmlMessage;
|
|
172
|
+
}
|
|
173
|
+
if (!!StringRatchet.trimToNull(rts.txtMessage)) {
|
|
174
|
+
rawMail += '\n\n--' + altBoundary + '\n';
|
|
175
|
+
rawMail += 'Content-Type: text/plain\n\n';
|
|
176
|
+
rawMail += rts.txtMessage;
|
|
177
|
+
}
|
|
178
|
+
rawMail += '\n\n--' + altBoundary + '--\n';
|
|
179
|
+
if (rts.attachments) {
|
|
180
|
+
rts.attachments.forEach((a) => {
|
|
181
|
+
rawMail += '\n\n--' + boundary + '\n';
|
|
182
|
+
rawMail += 'Content-Type: ' + a.contentType + '; name="' + a.filename + '"\n';
|
|
183
|
+
rawMail += 'Content-Transfer-Encoding: base64\n';
|
|
184
|
+
rawMail += 'Content-Disposition: attachment\n\n';
|
|
185
|
+
rawMail += a.base64Data.replace(/([^\0]{76})/g, '$1\n') + '\n\n';
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
rawMail += '\n\n--' + boundary + '--\n';
|
|
189
|
+
const params = {
|
|
190
|
+
RawMessage: { Data: new TextEncoder().encode(rawMail) },
|
|
191
|
+
};
|
|
192
|
+
rval = await this.ses.send(new SendRawEmailCommand(params));
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
Logger.error('Error while processing email: %s', err, err);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return rval;
|
|
199
|
+
}
|
|
200
|
+
static validEmail(email) {
|
|
201
|
+
return email !== null && Mailer.EMAIL.test(email);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
Mailer.EMAIL = new RegExp('.+@.+\\.[a-z]+');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import handlebars from 'handlebars';
|
|
2
|
+
import fetch from 'cross-fetch';
|
|
3
|
+
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
4
|
+
import { Logger } from '@bitblit/ratchet-common';
|
|
5
|
+
import layouts from 'handlebars-layouts';
|
|
6
|
+
export class RemoteHandlebarsTemplateRenderer {
|
|
7
|
+
constructor(prefix = '', suffix = '', maxCacheTemplates = 10) {
|
|
8
|
+
this.prefix = prefix;
|
|
9
|
+
this.suffix = suffix;
|
|
10
|
+
this.maxCacheTemplates = maxCacheTemplates;
|
|
11
|
+
if (this.maxCacheTemplates > 0) {
|
|
12
|
+
this.cache = new Map();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async renderTemplate(templateName, context, layoutName = null) {
|
|
16
|
+
return this.renderRemoteTemplate(templateName, context, layoutName);
|
|
17
|
+
}
|
|
18
|
+
async renderRemoteTemplate(templateName, inContext, layoutName = null) {
|
|
19
|
+
const template = await this.fetchTemplate(templateName);
|
|
20
|
+
const layoutText = !!layoutName ? await this.fetchTemplateText(layoutName) : null;
|
|
21
|
+
if (!!layoutText) {
|
|
22
|
+
await layouts.register(handlebars);
|
|
23
|
+
handlebars.registerPartial(layoutName, layoutText);
|
|
24
|
+
}
|
|
25
|
+
const context = inContext || {};
|
|
26
|
+
const result = !!template ? template(context) : null;
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
async renderTemplateDirect(templateText, context, layoutName = null) {
|
|
30
|
+
const template = handlebars.compile(templateText);
|
|
31
|
+
const result = template(context);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async fetchTemplate(templateName) {
|
|
35
|
+
let rval = null;
|
|
36
|
+
try {
|
|
37
|
+
if (!!this.cache && this.cache.has(templateName)) {
|
|
38
|
+
Logger.silly('Cache hit for template : %s', templateName);
|
|
39
|
+
rval = this.cache.get(templateName);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
Logger.debug('Cache miss for template : %s', templateName);
|
|
43
|
+
const templateText = await this.fetchTemplateText(templateName);
|
|
44
|
+
if (!!templateText) {
|
|
45
|
+
rval = handlebars.compile(templateText);
|
|
46
|
+
if (!!this.cache && !!rval) {
|
|
47
|
+
this.cache.set(templateName, rval);
|
|
48
|
+
if (this.cache.size > this.maxCacheTemplates) {
|
|
49
|
+
this.cache.delete(Array.from(this.cache.keys())[0]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
Logger.warn('Could not fetch and compile template : %s : %s', templateName, err, err);
|
|
57
|
+
rval = null;
|
|
58
|
+
}
|
|
59
|
+
return rval;
|
|
60
|
+
}
|
|
61
|
+
async fetchTemplateText(templateName) {
|
|
62
|
+
let rval = null;
|
|
63
|
+
const url = StringRatchet.trimToEmpty(this.prefix) + templateName + StringRatchet.trimToEmpty(this.suffix);
|
|
64
|
+
try {
|
|
65
|
+
const resp = await fetch(url);
|
|
66
|
+
rval = await resp.text();
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
Logger.warn('Could not fetch url : %s : %s', url, err, err);
|
|
70
|
+
rval = null;
|
|
71
|
+
}
|
|
72
|
+
return rval;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Logger } from '@bitblit/ratchet-common';
|
|
2
|
+
import { PublishCommand, SNSClient } from '@aws-sdk/client-sns';
|
|
3
|
+
import { RequireRatchet } from '@bitblit/ratchet-common';
|
|
4
|
+
export class SnsRatchet {
|
|
5
|
+
constructor(sns = new SNSClient({ region: 'us-east-1' }), topicArn) {
|
|
6
|
+
this.sns = sns;
|
|
7
|
+
this.topicArn = topicArn;
|
|
8
|
+
RequireRatchet.notNullOrUndefined(this.sns, 'sns');
|
|
9
|
+
RequireRatchet.notNullOrUndefined(this.topicArn, 'topicArn');
|
|
10
|
+
}
|
|
11
|
+
async sendMessage(inMsg, suppressErrors = false) {
|
|
12
|
+
let result = null;
|
|
13
|
+
try {
|
|
14
|
+
const safeInMsg = inMsg ? inMsg : 'NO-MESSAGE-PROVIDED';
|
|
15
|
+
const msg = typeof safeInMsg === 'string' ? safeInMsg : JSON.stringify(safeInMsg);
|
|
16
|
+
const params = {
|
|
17
|
+
TopicArn: this.topicArn,
|
|
18
|
+
Message: msg,
|
|
19
|
+
};
|
|
20
|
+
Logger.debug('Sending via SNS : %j', params);
|
|
21
|
+
result = await this.sns.send(new PublishCommand(params));
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (suppressErrors) {
|
|
25
|
+
Logger.error('Failed to fire SNS notification : %j : %s', inMsg, err);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
async conditionallySendMessage(inMsg, condition, suppressErrors = false) {
|
|
34
|
+
let rval = null;
|
|
35
|
+
if (condition) {
|
|
36
|
+
rval = await this.sendMessage(inMsg, suppressErrors);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
Logger.info('Not sending message, condition was false : %j', inMsg);
|
|
40
|
+
}
|
|
41
|
+
return rval;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Logger, RequireRatchet, StringRatchet } from '@bitblit/ratchet-common';
|
|
2
|
+
import { PutItemCommand } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
export class DynamoDbSyncLock {
|
|
4
|
+
constructor(ratchet, tableName) {
|
|
5
|
+
this.ratchet = ratchet;
|
|
6
|
+
this.tableName = tableName;
|
|
7
|
+
RequireRatchet.notNullOrUndefined(ratchet, 'ratchet');
|
|
8
|
+
RequireRatchet.notNullOrUndefined(StringRatchet.trimToNull(this.tableName), 'tableName');
|
|
9
|
+
}
|
|
10
|
+
async acquireLock(lockKey, expirationSeconds = 30) {
|
|
11
|
+
let rval = false;
|
|
12
|
+
if (!!lockKey && !!expirationSeconds) {
|
|
13
|
+
const nowSeconds = Math.floor(new Date().getTime() / 1000);
|
|
14
|
+
const row = {
|
|
15
|
+
lockingKey: lockKey,
|
|
16
|
+
timestamp: nowSeconds,
|
|
17
|
+
expires: nowSeconds + expirationSeconds,
|
|
18
|
+
};
|
|
19
|
+
const params = {
|
|
20
|
+
Item: row,
|
|
21
|
+
ReturnConsumedCapacity: 'TOTAL',
|
|
22
|
+
TableName: this.tableName,
|
|
23
|
+
ConditionExpression: 'attribute_not_exists(lockingKey)',
|
|
24
|
+
};
|
|
25
|
+
try {
|
|
26
|
+
const pio = await this.ratchet.getDDB().send(new PutItemCommand(params));
|
|
27
|
+
rval = true;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (String(err).indexOf('ConditionalCheckFailedException') > -1) {
|
|
31
|
+
Logger.silly('Unable to acquire lock on %s', lockKey);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return rval;
|
|
36
|
+
}
|
|
37
|
+
async releaseLock(lockKey) {
|
|
38
|
+
if (StringRatchet.trimToNull(lockKey)) {
|
|
39
|
+
try {
|
|
40
|
+
const dio = await this.ratchet.simpleDelete(this.tableName, { lockingKey: lockKey });
|
|
41
|
+
Logger.silly('Released lock %s : %s', lockKey, dio);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
Logger.warn('Failed to release lock key : %s : %s', lockKey, err, err);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async clearExpiredSyncLocks() {
|
|
49
|
+
const nowSeconds = Math.floor(new Date().getTime() / 1000);
|
|
50
|
+
const scan = {
|
|
51
|
+
TableName: this.tableName,
|
|
52
|
+
FilterExpression: 'expires < :now',
|
|
53
|
+
ExpressionAttributeValues: {
|
|
54
|
+
':now': nowSeconds,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const vals = await this.ratchet.fullyExecuteScan(scan);
|
|
58
|
+
const keysOnly = vals.map((v) => {
|
|
59
|
+
const next = { lockingKey: v['lockingKey'] };
|
|
60
|
+
return next;
|
|
61
|
+
});
|
|
62
|
+
const removed = await this.ratchet.deleteAllInBatches(this.tableName, keysOnly, 25);
|
|
63
|
+
return removed;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StringRatchet } from '@bitblit/ratchet-common';
|
|
2
|
+
export class MemorySyncLock {
|
|
3
|
+
constructor() {
|
|
4
|
+
this._locks = new Map();
|
|
5
|
+
}
|
|
6
|
+
async acquireLock(lockKey, expirationSeconds = 30) {
|
|
7
|
+
let rval = false;
|
|
8
|
+
if (StringRatchet.trimToNull(lockKey)) {
|
|
9
|
+
const now = Date.now();
|
|
10
|
+
const val = this._locks.get(lockKey);
|
|
11
|
+
if (!val || val < now) {
|
|
12
|
+
this._locks.set(lockKey, now + expirationSeconds * 1000);
|
|
13
|
+
rval = true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return rval;
|
|
17
|
+
}
|
|
18
|
+
async releaseLock(lockKey) {
|
|
19
|
+
if (StringRatchet.trimToNull(lockKey)) {
|
|
20
|
+
this._locks.delete(lockKey);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async clearExpiredSyncLocks() {
|
|
24
|
+
const toRemove = [];
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
this._locks.forEach((v, k) => {
|
|
27
|
+
if (v < now) {
|
|
28
|
+
toRemove.push(k);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
toRemove.forEach((k) => {
|
|
32
|
+
this._locks.delete(k);
|
|
33
|
+
});
|
|
34
|
+
return toRemove.length;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|