@bitblit/ratchet-common
Version:
Common tools for general use
174 lines • 8.19 kB
JavaScript
import { RequireRatchet } from '../lang/require-ratchet.js';
import { ErrorRatchet } from '../lang/error-ratchet.js';
import { Logger } from '../logger/logger.js';
import { StringRatchet } from '../lang/string-ratchet.js';
import { Base64Ratchet } from '../lang/base64-ratchet.js';
export class Mailer {
config;
constructor(config) {
this.config = config;
RequireRatchet.notNullOrUndefined(config, 'config');
RequireRatchet.notNullOrUndefined(config.provider, 'config.provider');
}
async fillEmailBody(rts, context, htmlTemplateName, txtTemplateName = null, layoutName = null, partialNames = null) {
RequireRatchet.notNullOrUndefined(htmlTemplateName);
if (!this.config.templateRenderer) {
ErrorRatchet.throwFormattedErr('Cannot use fill body if template renderer not set');
}
rts.htmlMessage = await this.config.templateRenderer.renderTemplate(htmlTemplateName, context, layoutName, partialNames);
rts.txtMessage = txtTemplateName ? await this.config.templateRenderer.renderTemplate(txtTemplateName, context) : null;
return rts;
}
async fillEmailBodyAndSend(rts, context, htmlTemplateName, txtTemplateName = null, layoutName = null, partialNames = null) {
const newVal = await this.fillEmailBody(rts, context, htmlTemplateName, txtTemplateName, layoutName, partialNames);
const rval = await this.sendEmail(newVal);
return rval;
}
filterEmailsToValid(emails) {
const rval = (emails || []).filter((e) => {
if (!this.config.allowedDestinationEmails || this.config.allowedDestinationEmails.length == 0) {
return true;
}
else {
const match = this.config.allowedDestinationEmails.find((s) => s.test(e));
return !!match;
}
});
return rval;
}
async archiveEmailIfConfigured(rts, rawSendResult) {
let rval = null;
if (!!rts && !!this.config.provider.archiveEmail && !rts.doNotArchive) {
Logger.debug('Archiving outbound email to : %j', rts.destinationAddresses);
try {
const raw = await this.config.provider.archiveEmail(rts, rawSendResult);
rval = {
raw: raw,
error: null,
meta: {},
};
}
catch (err) {
Logger.warn('Failed to archive email %j : %s', rts, err);
rval = {
raw: null,
error: ErrorRatchet.safeStringifyErr(err),
meta: {},
};
}
}
return rval;
}
applyLimitsToBodySizesIfAnyInPlace(rts) {
if (this.config.maxMessageBodySizeInBytes) {
const txtSize = StringRatchet.trimToEmpty(rts.txtMessage).length;
const htmlSize = StringRatchet.trimToEmpty(rts.htmlMessage).length;
const totalSize = txtSize + htmlSize;
if (totalSize > this.config.maxMessageBodySizeInBytes) {
Logger.warn('Max message size is %d but size is %d - converting', this.config.maxMessageBodySizeInBytes, totalSize);
rts.attachments = rts.attachments || [];
if (StringRatchet.trimToNull(rts.txtMessage)) {
const txtAttach = {
filename: 'original-txt-body.txt',
contentType: 'text/plain',
base64Data: Base64Ratchet.generateBase64VersionOfString(rts.txtMessage),
};
rts.attachments.push(txtAttach);
}
if (StringRatchet.trimToNull(rts.htmlMessage)) {
const htmlAttach = {
filename: 'original-html-body.html',
contentType: 'text/html',
base64Data: Base64Ratchet.generateBase64VersionOfString(rts.htmlMessage),
};
rts.attachments.push(htmlAttach);
}
rts.htmlMessage = null;
rts.txtMessage = 'The message was too large and was converted to attachment(s). Please see attached files for content';
}
}
}
applyLimitsToAttachmentSizesIfAnyInPlace(rts) {
if (this.config.maxAttachmentSizeInBase64Bytes) {
const filtered = [];
if (rts.attachments) {
rts.attachments.forEach((a) => {
if (a.base64Data && a.base64Data.length < this.config.maxAttachmentSizeInBase64Bytes) {
filtered.push(a);
}
else {
Logger.warn('Removing too-large attachment : %s : %s : %d', a.filename, a.contentType, a.base64Data.length);
filtered.push({
filename: 'attachment-removed-notice-' + StringRatchet.createRandomHexString(4) + '.txt',
contentType: 'text/plain',
base64Data: Base64Ratchet.generateBase64VersionOfString('Attachment ' +
a.filename +
' of type ' +
a.contentType +
' was removed since it was ' +
a.base64Data.length +
' bytes but max allowed is ' +
this.config.maxAttachmentSizeInBase64Bytes),
});
}
});
}
rts.attachments = filtered;
}
}
async sendEmail(inRts) {
RequireRatchet.notNullOrUndefined(inRts, 'RTS must be defined');
RequireRatchet.notNullOrUndefined(inRts.destinationAddresses, 'Destination addresses must be defined');
let rval = null;
const resolved = await this.resolveReadyToSendEmail(inRts);
try {
const raw = await this.config.provider.sendEmail(resolved);
const archiveResult = await this.archiveEmailIfConfigured(resolved, raw);
rval = {
request: inRts,
resolved: resolved,
success: true,
rawResult: raw,
error: null,
meta: {},
archiveResults: archiveResult,
};
}
catch (err) {
rval = {
request: inRts,
resolved: resolved,
success: false,
rawResult: null,
error: ErrorRatchet.safeStringifyErr(err),
meta: {},
archiveResults: null,
};
}
return rval;
}
async resolveReadyToSendEmail(inRts) {
RequireRatchet.notNullOrUndefined(inRts, 'RTS must be defined');
RequireRatchet.notNullOrUndefined(inRts.destinationAddresses, 'Destination addresses must be defined');
let toAddresses = this.filterEmailsToValid(inRts.destinationAddresses);
const autoBcc = inRts.doNotAutoBcc ? [] : this.config.autoBccAddresses || [];
const bccAddresses = (inRts.bccAddresses || []).concat(autoBcc);
if (toAddresses.length === 0 && bccAddresses.length > 0) {
Logger.debug('Destination emails filtered to none but BCC defined, copying BCC');
toAddresses = bccAddresses;
}
const rts = Object.assign({}, inRts);
rts.srcDestinationAddresses = inRts.destinationAddresses;
rts.srcBccAddresses = inRts.bccAddresses;
rts.destinationAddresses = toAddresses;
rts.bccAddresses = bccAddresses;
this.applyLimitsToBodySizesIfAnyInPlace(rts);
this.applyLimitsToAttachmentSizesIfAnyInPlace(rts);
if (rts.destinationAddresses.length === 0) {
Logger.info('After cleaning email lists, no destination addresses left - not sending email');
}
rts.fromAddress = rts.fromAddress || this.config.defaultSendingAddress;
return rts;
}
}
//# sourceMappingURL=mailer.js.map