UNPKG

adba

Version:
173 lines (172 loc) 7.11 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import nodemailer from "nodemailer"; import Handlebars from "handlebars"; import { splitAndFlat, t, flatten } from "dbl-utils"; import moment from "moment"; const config = { EmailProcessModel: null, SystemModel: null, colorPrimary: '#ffffff', attemptsTotal: 3, maxScheduling: 10, maxPriorScheduling: 20, priorOrder: 10, runningPriorSchedule: false, runningSchedule: false, priorDelay: 1000 * 60, delay: 1000 * 60 * 60, templates: {} }; export function setEmailProcessModel(EmailProcessModel) { config.EmailProcessModel = EmailProcessModel; } export function setSystemModel(SystemModel) { config.SystemModel = SystemModel; } export function colorPrimary(color) { config.colorPrimary = color; } export function setConfig(cfg) { Object.assign(config, cfg); } const buildTemplate = (templateName, data) => { const text = Object.entries(flatten(data)).map(([key, value]) => `${t(key, 'emailKeyTemplate>' + templateName)}: ${t(value, 'emailValueTemplate>' + templateName)}`).join('\n'); let html = text; let subject = data.subject; if (config.templates[templateName]) { const subjectTemplater = Handlebars.compile(config.templates[templateName].subject); subject = subjectTemplater(data); const htmlTemplater = Handlebars.compile(config.templates[templateName].template); html = htmlTemplater(data); } return { subject, html, text }; }; const sendEmail = (to_1, template_1, data_1, ...args_1) => __awaiter(void 0, [to_1, template_1, data_1, ...args_1], void 0, function* (to, template, data, order = 10) { if (!config.EmailProcessModel) return false; const emailElements = buildTemplate(template, data); const emailProcess = config.EmailProcessModel.fromJson(Object.assign(Object.assign({ emailAddress: splitAndFlat([to]) }, emailElements), { order, active: true })); try { const response = yield config.EmailProcessModel.query().insert(emailProcess); console.log('email scheduled:', response); return true; } catch (err) { console.error('error scheduling email:'); console.error(err); return false; } }); export const processEmailList = (transporter, emailList) => __awaiter(void 0, void 0, void 0, function* () { if (!config.EmailProcessModel) return false; for (const emailDoc of emailList) { if (['archived', 'completed'].includes(emailDoc.status)) continue; try { yield transporter.sendMail({ from: emailDoc.from, to: emailDoc.emailAddress, html: emailDoc.html, text: emailDoc.text, attachments: emailDoc.attachments, cc: emailDoc.cc, bcc: emailDoc.bcc, subject: emailDoc.subject, }); console.log(`Email sent to ${emailDoc.emailAddress}`); emailDoc.status = 'completed'; emailDoc.lastAttempt = moment().format('YYYY-mm-dd HH:mm:ss'); emailDoc.active = false; } catch (error) { console.error('Failed to send email:', error); emailDoc.attempts += 1; emailDoc.lastAttempt = moment().format('YYYY-mm-dd HH:mm:ss'); emailDoc.status = emailDoc.attempts > config.attemptsTotal ? 'archived' : 'failed'; } yield config.EmailProcessModel.query().update(emailDoc).catch(e => console.error(e)); } }); export const enqueueEmailList = (transportConf) => __awaiter(void 0, void 0, void 0, function* () { if (!config.SystemModel) return false; if (!config.EmailProcessModel) return false; let t9r; try { //configuration of oauth2.0 /* const sysTokens: ISystemConfigModel | null = await config.SystemModel.query().findOne({ name: 'emailTokens' }) as ISystemConfigModel | null; if (!sysTokens || !sysTokens.value) throw new Error('Email OAuth2 not configured'); const refreshToken = sysTokens.value; { service: process.env.EMAIL_SERVICE, auth: { type: 'OAuth2', user: process.env.EMAIL_USER, clientId: process.env.EMAIL_CLIENT_ID, clientSecret: process.env.EMAIL_CLIENT_SECRET, refreshToken } } */ t9r = yield new Promise((resolve, reject) => { const transporter = nodemailer.createTransport(transportConf); transporter.verify((error, success) => { if (error) { console.error('Error connecting to the SMTP server:', error); reject(error); } else { console.log('Server is ready to send emails:', success); resolve(transporter); } }); }); } catch (error) { console.error('[ERROR]', error); return false; } console.log('enqueue emails'); setInterval(() => __awaiter(void 0, void 0, void 0, function* () { config.runningPriorSchedule = true; const emailList = yield config.EmailProcessModel.query() .where('order', '<=', config.priorOrder) .whereNotIn('status', ['completed', 'expired', 'archived']) .where('attempts', '<=', config.attemptsTotal) .orderBy('order', "ASC") .limit(config.maxPriorScheduling); console.log('emailList prior:', emailList.length); yield processEmailList(t9r, emailList); config.runningPriorSchedule = false; }), config.priorDelay); setInterval(() => __awaiter(void 0, void 0, void 0, function* () { if (config.runningPriorSchedule) return; config.runningSchedule = true; const emailList = yield config.EmailProcessModel.query() .where('order', '>', config.priorOrder) .whereNotIn('status', ['completed', 'expired', 'archived']) .where('attempts', '<=', config.attemptsTotal) .orderBy('order', "ASC") .limit(config.maxScheduling); console.log('emailList standard:', emailList.length); yield processEmailList(t9r, emailList); config.runningSchedule = false; }), config.delay); return true; }); export default sendEmail;