UNPKG

@bitblit/ratchet-common

Version:

Common tools for general use

174 lines 8.19 kB
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