From 2aeb733b2c812fd3d34f01e9bcc8a9d04edf0f84 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 17 Oct 2018 21:51:51 -0700 Subject: [PATCH] Added mail resend utility Signed-off-by: James Ketrenos --- util/resend.js | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 util/resend.js diff --git a/util/resend.js b/util/resend.js new file mode 100644 index 0000000..4b18025 --- /dev/null +++ b/util/resend.js @@ -0,0 +1,163 @@ +"use strict"; + +const config = require("config"), + crypto = require("crypto"), + hb = require("handlebars"); + +const basePath = "/" + config.get("basePath").replace(/^\/+/, "").replace(/\/+$/, "") + "/"; + +const req = { + hostname: "ketrenos.com", + protocol: "https", + data: { + basePath: (basePath == "//") ? "/" : basePath + } +}; + +const app = req.app = { + get: function(key) { + return req.data[key]; + }, + set: function(key, value) { + req.data[key] = value; + return value; + } +}; + +if (config.has("admin.mail") && + config.has("smtp.host") && + config.has("smtp.sender")) { + app.set("transporter", require("nodemailer").createTransport({ + host: config.get("smtp.host"), + pool: true, + port: config.has("smtp.port") ? config.get("smtp.port") : 25 + })); +} else { + console.log("SMTP disabled. To enable SMTP, configure admin.mail, smtp.host, and smtp.sender"); +} + +const templates = { + "html": [ + "

Hello {{username}},

", + "", + "

Welcome to ketrenos.com. You are almost done creating your account. ", + "Before you can access the system, you must verify your email address.

", + "", + "

To do so, simply access this link:

", + "

VERIFY {{mail}} ADDRESS

", + "", + "

Sincerely,

", + "

James

" + ].join("\n"), + "text": [ + "Hello {{username}},", + "", + "Welcome to ketrenos.com. You are almost done creating your account. ", + "Before you can access the system, you must verify your email address.", + "", + "To do so, simply access this link:", + "", + "{{url}}{{secret}}", + "", + "Sincerely,", + "James" + ].join("\n") +}; + +require("../server/db/users").then(function(db) { + const userDB = db; + let user = null; + + return userDB.sequelize.query("SELECT * FROM users WHERE id=:id", { + replacements: { + id: process.argv[2] + }, + type: userDB.Sequelize.QueryTypes.SELECT, + raw: true + }).then(function(results) { + if (results.length != 1) { + return ("User not found."); + } + + user = results[0]; + }).then(function() { + return userDB.sequelize.query("DELETE FROM authentications WHERE userId=:id", { + 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) { + const transporter = req.app.get("transporter"); + if (!transporter) { + console.log("Not sending VERIFY email; SMTP not configured."); + return; + } + + let data = { + username: user.displayName, + mail: user.mail, + secret: secret, + url: req.protocol + "://" + req.hostname + req.app.get("basePath") + }, envelope = { + to: data.mail, + from: config.get("smtp.sender"), + subject: "Request to ketrenos.com create account for '" + data.username + "'", + cc: "", + bcc: config.get("admin.mail"), + text: hb.compile(templates.text)(data), + html: hb.compile(templates.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 mail. Trying again in 100ms (" + attempts + " attempts remain): ", error); + setTimeout(send.bind(undefined, envelope), 100); + }); + } + + send(envelope); + }).then(function() { + process.exit(0); + }); + }).catch(function(error) { + console.log("Error creating account: ", error); + }); +}); +