Browse Source

I think it works now?

master
John Shaver 2 months ago
parent
commit
62bb829ff7
7 changed files with 255 additions and 41 deletions
  1. 1
    0
      .gitignore
  2. 13
    0
      Dockerfile
  3. 46
    37
      index.js
  4. 164
    0
      package-lock.json
  5. 4
    4
      templater.js
  6. 11
    0
      templates/index.js
  7. 16
    0
      testing/testTemplate.js

+ 1
- 0
.gitignore View File

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

+ 13
- 0
Dockerfile View File

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

+ 46
- 37
index.js View File

@@ -3,58 +3,67 @@ let fs = require('fs');
3 3
 let bodyParser = require('body-parser');
4 4
 let outbound;
5 5
 
6
-let getTemplates = require('./templater');
6
+let getTemplates = require('./templates');
7 7
 let errorSender = require('./errorSender');
8 8
 exports.register = function() {
9 9
   outbound = this.haraka_require('./outbound');
10
-  let plugin = this;
11
-  this.register_hook('hook_init_http', function(next, server) {
10
+  this.register_hook('init_http', 'initExpress');
11
+}
12
+
13
+exports.initExpress = function(next, server) {
12 14
     server.http.app.use('/webSend', setupRoutes(server.http.express.Router()));
13 15
     server.http.app.get('/test', (req, res) => res.send("HELLO!"));
14
-    plugin.loginfo(server.http.app._router.stack);
15
-    next();
16
-  });
17
-}
16
+  next();
17
+};
18 18
 
19 19
 function setupRoutes(app) {
20 20
   app.use(bodyParser.json());
21 21
   app.use(errorSender);
22 22
 
23 23
   app.post('/template', function(req, res) {
24
-    if(!req.body) {
25
-      return res.sendError(400, "No body provided.");
26
-    }
27
-
28
-    let {to, from, template, headers} = req.body;
29
-    if(!template) {
30
-      return res.sendError(400, "No template name provided.");
31
-    }
32
-    return getTemplates.then(function(templates) {
33
-      let emailText = `From: ${from}\nTo: ${to}`;
34
-      if(headers) {
35
-        headers.forEach(function(header) {
36
-          emailText += `\n${header}`;
37
-        });
38
-      }
39
-      try {
40
-        let [subject, body] = `\n\n${templates[template](req.body)}\n`;
41
-        emailText += `\nSubject: ${subject}\n\n${body}`;
42
-      } catch (err) {
43
-        console.error("Error building email from template: ", err);
44
-        res.sendError(err.httpStatus || 400, err.userMessage || "Error parsing template");
24
+    try {
25
+      if(!req.body) {
26
+        return res.sendError(400, "No body provided.");
45 27
       }
46 28
 
47
-      outbound.send_email(from, to, emailText, function(code, message) {
48
-        console.log(`Queue mail result code: ${code} msg: ${msg}`);
49
-        res.type("json").send(JSON.stringigy({
50
-          code,
51
-          message
52
-        }));
29
+      let {to, from, template, headers} = req.body;
30
+      if(!template) {
31
+        console.error("Template not found in: ", req.body);
32
+        return res.sendError(400, "No template name provided.");
33
+      }
34
+      return getTemplates().then(function(templates) {
35
+        if(!templates[template]) {
36
+          return res.sendError(400, `Template not found in ${JSON.stringify(templates)}`);
37
+        }
38
+        let emailText = `From: ${from}\nTo: ${to}`;
39
+        if(headers) {
40
+          headers.forEach(function(header) {
41
+            emailText += `\n${header}`;
42
+          });
43
+        }
44
+        try {
45
+          let {subject, message} = templates[template](req.body);
46
+          emailText += `\nSubject: ${subject}\n\n${message}`;
47
+        } catch (err) {
48
+          console.error("Error building email from template: ", err);
49
+          res.sendError(err.httpStatus || 400, err.userMessage || "Error parsing template");
50
+        }
51
+        outbound.send_email(from, to, emailText, function(code, message) {
52
+          console.log(`Queue mail result code: ${code} msg: ${message}`);
53
+          res.type("json").send(JSON.stringify({
54
+            code,
55
+            message
56
+          }));
57
+        });
58
+      }).catch(function(err) {
59
+        console.error("Error loading templates:", err);
60
+        res.sendError(500, "Server Error");
61
+        throw(e);
53 62
       });
54
-    }).catch(function(err) {
55
-      console.error("Error loading templates:", err);
63
+    } catch(e) {
56 64
       res.sendError(500, "Server Error");
57
-    });
65
+      throw(e);
66
+    }
58 67
   });
59 68
     
60 69
   return app;

+ 164
- 0
package-lock.json View File

@@ -0,0 +1,164 @@
1
+{
2
+  "name": "haraka-plugin-webmailer",
3
+  "version": "1.0.0",
4
+  "lockfileVersion": 1,
5
+  "requires": true,
6
+  "dependencies": {
7
+    "body-parser": {
8
+      "version": "1.19.0",
9
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
10
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
11
+      "requires": {
12
+        "bytes": "3.1.0",
13
+        "content-type": "~1.0.4",
14
+        "debug": "2.6.9",
15
+        "depd": "~1.1.2",
16
+        "http-errors": "1.7.2",
17
+        "iconv-lite": "0.4.24",
18
+        "on-finished": "~2.3.0",
19
+        "qs": "6.7.0",
20
+        "raw-body": "2.4.0",
21
+        "type-is": "~1.6.17"
22
+      }
23
+    },
24
+    "bytes": {
25
+      "version": "3.1.0",
26
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
27
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
28
+    },
29
+    "content-type": {
30
+      "version": "1.0.4",
31
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
32
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
33
+    },
34
+    "debug": {
35
+      "version": "2.6.9",
36
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
37
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
38
+      "requires": {
39
+        "ms": "2.0.0"
40
+      }
41
+    },
42
+    "depd": {
43
+      "version": "1.1.2",
44
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
45
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
46
+    },
47
+    "ee-first": {
48
+      "version": "1.1.1",
49
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
50
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
51
+    },
52
+    "http-errors": {
53
+      "version": "1.7.2",
54
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
55
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
56
+      "requires": {
57
+        "depd": "~1.1.2",
58
+        "inherits": "2.0.3",
59
+        "setprototypeof": "1.1.1",
60
+        "statuses": ">= 1.5.0 < 2",
61
+        "toidentifier": "1.0.0"
62
+      }
63
+    },
64
+    "iconv-lite": {
65
+      "version": "0.4.24",
66
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
67
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
68
+      "requires": {
69
+        "safer-buffer": ">= 2.1.2 < 3"
70
+      }
71
+    },
72
+    "inherits": {
73
+      "version": "2.0.3",
74
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
75
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
76
+    },
77
+    "lodash.escape": {
78
+      "version": "4.0.1",
79
+      "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
80
+      "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg="
81
+    },
82
+    "media-typer": {
83
+      "version": "0.3.0",
84
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
85
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
86
+    },
87
+    "mime-db": {
88
+      "version": "1.40.0",
89
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
90
+      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
91
+    },
92
+    "mime-types": {
93
+      "version": "2.1.24",
94
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
95
+      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
96
+      "requires": {
97
+        "mime-db": "1.40.0"
98
+      }
99
+    },
100
+    "ms": {
101
+      "version": "2.0.0",
102
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
103
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
104
+    },
105
+    "on-finished": {
106
+      "version": "2.3.0",
107
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
108
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
109
+      "requires": {
110
+        "ee-first": "1.1.1"
111
+      }
112
+    },
113
+    "qs": {
114
+      "version": "6.7.0",
115
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
116
+      "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
117
+    },
118
+    "raw-body": {
119
+      "version": "2.4.0",
120
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
121
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
122
+      "requires": {
123
+        "bytes": "3.1.0",
124
+        "http-errors": "1.7.2",
125
+        "iconv-lite": "0.4.24",
126
+        "unpipe": "1.0.0"
127
+      }
128
+    },
129
+    "safer-buffer": {
130
+      "version": "2.1.2",
131
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
132
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
133
+    },
134
+    "setprototypeof": {
135
+      "version": "1.1.1",
136
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
137
+      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
138
+    },
139
+    "statuses": {
140
+      "version": "1.5.0",
141
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
142
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
143
+    },
144
+    "toidentifier": {
145
+      "version": "1.0.0",
146
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
147
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
148
+    },
149
+    "type-is": {
150
+      "version": "1.6.18",
151
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
152
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
153
+      "requires": {
154
+        "media-typer": "0.3.0",
155
+        "mime-types": "~2.1.24"
156
+      }
157
+    },
158
+    "unpipe": {
159
+      "version": "1.0.0",
160
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
161
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
162
+    }
163
+  }
164
+}

+ 4
- 4
templater.js View File

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

+ 11
- 0
templates/index.js View File

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

+ 16
- 0
testing/testTemplate.js View File

@@ -0,0 +1,16 @@
1
+let templater = require('../templater');
2
+
3
+module.exports = function({params}) {
4
+  let message = templater`Hello ${params.name},
5
+
6
+I am writing to inform you that I am testing a templated email.  I have tested it ${params.times} times.
7
+
8
+${params.valediction},
9
+
10
+${params.senderName}
11
+`;
12
+
13
+  let subject = "New message from webmailer program!";
14
+  return {subject, message};
15
+}
16
+

Loading…
Cancel
Save