I think it works now?

This commit is contained in:
John Shaver 2019-09-18 00:28:15 -07:00
parent 549d3a5a98
commit 62bb829ff7
7 changed files with 255 additions and 41 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
./node_modules

13
Dockerfile Normal file
View file

@ -0,0 +1,13 @@
FROM node:10.6-alpine
RUN mkdir /app
RUN chown node:node /app
WORKDIR /app
run apk add --no-cache python2 g++ make git curl
RUN yarn global add Haraka express
USER node
RUN haraka -i /app
RUN echo webmailer >> /app/config/plugins
RUN echo "listen=[::0]:8080" >> /app/config/http.ini
RUN echo "listen=[::0]:2525" >> /app/config/smtp.ini
COPY testing/testTemplate.js /app/plugins/webmailer/templates/testTemplate.js
CMD haraka -c /app

View file

@ -3,33 +3,38 @@ let fs = require('fs');
let bodyParser = require('body-parser'); let bodyParser = require('body-parser');
let outbound; let outbound;
let getTemplates = require('./templater'); let getTemplates = require('./templates');
let errorSender = require('./errorSender'); let errorSender = require('./errorSender');
exports.register = function() { exports.register = function() {
outbound = this.haraka_require('./outbound'); outbound = this.haraka_require('./outbound');
let plugin = this; this.register_hook('init_http', 'initExpress');
this.register_hook('hook_init_http', function(next, server) { }
exports.initExpress = function(next, server) {
server.http.app.use('/webSend', setupRoutes(server.http.express.Router())); server.http.app.use('/webSend', setupRoutes(server.http.express.Router()));
server.http.app.get('/test', (req, res) => res.send("HELLO!")); server.http.app.get('/test', (req, res) => res.send("HELLO!"));
plugin.loginfo(server.http.app._router.stack);
next(); next();
}); };
}
function setupRoutes(app) { function setupRoutes(app) {
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(errorSender); app.use(errorSender);
app.post('/template', function(req, res) { app.post('/template', function(req, res) {
try {
if(!req.body) { if(!req.body) {
return res.sendError(400, "No body provided."); return res.sendError(400, "No body provided.");
} }
let {to, from, template, headers} = req.body; let {to, from, template, headers} = req.body;
if(!template) { if(!template) {
console.error("Template not found in: ", req.body);
return res.sendError(400, "No template name provided."); return res.sendError(400, "No template name provided.");
} }
return getTemplates.then(function(templates) { return getTemplates().then(function(templates) {
if(!templates[template]) {
return res.sendError(400, `Template not found in ${JSON.stringify(templates)}`);
}
let emailText = `From: ${from}\nTo: ${to}`; let emailText = `From: ${from}\nTo: ${to}`;
if(headers) { if(headers) {
headers.forEach(function(header) { headers.forEach(function(header) {
@ -37,16 +42,15 @@ function setupRoutes(app) {
}); });
} }
try { try {
let [subject, body] = `\n\n${templates[template](req.body)}\n`; let {subject, message} = templates[template](req.body);
emailText += `\nSubject: ${subject}\n\n${body}`; emailText += `\nSubject: ${subject}\n\n${message}`;
} catch (err) { } catch (err) {
console.error("Error building email from template: ", err); console.error("Error building email from template: ", err);
res.sendError(err.httpStatus || 400, err.userMessage || "Error parsing template"); res.sendError(err.httpStatus || 400, err.userMessage || "Error parsing template");
} }
outbound.send_email(from, to, emailText, function(code, message) { outbound.send_email(from, to, emailText, function(code, message) {
console.log(`Queue mail result code: ${code} msg: ${msg}`); console.log(`Queue mail result code: ${code} msg: ${message}`);
res.type("json").send(JSON.stringigy({ res.type("json").send(JSON.stringify({
code, code,
message message
})); }));
@ -54,7 +58,12 @@ function setupRoutes(app) {
}).catch(function(err) { }).catch(function(err) {
console.error("Error loading templates:", err); console.error("Error loading templates:", err);
res.sendError(500, "Server Error"); res.sendError(500, "Server Error");
throw(e);
}); });
} catch(e) {
res.sendError(500, "Server Error");
throw(e);
}
}); });
return app; return app;

164
package-lock.json generated Normal file
View file

@ -0,0 +1,164 @@
{
"name": "haraka-plugin-webmailer",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
"requires": {
"bytes": "3.1.0",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"on-finished": "~2.3.0",
"qs": "6.7.0",
"raw-body": "2.4.0",
"type-is": "~1.6.17"
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
"integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"mime-db": {
"version": "1.40.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
},
"mime-types": {
"version": "2.1.24",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
"requires": {
"mime-db": "1.40.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"raw-body": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
}
}
}

View file

@ -2,10 +2,10 @@ let escape = require("lodash.escape");
module.exports = function(strings) { module.exports = function(strings) {
//first element is the strings, don't need it //first element is the strings, don't need it
let args = arguments.slice(1); let args = Array.prototype.slice.call(arguments,1);
//first element will be the initial value //first element will be the initial value
return strings.slice(1).reduce(function(result, string, i) { return strings.reduce(function(result, string, i) {
return result + escape(args[i]) + string; return result + escape(args[i-1]) + string;
}, strings[0]); });
}; };

11
templates/index.js Normal file
View file

@ -0,0 +1,11 @@
let fs = require('fs');
let templateFiles = fs.readdirSync(__dirname, "utf8").filter(
x => x[0] !== "." && x !== "index.js"
);
let templates = templateFiles.reduce((obj, file) => { obj[file.split(".")[0]] = require(`./${file}`); return obj;}, {});
module.exports = function() {
//I might want to make this asynchronous very soon
return Promise.resolve(templates);
};

16
testing/testTemplate.js Normal file
View file

@ -0,0 +1,16 @@
let templater = require('../templater');
module.exports = function({params}) {
let message = templater`Hello ${params.name},
I am writing to inform you that I am testing a templated email. I have tested it ${params.times} times.
${params.valediction},
${params.senderName}
`;
let subject = "New message from webmailer program!";
return {subject, message};
}