I think it works now?
This commit is contained in:
parent
549d3a5a98
commit
62bb829ff7
7 changed files with 255 additions and 41 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
./node_modules
|
13
Dockerfile
Normal file
13
Dockerfile
Normal 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
|
33
index.js
33
index.js
|
@ -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
164
package-lock.json
generated
Normal 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="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
11
templates/index.js
Normal 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
16
testing/testTemplate.js
Normal 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};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue