1
0
goodtimes/server/lib/mail.js
James Ketrenos 74f1f092ec Authentication working
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
2022-04-06 17:33:18 -07:00

251 lines
6.7 KiB
JavaScript

"use strict";
const config = require("config"),
crypto = require("crypto"),
hb = require("handlebars");
const createTransport = require('nodemailer').createTransport;
const transporter = createTransport({
host: 'ketrenos.com',
pool: true,
port: 25
});
const templates = {
"verify": {
"html": [
"<p>Hello {{firstName}},</p>",
"",
"<p>Welcome to <b>goodtimes.ketrenos.com</b>. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address {{email}}.</p>",
"",
"<p>To do so, simply access this link:</p>",
"<p><a href=\"{{url}}{{secret}}\">VERIFY ADDRESS</a></p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"Hello {{firstName}},",
"",
"Welcome to goodtimes.ketrenos.com. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address {{email}}.",
"",
"To do so, simply access this link:",
"",
"{{url}}{{secret}}",
"",
"Sincerely,",
"James"
].join("\n")
},
"verified": {
"html": [
"<p>The user {{email}} verified their address and is now active",
"on Goodtimes.</p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"The user {{email}} verified their address and is now active",
"on Goodtimes.",
"",
"Sincerely,",
"James"
].join("\n")
},
"password": {
"html": [
"<p>Hello {{firstName}},</p>",
"",
"<p>You changed your password on <b>goodtimes.ketrenos.com</b>.</p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"Hello {{firstName}},",
"",
"You changed your password on goodtimes.ketrenos.com.",
"",
"Sincerely,</p>",
"James"
].join("\n")
}
};
const sendVerifyMail = function(userDB, req, user) {
return userDB.sequelize.query("DELETE FROM authentications WHERE userId=:id AND type='account-setup'", {
replacements: {
id: user.id
}
}).then(function() {
return new Promise(function(resolve, reject) {
crypto.randomBytes(16, function(error, buffer) {
if (error) {
return reject(error);
}
return resolve(buffer.toString('hex'));
});
});
}).then(function(secret) {
return userDB.sequelize.query(
"INSERT INTO authentications " +
"(userId,issued,key,type) " +
"VALUES (:userId,CURRENT_TIMESTAMP,:key,'account-setup')", {
replacements: {
key: secret,
userId: user.id
}
}).then(function() {
return secret;
}).catch(function(error) {
console.log(error);
throw error;
});
}).then(function(secret) {
if (!transporter) {
console.log("Not sending VERIFY email; SMTP not configured.");
return;
}
let data = {
firstName: user.firstName,
email: user.email,
secret: secret,
url: req.protocol + "://" + req.hostname + req.app.get("basePath") +
"/user/verify-email/"
}, envelope = {
to: data.email,
from: config.get("smtp.sender"),
subject: "Request to goodtimes.ketrenos.com create account for '" + data.firstName + "'",
cc: "",
bcc: config.get("admin.mail"),
text: hb.compile(templates.verify.text)(data),
html: hb.compile(templates.verify.html)(data)
};
return new Promise(function (resolve, reject) {
let attempts = 10;
function send(envelope) {
/* Rate limit to ten per second */
transporter.sendMail(envelope, function (error, info) {
if (!error) {
console.log('Message sent: ' + info.response);
return resolve();
}
if (attempts == 0) {
console.log("Error sending email: ", error);
return reject(error);
}
attempts--;
console.log("Unable to send email. Trying again in 100ms (" + attempts + " attempts remain): ", error);
setTimeout(send.bind(undefined, envelope), 100);
});
}
send(envelope);
});
}).catch(function(error) {
console.log("Error creating account: ", error);
});
};
const sendPasswordChangedMail = function(userDB, req, user) {
if (!transporter) {
console.log("Not sending VERIFY email; SMTP not configured.");
return;
}
let data = {
firstName: user.firstName,
email: user.email,
url: req.protocol + "://" + req.hostname + req.app.get("basePath")
}, envelope = {
to: data.email,
from: config.get("smtp.sender"),
subject: "Password changed on goodtimes.ketrenos.com for '" + data.firstName + "'",
cc: "",
bcc: config.get("admin.mail"),
text: hb.compile(templates.password.text)(data),
html: hb.compile(templates.password.html)(data)
};
return new Promise(function (resolve, reject) {
let attempts = 10;
function send(envelope) {
/* Rate limit to ten per second */
transporter.sendMail(envelope, function (error, info) {
if (!error) {
console.log('Message sent: ' + info.response);
return resolve();
}
if (attempts == 0) {
console.log("Error sending email: ", error);
return reject(error);
}
attempts--;
console.log("Unable to send email. Trying again in 100ms (" + attempts + " attempts remain): ", error);
setTimeout(send.bind(undefined, envelope), 100);
});
}
send(envelope);
});
};
const sendVerifiedMail = function (userDB, req, user) {
if (!transporter) {
console.log("Not sending VERIFIED email; SMTP not configured.");
return;
}
const envelope = {
to: config.get("admin.mail"),
from: config.get("smtp.sender"),
subject: "VERIFIED: Account'" + user.email + "'",
cc: "",
bcc: "",
text: hb.compile(templates.verified.text)(user),
html: hb.compile(templates.verified.html)(user)
};
return new Promise(function (resolve, reject) {
let attempts = 10;
function send(envelope) {
/* Rate limit to ten per second */
transporter.sendMail(envelope, function (error, info) {
if (!error) {
console.log('Message sent: ' + info.response);
return resolve();
}
if (attempts == 0) {
console.log("Error sending email: ", error)
return reject(error);
}
attempts--;
console.log("Unable to send mail. Trying again in 100ms (" +
attempts + " attempts remain): ", error);
setTimeout(send.bind(undefined, envelope), 100);
});
}
send(envelope);
});
};
module.exports = {
sendVerifyMail,
sendVerifiedMail,
sendPasswordChangedMail
}