Advertisement
Guest User

Untitled

a guest
Mar 16th, 2017
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.88 KB | None | 0 0
  1. #!/usr/bin/env node
  2. /**
  3. * Capture and react to alerts generated by Q-See cameras over SMTP
  4. *
  5. * Author: Dave Eddy <dave@daveeddy.com>
  6. * Date: March 11, 2017
  7. * License: MIT
  8. */
  9.  
  10. var f = require('util').format;
  11. var fs = require('fs');
  12. var path = require('path');
  13.  
  14. var assert = require('assert-plus');
  15. var mkdirp = require('mkdirp');
  16.  
  17. var MailParser = require('mailparser').MailParser;
  18. var SMTPServer = require('smtp-server').SMTPServer;
  19.  
  20. var ATTACHMENT_RE = /^[a-zA-Z0-9_-]+\.(jpg|png)$/;
  21. var ATTACHMENT_DIR = path.join(__dirname, 'data');
  22. var USERNAME = 'foo@example.com';
  23. var PASSWORD = 'bar';
  24. var HOST = '0.0.0.0';
  25. var PORT = 10465;
  26.  
  27. var connections = {};
  28.  
  29. var server = new SMTPServer({
  30. secure: false,
  31. disabledCommands: ['STARTTLS'],
  32. authOptional: true,
  33. onAuth: onAuth,
  34. onConnect: onConnect,
  35. onData: onData,
  36. onClose: onClose
  37. });
  38. server.listen(PORT, HOST, onconnected);
  39.  
  40. function log() {
  41. var s = f.apply(null, arguments);
  42. console.log('[%s] %s', new Date().toISOString(), s);
  43. }
  44.  
  45. function onconnected() {
  46. log('Listening on smtp://%s:%d', HOST, PORT);
  47. }
  48.  
  49. function onConnect(session, cb) {
  50. log('[%s] Connection from %s', session.id, session.remoteAddress);
  51. connections[session.id] = session;
  52. cb();
  53. }
  54.  
  55. function onAuth(auth, session, cb) {
  56. var msg;
  57.  
  58. // find the session
  59. if (!connections[session.id]) {
  60. msg = f('[%s] Unexpected auth from user "%s" (%s)',
  61. session.id, auth.username, session.remoteAddress);
  62. log(msg);
  63. cb(new Error(msg));
  64. return;
  65. }
  66.  
  67. // check username and password
  68. if (auth.username !== USERNAME || auth.password !== PASSWORD) {
  69. msg = f('[%s] Auth failure for user "%s" (%s)',
  70. session.id, auth.username, session.remoteAddress);
  71. log(msg);
  72. cb(new Error(msg));
  73. return;
  74. }
  75.  
  76. log('[%s] Successfully authed user "%s" (%s)',
  77. session.id, auth.username, session.remoteAddress);
  78. cb(null, {user: auth.username});
  79. }
  80.  
  81. function onData(stream, session, cb) {
  82. // find the session
  83. if (!connections[session.id]) {
  84. msg = f('[%s] Unexpected auth from user "%s" (%s)',
  85. session.id, auth.username, session.remoteAddress);
  86. log(msg);
  87. cb(new Error(msg));
  88. return;
  89. }
  90.  
  91. var parser = new MailParser();
  92. var dname = path.join(ATTACHMENT_DIR, Date.now().toString());
  93.  
  94. // callback object
  95. var ret = {
  96. attachments: {
  97. dir: dname,
  98. files: []
  99. }
  100. };
  101.  
  102. parser.on('headers', function (headers) {
  103. ret.subject = headers.get('subject');
  104. ret.date = headers.get('date');
  105. ret.from = headers.get('from').text;
  106. ret.to = headers.get('to').text;
  107. });
  108.  
  109. parser.on('data', function (data) {
  110. switch (data.type) {
  111. case 'attachment':
  112. if (!ATTACHMENT_RE.test(data.filename)) {
  113. log('filename failed regex match: "%s"',
  114. data.filename);
  115. data.release();
  116. return;
  117. }
  118.  
  119. mkdirp.sync(dname);
  120. var fname = path.join(dname, data.filename);
  121.  
  122. var ws = fs.createWriteStream(fname);
  123. data.content.pipe(ws);
  124. ws.on('close', function () {
  125. ret.attachments.files.push(fname);
  126. data.release();
  127. });
  128. break;
  129. case 'text':
  130. ret.rawBody = data.text;
  131.  
  132. /*
  133. * attempt to parse the email body, exmaple output:
  134. *
  135. * Device ID: 0, Device Name: EDVR
  136. *
  137. *
  138. * Channel ID: 1, Camera Name:CAMERA01
  139. * Alarm Type:Motion Alarm, Time:2017-3-11 12:59:33
  140. */
  141. ret.data = {};
  142. data.text.split('\n').forEach(function (line) {
  143. if (line.trim() === '') {
  144. return;
  145. }
  146. line.split(', ').forEach(function (s) {
  147. var match = s.match(/([^:]+):(.*)$/);
  148. if (!match) {
  149. return;
  150. }
  151.  
  152. var key = match[1];
  153. var value = match[2].trim();
  154. ret.data[key] = value;
  155. });
  156. });
  157. break;
  158. default:
  159. log('unexpected data.type "%s"', data.type);
  160. break;
  161. }
  162. });
  163.  
  164. parser.on('end', function () {
  165. if (ret.attachments.files.length === 0) {
  166. delete ret.attachments;
  167. }
  168. console.log(JSON.stringify(ret, null, 2));
  169. cb();
  170. });
  171.  
  172. stream.pipe(parser);
  173. }
  174.  
  175. function onClose(session) {
  176. // find the session
  177. if (!connections[session.id]) {
  178. msg = f('[%s] Unexpected close (%s)',
  179. session.id, session.remoteAddress);
  180. log(msg);
  181. cb(new Error(msg));
  182. return;
  183. }
  184.  
  185. log('[%s] Connection closed', session.id);
  186. delete connections[session];
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement