Haraka 2.8.28 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/.eslintrc.yaml +2 -10
  2. package/Changes.md +84 -2
  3. package/Dockerfile +1 -1
  4. package/Plugins.md +9 -4
  5. package/README.md +2 -6
  6. package/bin/haraka +5 -4
  7. package/config/outbound.ini +0 -7
  8. package/config/plugins +1 -1
  9. package/config/smtp.ini +1 -1
  10. package/config/smtp_forward.ini +2 -8
  11. package/config/smtp_proxy.ini +0 -6
  12. package/connection.js +178 -204
  13. package/coverage/lcov.info +13863 -0
  14. package/coverage/tmp/coverage-42958-1658373250585-0.json +1 -0
  15. package/coverage/tmp/coverage-42961-1658373250529-0.json +1 -0
  16. package/dkim.js +66 -73
  17. package/docs/Body.md +1 -22
  18. package/docs/CoreConfig.md +2 -2
  19. package/docs/Header.md +1 -47
  20. package/docs/Outbound.md +8 -36
  21. package/endpoint.js +1 -1
  22. package/haraka.js +1 -1
  23. package/host_pool.js +8 -12
  24. package/logger.js +25 -32
  25. package/outbound/client_pool.js +11 -153
  26. package/outbound/config.js +5 -11
  27. package/outbound/hmail.js +109 -143
  28. package/outbound/index.js +13 -25
  29. package/outbound/mx_lookup.js +10 -7
  30. package/outbound/queue.js +8 -12
  31. package/outbound/timer_queue.js +2 -4
  32. package/outbound/tls.js +17 -18
  33. package/outbound/todo.js +1 -0
  34. package/package.json +57 -55
  35. package/plugins/auth/auth_base.js +39 -63
  36. package/plugins/auth/auth_bridge.js +3 -4
  37. package/plugins/auth/auth_proxy.js +16 -16
  38. package/plugins/auth/auth_vpopmaild.js +30 -37
  39. package/plugins/auth/flat_file.js +9 -13
  40. package/plugins/avg.js +9 -11
  41. package/plugins/backscatterer.js +1 -1
  42. package/plugins/block_me.js +2 -6
  43. package/plugins/bounce.js +106 -124
  44. package/plugins/clamd.js +59 -63
  45. package/plugins/data.signatures.js +6 -6
  46. package/plugins/data.uribl.js +1 -415
  47. package/plugins/delay_deny.js +19 -20
  48. package/plugins/dkim_sign.js +56 -62
  49. package/plugins/dkim_verify.js +9 -8
  50. package/plugins/dns_list_base.js +43 -42
  51. package/plugins/dnsbl.js +41 -46
  52. package/plugins/dnswl.js +23 -26
  53. package/plugins/early_talker.js +24 -28
  54. package/plugins/esets.js +8 -11
  55. package/plugins/greylist.js +161 -190
  56. package/plugins/helo.checks.js +175 -197
  57. package/plugins/mail_from.is_resolvable.js +38 -38
  58. package/plugins/messagesniffer.js +33 -40
  59. package/plugins/prevent_credential_leaks.js +7 -5
  60. package/plugins/process_title.js +16 -17
  61. package/plugins/queue/deliver.js +2 -2
  62. package/plugins/queue/lmtp.js +5 -6
  63. package/plugins/queue/qmail-queue.js +11 -13
  64. package/plugins/queue/quarantine.js +25 -34
  65. package/plugins/queue/rabbitmq.js +3 -2
  66. package/plugins/queue/rabbitmq_amqplib.js +9 -9
  67. package/plugins/queue/smtp_bridge.js +5 -4
  68. package/plugins/queue/smtp_forward.js +81 -89
  69. package/plugins/queue/smtp_proxy.js +21 -22
  70. package/plugins/queue/test.js +2 -1
  71. package/plugins/rcpt_to.host_list_base.js +20 -30
  72. package/plugins/rcpt_to.in_host_list.js +12 -14
  73. package/plugins/rcpt_to.max_count.js +7 -5
  74. package/plugins/record_envelope_addresses.js +4 -6
  75. package/plugins/relay.js +64 -74
  76. package/plugins/reseed_rng.js +1 -2
  77. package/plugins/spamassassin.js +56 -68
  78. package/plugins/status.js +2 -3
  79. package/plugins/tarpit.js +8 -11
  80. package/plugins/tls.js +14 -17
  81. package/plugins/toobusy.js +6 -8
  82. package/plugins/xclient.js +14 -25
  83. package/plugins.js +24 -29
  84. package/rfc1869.js +2 -2
  85. package/server.js +3 -13
  86. package/smtp_client.js +138 -215
  87. package/tests/config/smtp_forward.ini +0 -6
  88. package/tests/fixtures/line_socket.js +1 -1
  89. package/tests/fixtures/util_hmailitem.js +5 -7
  90. package/tests/fixtures/vm_harness.js +2 -2
  91. package/tests/host_pool.js +13 -14
  92. package/tests/installation/plugins/inherits.js +1 -2
  93. package/tests/logger.js +2 -2
  94. package/tests/plugins/bounce.js +6 -8
  95. package/tests/plugins/dkim_signer.js +7 -7
  96. package/tests/plugins/dns_list_base.js +7 -7
  97. package/tests/plugins/helo.checks.js +1 -1
  98. package/tests/plugins/mail_from.is_resolvable.js +10 -54
  99. package/tests/plugins/queue/smtp_forward.js +11 -11
  100. package/tests/plugins/rcpt_to.host_list_base.js +1 -1
  101. package/tests/plugins/rcpt_to.in_host_list.js +1 -1
  102. package/tests/plugins/spamassassin.js +1 -1
  103. package/tests/queue/multibyte +0 -0
  104. package/tests/queue/plain +0 -0
  105. package/tests/rfc1869.js +4 -1
  106. package/tests/server.js +15 -9
  107. package/tests/smtp_client/auth.js +4 -14
  108. package/tests/smtp_client/basic.js +5 -15
  109. package/tests/smtp_client.js +7 -3
  110. package/tests/transaction.js +72 -19
  111. package/tls_socket.js +75 -85
  112. package/transaction.js +7 -9
  113. package/attachment_stream.js +0 -118
  114. package/bin/spf +0 -48
  115. package/chunkemitter.js +0 -75
  116. package/config/data.uribl.excludes +0 -202
  117. package/config/data.uribl.ini +0 -37
  118. package/config/spf.ini +0 -1
  119. package/docs/plugins/attachment.md +0 -92
  120. package/docs/plugins/data.uribl.md +0 -120
  121. package/docs/plugins/spf.md +0 -142
  122. package/mailbody.js +0 -502
  123. package/mailheader.js +0 -304
  124. package/messagestream.js +0 -441
  125. package/plugins/aliases.js +0 -120
  126. package/plugins/attachment.js +0 -503
  127. package/plugins/connect.p0f.js +0 -5
  128. package/plugins/spf.js +0 -327
  129. package/spf.js +0 -689
  130. package/tests/mailbody.js +0 -348
  131. package/tests/mailheader.js +0 -138
  132. package/tests/messagestream.js +0 -34
  133. package/tests/plugins/aliases.js +0 -376
  134. package/tests/plugins/spf.js +0 -251
  135. package/tests/spf.js +0 -96
@@ -17,13 +17,12 @@ exports.transaction = {
17
17
  tearDown : _tear_down,
18
18
 
19
19
  'add_body_filter' (test) {
20
- const self = this;
21
20
 
22
21
  test.expect(3);
23
22
 
24
23
  this.transaction.add_body_filter('text/plain', (ct, enc, buf) => {
25
- // The actual functionality of these filter functions is tested in
26
- // mailbody.js. This just makes sure the plumbing is in place.
24
+ // The functionality of these filter functions is tested in
25
+ // haraka-email-message. This just assures the plumbing is in place.
27
26
 
28
27
  test.ok(ct.indexOf('text/plain') === 0, "correct body part");
29
28
  test.ok(/utf-?8/i.test(enc), "correct encoding");
@@ -43,7 +42,7 @@ exports.transaction = {
43
42
  "<p>HTML part</p>\n",
44
43
  "--abcd--\n",
45
44
  ].forEach(line => {
46
- self.transaction.add_data(line);
45
+ this.transaction.add_data(line);
47
46
  });
48
47
  this.transaction.end_data(() => {
49
48
  test.done();
@@ -51,7 +50,6 @@ exports.transaction = {
51
50
  },
52
51
 
53
52
  'regression: attachment_hooks before set_banner/add_body_filter' (test) {
54
- const self = this;
55
53
 
56
54
  test.expect(2);
57
55
 
@@ -65,10 +63,10 @@ exports.transaction = {
65
63
  "\n",
66
64
  "Some text\n",
67
65
  ].forEach(line => {
68
- self.transaction.add_data(line);
66
+ this.transaction.add_data(line);
69
67
  });
70
68
  this.transaction.end_data(() => {
71
- self.transaction.message_stream.get_data(body => {
69
+ this.transaction.message_stream.get_data(body => {
72
70
  test.ok(/banner$/.test(body.toString().trim()), "banner applied");
73
71
  test.done();
74
72
  });
@@ -103,7 +101,6 @@ exports.transaction = {
103
101
  },
104
102
 
105
103
  'no munging of bytes if not parsing body' (test) {
106
- const self = this;
107
104
 
108
105
  // Czech panagram "Příliš žluťoučký kůň úpěl ďábelské ódy.\n" in ISO-8859-2 encoding
109
106
  const message = Buffer.from([0x50, 0xF8, 0xED, 0x6C, 0x69, 0xB9, 0x20, 0xBE, 0x6C, 0x75, 0xBB, 0x6F, 0x76, 0xE8, 0x6B, 0xFD, 0x20, 0x6B, 0xF9, 0xF2, 0xFA, 0xEC, 0x6C, 0x20, 0xEF, 0xE2, 0x62, 0x65, 0x6C, 0x73, 0x6b, 0xE9, 0x20, 0xF3, 0x64, 0x79, 0x2E, 0x0A]);
@@ -116,10 +113,10 @@ exports.transaction = {
116
113
  test.expect(1);
117
114
 
118
115
  payload.forEach(line => {
119
- self.transaction.add_data(line);
116
+ this.transaction.add_data(line);
120
117
  });
121
118
  this.transaction.end_data(() => {
122
- self.transaction.message_stream.get_data(body => {
119
+ this.transaction.message_stream.get_data(body => {
123
120
  test.ok(body.includes(message), "message not damaged");
124
121
  test.done();
125
122
  });
@@ -186,12 +183,11 @@ exports.base64_handling = {
186
183
  tearDown: _tear_down,
187
184
 
188
185
  'varied-base64-fold-lengths-preserve-data' (test) {
189
- const self = this;
190
186
 
191
187
  const parsed_attachments = {};
192
- self.transaction.parse_body = true;
188
+ this.transaction.parse_body = true;
193
189
  //accumulate attachment buffers.
194
- self.transaction.attachment_hooks((ct, filename, body, stream) => {
190
+ this.transaction.attachment_hooks((ct, filename, body, stream) => {
195
191
  let attachment = Buffer.alloc(0);
196
192
  stream.on('data', data => {
197
193
  attachment = Buffer.concat([attachment, data]);
@@ -202,9 +198,9 @@ exports.base64_handling = {
202
198
  });
203
199
 
204
200
  const specimen_path = path.join(__dirname, 'mail_specimen', 'varied-fold-lengths-preserve-data.txt');
205
- write_file_data_to_transaction(self.transaction, specimen_path);
201
+ write_file_data_to_transaction(this.transaction, specimen_path);
206
202
 
207
- test.equal(self.transaction.body.children.length, 6);
203
+ test.equal(this.transaction.body.children.length, 6);
208
204
 
209
205
  let first_attachment = null;
210
206
  for (const i in parsed_attachments) {
@@ -219,13 +215,70 @@ exports.base64_handling = {
219
215
  },
220
216
 
221
217
  'base64-root-html-decodes-correct-number-of-bytes' (test) {
222
- const self = this;
223
218
 
224
- self.transaction.parse_body = true;
219
+ this.transaction.parse_body = true;
225
220
  const specimen_path = path.join(__dirname, 'mail_specimen', 'base64-root-part.txt');
226
- write_file_data_to_transaction(self.transaction, specimen_path);
221
+ write_file_data_to_transaction(this.transaction, specimen_path);
227
222
 
228
- test.equal(self.transaction.body.bodytext.length, 425);
223
+ test.equal(this.transaction.body.bodytext.length, 425);
229
224
  test.done();
230
225
  },
231
226
  }
227
+
228
+ // Test is to ensure boundary marker just after the headers, is in-tact
229
+ // Issue: "User1990" <--abcd
230
+ // Expected: --abcd
231
+ exports.boundarymarkercorrupt_test = {
232
+ setUp : _set_up,
233
+ tearDown: _tear_down,
234
+
235
+ // populate the same email data in transaction (self.transaction.add_data()) and
236
+ // in raw buffer, then compare
237
+ 'fix mime boundary corruption issue' (test) {
238
+ const self = this;
239
+ let buffer = '';
240
+ self.transaction.add_data("Content-Type: multipart/alternative; boundary=abcd\r\n");
241
+ buffer += "Content-Type: multipart/alternative; boundary=abcd\r\n";
242
+ self.transaction.add_data('To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n');
243
+ buffer += 'To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n';
244
+ // make sure we add headers so that it exceeds 64k bytes to expose this issue
245
+ for (let i=0;i<725;i++){
246
+ self.transaction.add_data(` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`);
247
+ buffer += ` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`
248
+ }
249
+ self.transaction.add_data(' "Final User_firstname_middlename_lastname" <final_user_firstname_middlename_lastname@test.com>\r\n');
250
+ buffer += ' "Final User_firstname_middlename_lastname" <final_user_firstname_middlename_lastname@test.com>\r\n';
251
+ self.transaction.add_data('Message-ID: <Boundary_Marker_Test>\r\n');
252
+ buffer += 'Message-ID: <Boundary_Marker_Test>\r\n';
253
+ self.transaction.add_data('MIME-Version: 1.0\r\n');
254
+ buffer += 'MIME-Version: 1.0\r\n';
255
+ self.transaction.add_data('Date: Wed, 1 Jun 2022 16:44:39 +0530 (IST)\r\n');
256
+ buffer += 'Date: Wed, 1 Jun 2022 16:44:39 +0530 (IST)\r\n';
257
+ self.transaction.add_data('\r\n');
258
+ buffer += '\r\n';
259
+ self.transaction.add_data("--abcd\r\n");
260
+ buffer += "--abcd\r\n";
261
+
262
+ [
263
+ "Content-Type: text/plain\r\n",
264
+ "\r\n",
265
+ "Text part\r\n",
266
+ "--abcd\r\n",
267
+ "Content-Type: text/html\r\n",
268
+ "\r\n",
269
+ "<p>HTML part</p>\r\n",
270
+ "--abcd--\r\n",
271
+ ].forEach(line => {
272
+ self.transaction.add_data(line);
273
+ buffer += line;
274
+ });
275
+
276
+ this.transaction.end_data(function () {
277
+ self.transaction.message_stream.get_data(function (body) {
278
+ test.ok(body.includes(buffer), "message is damaged");
279
+ test.done();
280
+ });
281
+ });
282
+ },
283
+ }
284
+
package/tls_socket.js CHANGED
@@ -7,7 +7,7 @@
7
7
  const cluster = require('cluster');
8
8
  const net = require('net');
9
9
  const path = require('path');
10
- const spawn = require('child_process').spawn;
10
+ const { spawn } = require('child_process');
11
11
  const stream = require('stream');
12
12
  const tls = require('tls');
13
13
  const util = require('util');
@@ -53,61 +53,60 @@ class pluggableStream extends stream.Stream {
53
53
  }
54
54
 
55
55
  attach (socket) {
56
- const self = this;
57
- self.targetsocket = socket;
58
- self.targetsocket.on('data', data => {
59
- self.emit('data', data);
56
+ this.targetsocket = socket;
57
+ this.targetsocket.on('data', data => {
58
+ this.emit('data', data);
60
59
  });
61
- self.targetsocket.on('connect', (a, b) => {
62
- self.emit('connect', a, b);
60
+ this.targetsocket.on('connect', (a, b) => {
61
+ this.emit('connect', a, b);
63
62
  });
64
- self.targetsocket.on('secureConnect', (a, b) => {
65
- self.emit('secureConnect', a, b);
66
- self.emit('secure', a, b);
63
+ this.targetsocket.on('secureConnect', (a, b) => {
64
+ this.emit('secureConnect', a, b);
65
+ this.emit('secure', a, b);
67
66
  });
68
- self.targetsocket.on('secureConnection', (a, b) => {
67
+ this.targetsocket.on('secureConnection', (a, b) => {
69
68
  // investigate this for removal, see #2743
70
- self.emit('secureConnection', a, b);
71
- self.emit('secure', a, b);
69
+ this.emit('secureConnection', a, b);
70
+ this.emit('secure', a, b);
72
71
  });
73
- self.targetsocket.on('secure', (a, b) => {
74
- self.emit('secureConnection', a, b);
75
- self.emit('secure', a, b);
72
+ this.targetsocket.on('secure', (a, b) => {
73
+ this.emit('secureConnection', a, b);
74
+ this.emit('secure', a, b);
76
75
  });
77
- self.targetsocket.on('end', () => {
78
- self.writable = self.targetsocket.writable;
79
- self.emit('end');
76
+ this.targetsocket.on('end', () => {
77
+ this.writable = this.targetsocket.writable;
78
+ this.emit('end');
80
79
  });
81
- self.targetsocket.on('close', had_error => {
82
- self.writable = self.targetsocket.writable;
83
- self.emit('close', had_error);
80
+ this.targetsocket.on('close', had_error => {
81
+ this.writable = this.targetsocket.writable;
82
+ this.emit('close', had_error);
84
83
  });
85
- self.targetsocket.on('drain', () => {
86
- self.emit('drain');
84
+ this.targetsocket.on('drain', () => {
85
+ this.emit('drain');
87
86
  });
88
- self.targetsocket.once('error', exception => {
89
- self.writable = self.targetsocket.writable;
87
+ this.targetsocket.once('error', exception => {
88
+ this.writable = this.targetsocket.writable;
90
89
  exception.source = 'tls';
91
- self.emit('error', exception);
90
+ this.emit('error', exception);
92
91
  });
93
- self.targetsocket.on('timeout', () => {
94
- self.emit('timeout');
92
+ this.targetsocket.on('timeout', () => {
93
+ this.emit('timeout');
95
94
  });
96
- if (self.targetsocket.remotePort) {
97
- self.remotePort = self.targetsocket.remotePort;
95
+ if (this.targetsocket.remotePort) {
96
+ this.remotePort = this.targetsocket.remotePort;
98
97
  }
99
- if (self.targetsocket.remoteAddress) {
100
- self.remoteAddress = self.targetsocket.remoteAddress;
98
+ if (this.targetsocket.remoteAddress) {
99
+ this.remoteAddress = this.targetsocket.remoteAddress;
101
100
  }
102
- if (self.targetsocket.localPort) {
103
- self.localPort = self.targetsocket.localPort;
101
+ if (this.targetsocket.localPort) {
102
+ this.localPort = this.targetsocket.localPort;
104
103
  }
105
- if (self.targetsocket.localAddress) {
106
- self.localAddress = self.targetsocket.localAddress;
104
+ if (this.targetsocket.localAddress) {
105
+ this.localAddress = this.targetsocket.localAddress;
107
106
  }
108
107
  }
109
108
  clean (data) {
110
- if (this.targetsocket && this.targetsocket.removeAllListeners) {
109
+ if (this.targetsocket?.removeAllListeners) {
111
110
  [ 'data', 'secure', 'secureConnect', 'secureConnection',
112
111
  'end', 'close', 'error', 'drain'
113
112
  ].forEach((name) => {
@@ -224,7 +223,6 @@ exports.parse_x509 = string => {
224
223
  }
225
224
 
226
225
  exports.load_tls_ini = (opts) => {
227
- const tlss = this;
228
226
 
229
227
  log.loginfo(`loading tls.ini`); // from ${this.config.root_path}`);
230
228
 
@@ -247,7 +245,7 @@ exports.load_tls_ini = (opts) => {
247
245
  '-main.mutual_tls',
248
246
  ]
249
247
  }, () => {
250
- tlss.load_tls_ini();
248
+ this.load_tls_ini();
251
249
  });
252
250
 
253
251
  if (cfg.no_tls_hosts === undefined) cfg.no_tls_hosts = {};
@@ -279,11 +277,11 @@ exports.load_tls_ini = (opts) => {
279
277
 
280
278
  if (!Array.isArray(cfg.main.no_starttls_ports)) cfg.main.no_starttls_ports = [];
281
279
 
282
- tlss.cfg = cfg;
280
+ this.cfg = cfg;
283
281
 
284
282
  if (!opts || opts.role === 'server') {
285
- tlss.applySocketOpts('*');
286
- tlss.load_default_opts();
283
+ this.applySocketOpts('*');
284
+ this.load_default_opts();
287
285
  }
288
286
 
289
287
  return cfg;
@@ -295,7 +293,6 @@ exports.saveOpt = (name, opt, val) => {
295
293
  }
296
294
 
297
295
  exports.applySocketOpts = name => {
298
- const tlss = this;
299
296
 
300
297
  if (!certsByHost[name]) certsByHost[name] = {};
301
298
 
@@ -318,56 +315,55 @@ exports.applySocketOpts = name => {
318
315
 
319
316
  for (const opt of allOpts) {
320
317
 
321
- if (tlss.cfg[name] && tlss.cfg[name][opt] !== undefined) {
318
+ if (this.cfg[name] && this.cfg[name][opt] !== undefined) {
322
319
  // if the setting exists in tls.ini [name]
323
- tlss.saveOpt(name, opt, tlss.cfg[name][opt]);
320
+ this.saveOpt(name, opt, this.cfg[name][opt]);
324
321
  continue;
325
322
  }
326
323
 
327
- if (tlss.cfg.main[opt] !== undefined) {
324
+ if (this.cfg.main[opt] !== undefined) {
328
325
  // if the setting exists in tls.ini [main]
329
326
  // then save it to the certsByHost options
330
- tlss.saveOpt(name, opt, tlss.cfg.main[opt]);
327
+ this.saveOpt(name, opt, this.cfg.main[opt]);
331
328
  continue;
332
329
  }
333
330
 
334
331
  // defaults
335
332
  switch (opt) {
336
333
  case 'sessionIdContext':
337
- tlss.saveOpt(name, opt, 'haraka');
334
+ this.saveOpt(name, opt, 'haraka');
338
335
  break;
339
336
  case 'isServer':
340
- tlss.saveOpt(name, opt, true);
337
+ this.saveOpt(name, opt, true);
341
338
  break;
342
339
  case 'key':
343
- tlss.saveOpt(name, opt, 'tls_key.pem');
340
+ this.saveOpt(name, opt, 'tls_key.pem');
344
341
  break;
345
342
  case 'cert':
346
- tlss.saveOpt(name, opt, 'tls_cert.pem');
343
+ this.saveOpt(name, opt, 'tls_cert.pem');
347
344
  break;
348
345
  case 'dhparam':
349
- tlss.saveOpt(name, opt, 'dhparams.pem');
346
+ this.saveOpt(name, opt, 'dhparams.pem');
350
347
  break;
351
348
  case 'SNICallback':
352
- tlss.saveOpt(name, opt, SNICallback);
349
+ this.saveOpt(name, opt, SNICallback);
353
350
  break;
354
351
  }
355
352
  }
356
353
  }
357
354
 
358
355
  exports.load_default_opts = () => {
359
- const tlss = this;
360
356
 
361
357
  const cfg = certsByHost['*'];
362
358
 
363
359
  if (cfg.dhparam && typeof cfg.dhparam === 'string') {
364
360
  log.logdebug(`loading dhparams from ${cfg.dhparam}`);
365
- tlss.saveOpt('*', 'dhparam', tlss.config.get(cfg.dhparam, 'binary'));
361
+ this.saveOpt('*', 'dhparam', this.config.get(cfg.dhparam, 'binary'));
366
362
  }
367
363
 
368
364
  if (cfg.ca && typeof cfg.ca === 'string') {
369
365
  log.loginfo(`loading CA certs from ${cfg.ca}`);
370
- tlss.saveOpt('*', 'ca', tlss.config.get(cfg.ca, 'binary'));
366
+ this.saveOpt('*', 'ca', this.config.get(cfg.ca, 'binary'));
371
367
  }
372
368
 
373
369
  // make non-array key/cert option into Arrays with one entry
@@ -383,32 +379,32 @@ exports.load_default_opts = () => {
383
379
  // turn key/cert file names into actual key/cert binary data
384
380
  const asArray = cfg.key.map(keyFileName => {
385
381
  if (!keyFileName) return;
386
- const key = tlss.config.get(keyFileName, 'binary');
382
+ const key = this.config.get(keyFileName, 'binary');
387
383
  if (!key) {
388
- log.logerror(`tls key ${path.join(tlss.config.root_path, keyFileName)} could not be loaded.`);
384
+ log.logerror(`tls key ${path.join(this.config.root_path, keyFileName)} could not be loaded.`);
389
385
  }
390
386
  return key;
391
387
  })
392
- tlss.saveOpt('*', 'key', asArray);
388
+ this.saveOpt('*', 'key', asArray);
393
389
  }
394
390
 
395
391
  if (typeof cfg.cert[0] === 'string') {
396
392
  const asArray = cfg.cert.map(certFileName => {
397
393
  if (!certFileName) return;
398
- const cert = tlss.config.get(certFileName, 'binary');
394
+ const cert = this.config.get(certFileName, 'binary');
399
395
  if (!cert) {
400
- log.logerror(`tls cert ${path.join(tlss.config.root_path, certFileName)} could not be loaded.`);
396
+ log.logerror(`tls cert ${path.join(this.config.root_path, certFileName)} could not be loaded.`);
401
397
  }
402
398
  return cert;
403
399
  })
404
- tlss.saveOpt('*', 'cert', asArray);
400
+ this.saveOpt('*', 'cert', asArray);
405
401
  }
406
402
 
407
403
  if (cfg.cert[0] && cfg.key[0]) {
408
- tlss.tls_valid = true;
404
+ this.tls_valid = true;
409
405
 
410
406
  // now that all opts are applied, generate TLS context
411
- tlss.ensureDhparams(() => {
407
+ this.ensureDhparams(() => {
412
408
  ctxByHost['*'] = tls.createSecureContext(cfg);
413
409
  })
414
410
  }
@@ -423,9 +419,8 @@ function SNICallback (servername, sniDone) {
423
419
  }
424
420
 
425
421
  exports.get_certs_dir = (tlsDir, done) => {
426
- const tlss = this;
427
422
 
428
- tlss.config.getDir(tlsDir, {}, (iterErr, files) => {
423
+ this.config.getDir(tlsDir, {}, (iterErr, files) => {
429
424
  if (iterErr) return done(iterErr);
430
425
 
431
426
  async.map(files, (file, iter_done) => {
@@ -452,7 +447,7 @@ exports.get_certs_dir = (tlsDir, done) => {
452
447
  log.logerror(e);
453
448
  }
454
449
 
455
- const expire = tlss.parse_x509_expire(file, as_str);
450
+ const expire = this.parse_x509_expire(file, as_str);
456
451
  if (expire && expire < new Date()) {
457
452
  log.logerror(`${file.path} expired on ${expire}`);
458
453
  }
@@ -462,7 +457,7 @@ exports.get_certs_dir = (tlsDir, done) => {
462
457
  file: path.basename(file.path),
463
458
  key: parsed.key,
464
459
  cert: parsed.cert,
465
- names: tlss.parse_x509_names(as_str),
460
+ names: this.parse_x509_names(as_str),
466
461
  expires: expire,
467
462
  })
468
463
  })
@@ -486,13 +481,13 @@ exports.get_certs_dir = (tlsDir, done) => {
486
481
 
487
482
  // log.logdebug(cert); // DANGER: Also logs private key!
488
483
  cert.names.forEach(name => {
489
- tlss.applySocketOpts(name);
484
+ this.applySocketOpts(name);
490
485
 
491
- tlss.saveOpt(name, 'cert', cert.cert);
492
- tlss.saveOpt(name, 'key', cert.key);
486
+ this.saveOpt(name, 'cert', cert.cert);
487
+ this.saveOpt(name, 'key', cert.key);
493
488
  if (certsByHost['*'] !== undefined && certsByHost['*'].dhparam) {
494
489
  // copy in dhparam from default '*' TLS config
495
- tlss.saveOpt(name, 'dhparam', certsByHost['*'].dhparam);
490
+ this.saveOpt(name, 'dhparam', certsByHost['*'].dhparam);
496
491
  }
497
492
 
498
493
  // now that all opts are applied, generate TLS context
@@ -507,12 +502,11 @@ exports.get_certs_dir = (tlsDir, done) => {
507
502
  }
508
503
 
509
504
  exports.getSocketOpts = (name, done) => {
510
- const tlss = this;
511
505
 
512
506
  // startup time, load the config/tls dir
513
- if (!certsByHost['*']) tlss.load_tls_ini();
507
+ if (!certsByHost['*']) this.load_tls_ini();
514
508
 
515
- tlss.get_certs_dir('tls', () => {
509
+ this.get_certs_dir('tls', () => {
516
510
  if (certsByHost[name]) {
517
511
  // log.logdebug(certsByHost[name]);
518
512
  return done(certsByHost[name]);
@@ -538,7 +532,6 @@ function pipe (cleartext, socket) {
538
532
  }
539
533
 
540
534
  exports.ensureDhparams = done => {
541
- const tlss = this;
542
535
 
543
536
  // empty/missing dhparams file
544
537
  if (certsByHost['*'].dhparam) {
@@ -547,7 +540,7 @@ exports.ensureDhparams = done => {
547
540
 
548
541
  if (cluster.isWorker) return; // only once, on the master process
549
542
 
550
- const filePath = tlss.cfg.main.dhparam || 'dhparams.pem';
543
+ const filePath = this.cfg.main.dhparam || 'dhparams.pem';
551
544
  const fpResolved = path.resolve(exports.config.root_path, filePath);
552
545
 
553
546
  log.loginfo(`Generating a 2048 bit dhparams file at ${fpResolved}`);
@@ -568,9 +561,9 @@ exports.ensureDhparams = done => {
568
561
  }
569
562
 
570
563
  log.loginfo(`Saved to ${fpResolved}`);
571
- const content = tlss.config.get(filePath, 'binary');
564
+ const content = this.config.get(filePath, 'binary');
572
565
 
573
- tlss.saveOpt('*', 'dhparam', content);
566
+ this.saveOpt('*', 'dhparam', content);
574
567
  done(null, certsByHost['*'].dhparam);
575
568
  });
576
569
  }
@@ -636,9 +629,7 @@ exports.get_rejectUnauthorized = (rejectUnauthorized, port, port_list) => {
636
629
 
637
630
  if (rejectUnauthorized) return true;
638
631
 
639
- if (port_list.includes(port)) return true;
640
-
641
- return false;
632
+ return !!(port_list.includes(port));
642
633
  }
643
634
 
644
635
  function createServer (cb) {
@@ -704,11 +695,10 @@ function getCertFor (host) {
704
695
  return certsByHost['*']; // the default TLS cert
705
696
  }
706
697
 
707
- function connect (port, host, cb) {
698
+ function connect (port, host) {
708
699
  let conn_options = {};
709
700
  if (typeof port === 'object') {
710
701
  conn_options = port;
711
- cb = host;
712
702
  }
713
703
  else {
714
704
  conn_options.port = port;
package/transaction.js CHANGED
@@ -9,9 +9,7 @@ const Notes = require('haraka-notes');
9
9
  const utils = require('haraka-utils');
10
10
 
11
11
  // Haraka modules
12
- const Header = require('./mailheader').Header;
13
- const body = require('./mailbody');
14
- const MessageStream = require('./messagestream');
12
+ const message = require('haraka-email-message')
15
13
 
16
14
  class Transaction {
17
15
  constructor (uuid, cfg) {
@@ -31,8 +29,8 @@ class Transaction {
31
29
  this.parse_body = false;
32
30
  this.notes = new Notes();
33
31
  this.notes.skip_plugins = [];
34
- this.header = new Header();
35
- this.message_stream = new MessageStream(this.cfg, this.uuid, this.header.header_list);
32
+ this.header = new message.Header();
33
+ this.message_stream = new message.stream(this.cfg, this.uuid, this.header.header_list);
36
34
  this.discard_data = false;
37
35
  this.resetting = false;
38
36
  this.rcpt_count = {
@@ -50,7 +48,7 @@ class Transaction {
50
48
  ensure_body () {
51
49
  if (this.body) return;
52
50
 
53
- this.body = new body.Body(this.header);
51
+ this.body = new message.Body(this.header);
54
52
  this.body.on('mime_boundary', m => this.incr_mime_count());
55
53
  this.attachment_start_hooks.forEach(h => {
56
54
  this.body.on('attachment_start', h);
@@ -62,7 +60,7 @@ class Transaction {
62
60
 
63
61
  for (const o of this.body_filters) {
64
62
  this.body.add_filter((ct, enc, buf) => {
65
- const re_match = (util.isRegExp(o.ct_match) && o.ct_match.test(ct.toLowerCase()));
63
+ const re_match = (util.types.isRegExp(o.ct_match) && o.ct_match.test(ct.toLowerCase()));
66
64
  const ct_begins = ct.toLowerCase().indexOf(String(o.ct_match).toLowerCase()) === 0;
67
65
  if (re_match || ct_begins) return o.filter(ct, enc, buf);
68
66
  })
@@ -186,8 +184,8 @@ class Transaction {
186
184
  this.header_pos = header_pos;
187
185
  if (this.parse_body) {
188
186
  this.ensure_body();
189
- for (let j = 0; j < body_lines.length; j++) {
190
- this.body.parse_more(body_lines[j]);
187
+ for (const bodyLine of body_lines) {
188
+ this.body.parse_more(bodyLine);
191
189
  }
192
190
  }
193
191
  }