You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.8 KiB
103 lines
2.8 KiB
3 years ago
|
// 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);
|
||
|
},
|
||
|
};
|