UNPKG

@perfood/couch-auth

Version:

Easy and secure authentication for CouchDB/Cloudant. Based on SuperLogin, updated and rewritten in Typescript.

95 lines (94 loc) 3.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Mailer = void 0; const nodemailer_1 = __importDefault(require("nodemailer")); const path_1 = require("path"); const template_utils_1 = require("./template-utils"); const util_1 = require("./util"); class Mailer { constructor(config) { this.config = config; if (config.testMode?.noEmail) { this.transporter = nodemailer_1.default.createTransport(require('nodemailer-stub-transport')()); } else { this.transporter = nodemailer_1.default.createTransport(config.mailer.transport ?? config.mailer.options); } } /** * Use the same nodemailer config that couch-auth uses to send out an email. * Internally, `req` (the sent request), `user` (the sl-user doc) and `data` * defined in the config are always available. * * @param templateId the entry under the `emails` property in the config * @param recepient the recepient's email address * @param data additional data directly passed to `nunjucks.render()`. Don't * add anything called `data` in here! */ async sendEmail(templateId, recepient, data) { // load the template and parse it const templateConfig = this.config.emailTemplates.templates[templateId]; if (!templateConfig) { return Promise.reject('No template entry for "' + templateId + '".'); } const templateDirectory = this.config.emailTemplates.folder ?? (0, path_1.join)(__dirname, './templates/email'); let templates; const templateData = { subject: templateConfig.subject, data: { ...this.config.emailTemplates.data, ...templateConfig.data }, ...data, templateId }; try { templates = (0, template_utils_1.parseCompositeTemplate)(templateDirectory, templateId, templateData); } catch (error) { templates = (0, template_utils_1.parseTemplatesDirectly)(templateDirectory, templateId, templateData); if (!templates.html && !templates.text) { return Promise.reject(`Could not parse ${templateId} in ${templateDirectory}. ` + error); } } // form the email let mailOptions = { from: this.config.mailer.fromEmail, to: recepient, subject: templateConfig.subject, ...templates }; if (this.config.mailer.messageConfig) { mailOptions = { ...this.config.mailer.messageConfig, ...mailOptions }; } if (this.config.testMode?.debugEmail) { console.log(mailOptions); } // send the message if (this.config.mailer.retryOnError) { return this.sendMailWithBackoff(mailOptions, 0); } else { return this.transporter.sendMail(mailOptions); } } async sendMailWithBackoff(mailOptions, attempt) { try { return this.transporter.sendMail(mailOptions); } catch (error) { attempt += 1; if (attempt > this.config.mailer.retryOnError.maxRetries) { throw error; } await (0, util_1.timeoutPromise)(1000 * this.config.mailer.retryOnError.initialBackoffSeconds * 2 ** attempt); return this.sendMailWithBackoff(mailOptions, attempt); } } } exports.Mailer = Mailer;