var XMLParser = require("fast-xml-parser").XMLParser; var http = require("http"); var https = require("https"); var fs = require("fs"); var MongoClient = require('mongodb').MongoClient; var nodemailer = require("nodemailer"); var transporter = nodemailer.createTransport({ host: "localhost", port: 25, secure: false, // Use `true` for port 465, `false` for all other ports tls: { rejectUnauthorized: false }, pool: true }); var fromEmail = "root@localhost"; var mongoURL = "mongodb://localhost/newsletter"; var dbname = "newsletter"; function antiXSS(string) { return string.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); } function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } function connectMongo(callback) { MongoClient.connect(mongoURL, function (err, db) { if (err) throw err; var dbo = db.db(dbname); dbo.createCollection("emails", function (err, dbres) { dbo.createCollection("posts", function (err, dbres) { callback(dbo); }); }); }); } function formatTemplate(templateName, templateData, callback) { fs.readFile(__dirname + "/" + templateName + ".template", function (err, data) { if (err) throw err; var tD = data.toString(); Object.keys(templateData).forEach(function (key) { tD = tD.replace(new RegExp("\\{\\{" + escapeRegExp(key) + "\\}\\}", "g"), templateData[key]); }); callback(tD); }); } https.get("https://blog.svrjs.org/atom.xml", function (res) { var data = ""; res.on("data", function (chunk) { data += chunk.toString(); }); res.on("end", function () { var parser = new XMLParser(); var parsedData = parser.parse(data); var entries = parsedData.feed.entry; connectMongo(function (db) { db.collection("emails").find({}).toArray(function (err, emails) { if (err) throw err; var queue = []; var ent = JSON.parse(JSON.stringify(entries)).reverse(); function getEntriesId(_id) { if (!_id) _id = 0; if (_id >= ent.length) { process.exit(0); return; } db.collection("posts").find({ id: ent[_id].id }).toArray(function (err, result) { if (err) throw err; if (result.length == 0) { db.collection("posts").insertOne({ id: ent[_id].id }, function (err, dbres) { if (err) throw err; var _qid = _id; function sendEmail(_id) { if (!_id) _id = 0; if (_id >= emails.length) { getEntriesId(_id + 1); return; } var qim = ent[_qid].id.match(/https:\/\/blog\.svrjs\.org\/[0-9]+\/[0-9]+\/[0-9]+\/([^\/]+)/); var imageURL = "https://blog.svrjs.org/images/covers/" + (qim ? qim[1] : "missing") + ".png"; formatTemplate("index.html", { "title": antiXSS(ent[_qid].title), "summary": ent[_qid].summary.replace(/ (src|href)="\/(?!\/)/g," $1=\"https://blog.svrjs.org/"), "image": antiXSS(imageURL), "link": antiXSS(ent[_qid].id), "unsubscribe": antiXSS("https://newsletter.svrjs.org/unsubscribe.svr?id=" + encodeURIComponent(emails[_id].unsubscribeId)) }, function (data) { transporter.sendMail({ from: fromEmail, to: emails[_id].email, subject: ent[_qid].title + " - SVR.JS Blog Newsletter", text: 'This message requires HTML to be viewed', html: data }, function (err, info) { if (err) throw err; sendEmail(_id + 1); }); }); } sendEmail(); }); } else { getEntriesId(_id + 1); } }); } getEntriesId(); }); }); }); });