From 279a9ca946ec028e7003df4f3f78ce80f5e455b4 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Mon, 1 Mar 2021 17:40:45 +0100 Subject: [PATCH] Added basic mailer that can send pw reset mails --- src/Mailer.ts | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/Mailer.ts diff --git a/src/Mailer.ts b/src/Mailer.ts new file mode 100644 index 0000000..5bf3a65 --- /dev/null +++ b/src/Mailer.ts @@ -0,0 +1,96 @@ +import fs from "fs"; +import Handlebars from 'handlebars'; +import i18next from "i18next"; +import Backend from 'i18next-fs-backend'; +import nodemailer from 'nodemailer'; +import { MailOptions } from 'nodemailer/lib/json-transport'; +import Mail from 'nodemailer/lib/mailer'; +import path from 'path'; +import { config } from './config'; +import { MailServerConfigError } from './errors/MailErrors'; + + +/** + * This class is responsible for all things pdf creation. + * This uses the html templates from src/templates. + */ +export class Mailer { + private templateDir = path.join(__dirname, '/templates'); + private transport: Mail; + private static interpolations = { eventname: config.eventname } + + /** + * Main constructor. + * Initializes i18n(ext), Handlebars and puppeteer. + */ + constructor() { + this.init(); + } + + /** + * Main constructor. + * Initializes i18n(ext), Handlebars and puppeteer. + */ + public async init() { + await i18next + .use(Backend) + .init({ + fallbackLng: 'en', + lng: 'en', + backend: { + loadPath: path.join(__dirname, '/locales/{{lng}}.json') + } + }); + await Handlebars.registerHelper('__', + function (str) { + return i18next.t(str, Mailer.interpolations).toString(); + } + ); + this.transport = nodemailer.createTransport({ + host: config.mail_server, + port: config.mail_port, + auth: { + user: config.mail_user, + pass: config.mail_password + } + }); + + this.transport.verify(function (error, success) { + if (error) { + throw new MailServerConfigError(); + } + }); + } + + /** + * Function for sending a test mail from the test mail template. + * @param to_address The address the mail will be sent to. Should always get pulled from a user object. + * @param token The requested password reset token - will be combined with the app_url to generate a password reset link. + */ + public async sendResetMail(to_address: string, token: string, locale: string = "en") { + await i18next.changeLanguage(locale); + + const reset_link = `${config.app_url}/reset/${(Buffer.from(token)).toString("base64")}` + const template_html = Handlebars.compile(fs.readFileSync(__dirname + '/static/mail_templates/pw-reset.html', { encoding: 'utf8' })); + const template_txt = Handlebars.compile(fs.readFileSync(__dirname + '/static/mail_templates/pw-reset.html', { encoding: 'utf8' })); + const body_html = template_html({ recipient_mail: to_address, copyright_owner: config.copyright_owner, link_imprint: `${config.app_url}/imprint`, link_privacy: `${config.app_url}/privacy`, reset_link }); + const body_txt = template_txt({ recipient_mail: to_address, copyright_owner: config.copyright_owner, link_imprint: `${config.app_url}/imprint`, link_privacy: `${config.app_url}/privacy`, reset_link }); + + const mail: MailOptions = { + to: to_address, + subject: i18next.t("subject_reset", Mailer.interpolations).toString(), + text: body_txt, + html: body_html + }; + await this.sendMail(mail); + } + + /** + * Wrapper function for sending a mail via this object's transporter. + * @param mail MailOptions object containing the + */ + public async sendMail(mail: MailOptions) { + mail.from = config.mail_from; + await this.transport.sendMail(mail); + } +} \ No newline at end of file