// email.js // Copyright (C) 2021 Digital Telepresence, LLC // License: Apache-2.0 'use strict'; const path = require('path'); const pug = require('pug'); const mailgun = require('mailgun-js'); const mongoose = require('mongoose'); const EmailBlacklist = mongoose.model('EmailBlacklist'); const disposableEmailDomains = require('disposable-email-provider-domains'); const emailValidator = require('email-validator'); const emailDomainCheck = require('email-domain-check'); const { SiteService } = require('../../lib/site-lib'); class EmailService extends SiteService { constructor (dtp) { super(dtp, module.exports); } async start ( ) { await super.start(); if (process.env.DTP_MAILGUN_ENABLED === 'enabled') { this.mg = mailgun({ apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN, }); } this.templates = { html: { welcome: pug.compileFile(path.join(this.dtp.config.root, 'app', 'templates', 'html', 'welcome.pug')), }, text: { welcome: pug.compileFile(path.join(this.dtp.config.root, 'app', 'templates', 'text', 'welcome.pug')), }, }; } async send (message) { return new Promise((resolve, reject) => { this.log.info('sending email', { to: message.to, subject: message.subject }); this.mg.messages().send(message, async (error, body) => { if (error) { return reject(error); } resolve(body); }); }); } async checkEmailAddress (emailAddress) { this.log.debug('validating email address', { emailAddress }); if (!emailValidator.validate(emailAddress)) { throw new Error('Email address is invalid'); } const domainCheck = await emailDomainCheck(emailAddress); this.log.debug('email domain check', { domainCheck }); if (!domainCheck) { throw new Error('Email address is invalid'); } await this.isEmailBlacklisted(emailAddress); } async isEmailBlacklisted (emailAddress) { emailAddress = emailAddress.toLowerCase().trim(); const domain = emailAddress.split('@')[1]; this.log.debug('checking email domain for blacklist', { domain }); if (disposableEmailDomains.domains.includes(domain)) { this.log.alert('blacklisted email domain blocked', { emailAddress, domain }); throw new Error('Invalid email address'); } const blacklistRecord = await EmailBlacklist.findOne({ email: emailAddress }); if (blacklistRecord) { throw new Error('Email address has requested to not receive emails', { blacklistRecord }); } return false; } async renderTemplate (templateId, templateType, message) { return this.templates[templateType][templateId](message); } } module.exports = { slug: 'email', name: 'email', create: (dtp) => { return new EmailService(dtp); }, };