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
@@ -5,13 +5,11 @@ const sock = require('./line_socket');
5
5
  const utils = require('haraka-utils');
6
6
 
7
7
  exports.register = function () {
8
- const plugin = this;
9
- plugin.load_spamassassin_ini();
8
+ this.load_spamassassin_ini();
10
9
  }
11
10
 
12
11
  exports.load_spamassassin_ini = function () {
13
- const plugin = this;
14
- plugin.cfg = plugin.config.get('spamassassin.ini', {
12
+ this.cfg = this.config.get('spamassassin.ini', {
15
13
  booleans: [
16
14
  '+add_headers',
17
15
  '+check.authenticated',
@@ -24,7 +22,7 @@ exports.load_spamassassin_ini = function () {
24
22
  '-defer.scan_timeout',
25
23
  ],
26
24
  }, () => {
27
- plugin.load_spamassassin_ini();
25
+ this.load_spamassassin_ini();
28
26
  });
29
27
 
30
28
  const defaults = {
@@ -36,31 +34,29 @@ exports.load_spamassassin_ini = function () {
36
34
  };
37
35
 
38
36
  for (const key in defaults) {
39
- if (plugin.cfg.main[key]) continue;
40
- plugin.cfg.main[key] = defaults[key];
37
+ if (this.cfg.main[key]) continue;
38
+ this.cfg.main[key] = defaults[key];
41
39
  }
42
40
 
43
41
  [
44
42
  'reject_threshold', 'relay_reject_threshold',
45
43
  'munge_subject_threshold', 'max_size'
46
44
  ].forEach(item => {
47
- if (!plugin.cfg.main[item]) return;
48
- plugin.cfg.main[item] = Number(plugin.cfg.main[item]);
45
+ if (!this.cfg.main[item]) return;
46
+ this.cfg.main[item] = Number(this.cfg.main[item]);
49
47
  });
50
48
  }
51
49
 
52
50
  exports.hook_data_post = function (next, connection) {
53
- const plugin = this;
54
- const conn = connection;
55
- const txn = connection.transaction;
56
51
 
57
- if (plugin.should_skip(conn)) return next();
52
+ if (this.should_skip(connection)) return next();
58
53
 
59
- txn.remove_header(plugin.cfg.main.spamc_auth_header); // just to be safe
54
+ const txn = connection.transaction;
55
+ txn.remove_header(this.cfg.main.spamc_auth_header); // just to be safe
60
56
 
61
- const username = plugin.get_spamd_username(conn);
62
- const headers = plugin.get_spamd_headers(conn, username);
63
- const socket = plugin.get_spamd_socket(next, conn, headers);
57
+ const username = this.get_spamd_username(connection);
58
+ const headers = this.get_spamd_headers(connection, username);
59
+ const socket = this.get_spamd_socket(next, connection, headers);
64
60
 
65
61
  const spamd_response = { headers: {} };
66
62
  let state = 'line0';
@@ -68,7 +64,7 @@ exports.hook_data_post = function (next, connection) {
68
64
  const start = Date.now();
69
65
 
70
66
  socket.on('line', line => {
71
- conn.logprotocol(plugin, `Spamd C: ${line} state=${state}`);
67
+ connection.logprotocol(this, `Spamd C: ${line} state=${state}`);
72
68
  line = line.replace(/\r?\n/, '');
73
69
  if (state === 'line0') {
74
70
  spamd_response.line0 = line;
@@ -92,7 +88,7 @@ exports.hook_data_post = function (next, connection) {
92
88
  else if (state === 'headers') {
93
89
  const m = line.match(/^X-Spam-([\x21-\x39\x3B-\x7E]+):\s*(.*)/);
94
90
  if (m) {
95
- conn.logdebug(plugin, `header: ${line}`);
91
+ connection.logdebug(this, `header: ${line}`);
96
92
  last_header = m[1];
97
93
  spamd_response.headers[m[1]] = m[2];
98
94
  return;
@@ -107,14 +103,14 @@ exports.hook_data_post = function (next, connection) {
107
103
  });
108
104
 
109
105
  socket.once('end', () => {
110
- if (!conn.transaction) return next() // client gone
106
+ if (!connection.transaction) return next() // client gone
111
107
 
112
- if (spamd_response.headers && spamd_response.headers.Tests) {
108
+ if (spamd_response.headers?.Tests) {
113
109
  spamd_response.tests = spamd_response.headers.Tests.replace(/\s/g, '');
114
110
  }
115
111
  if (spamd_response.tests === undefined) {
116
112
  // strip the 'tests' from the X-Spam-Status header
117
- if (spamd_response.headers && spamd_response.headers.Status) {
113
+ if (spamd_response.headers?.Status) {
118
114
  // SpamAssassin appears to have a bug that causes a space not to
119
115
  // be added before autolearn= when the header line has been folded.
120
116
  // So we modify the regexp here not to match autolearn onwards.
@@ -127,29 +123,28 @@ exports.hook_data_post = function (next, connection) {
127
123
 
128
124
  // do stuff with the results...
129
125
  txn.notes.spamassassin = spamd_response;
130
- conn.results.add(plugin, {
126
+ connection.results.add(this, {
131
127
  time: (Date.now() - start)/1000,
132
128
  hits: spamd_response.hits,
133
129
  flag: spamd_response.flag,
134
130
  });
135
131
 
136
- plugin.fixup_old_headers(txn);
137
- plugin.do_header_updates(conn, spamd_response);
138
- plugin.log_results(conn, spamd_response);
132
+ this.fixup_old_headers(txn);
133
+ this.do_header_updates(connection, spamd_response);
134
+ this.log_results(connection, spamd_response);
139
135
 
140
- const exceeds_err = plugin.score_too_high(conn, spamd_response);
136
+ const exceeds_err = this.score_too_high(connection, spamd_response);
141
137
  if (exceeds_err) return next(DENY, exceeds_err);
142
138
 
143
- plugin.munge_subject(conn, spamd_response.score);
139
+ this.munge_subject(connection, spamd_response.score);
144
140
 
145
141
  next();
146
142
  });
147
143
  }
148
144
 
149
145
  exports.fixup_old_headers = function (txn) {
150
- const plugin = this;
151
- const action = plugin.cfg.main.old_headers_action;
152
- const headers = txn.notes.spamassassin.headers;
146
+ const action = this.cfg.main.old_headers_action;
147
+ const { headers } = txn.notes.spamassassin;
153
148
 
154
149
  let key;
155
150
  switch (action) {
@@ -178,29 +173,27 @@ exports.fixup_old_headers = function (txn) {
178
173
  }
179
174
 
180
175
  exports.munge_subject = function (conn, score) {
181
- const plugin = this;
182
- const munge = plugin.cfg.main.munge_subject_threshold;
176
+ const munge = this.cfg.main.munge_subject_threshold;
183
177
  if (!munge) return;
184
178
  if (parseFloat(score) < parseFloat(munge)) return;
185
179
 
186
180
  const subj = conn.transaction.header.get('Subject');
187
- const subject_re = new RegExp(`^${utils.regexp_escape(plugin.cfg.main.subject_prefix)}`);
181
+ const subject_re = new RegExp(`^${utils.regexp_escape(this.cfg.main.subject_prefix)}`);
188
182
  if (subject_re.test(subj)) return; // prevent double munge
189
183
 
190
184
  conn.transaction.remove_header('Subject');
191
- conn.transaction.add_header('Subject', `${plugin.cfg.main.subject_prefix} ${subj}`);
185
+ conn.transaction.add_header('Subject', `${this.cfg.main.subject_prefix} ${subj}`);
192
186
  }
193
187
 
194
188
  exports.do_header_updates = function (conn, spamd_response) {
195
- const plugin = this;
196
189
  if (spamd_response.flag === 'Yes') {
197
190
  // X-Spam-Flag is added by SpamAssassin
198
191
  conn.transaction.remove_header('precedence');
199
192
  conn.transaction.add_header('Precedence', 'junk');
200
193
  }
201
194
 
202
- const modern = plugin.cfg.main.modern_status_syntax;
203
- if ( !plugin.cfg.main.add_headers ) return;
195
+ const modern = this.cfg.main.modern_status_syntax;
196
+ if ( !this.cfg.main.add_headers ) return;
204
197
 
205
198
  for (const key in spamd_response.headers) {
206
199
  if (!key || key === '' || key === undefined) continue;
@@ -218,31 +211,27 @@ exports.do_header_updates = function (conn, spamd_response) {
218
211
  }
219
212
 
220
213
  exports.score_too_high = function (conn, spamd_response) {
221
- const plugin = this;
222
- const score = spamd_response.score;
214
+ const { score } = spamd_response;
223
215
  if (conn.relaying) {
224
- const rmax = plugin.cfg.main.relay_reject_threshold;
216
+ const rmax = this.cfg.main.relay_reject_threshold;
225
217
  if (rmax && (score >= rmax)) {
226
218
  return "spam score exceeded relay threshold";
227
219
  }
228
220
  }
229
221
 
230
- const max = plugin.cfg.main.reject_threshold;
231
- if (max && (score >= max)) {
232
- return "spam score exceeded threshold";
233
- }
222
+ const max = this.cfg.main.reject_threshold;
223
+ if (max && (score >= max)) return "spam score exceeded threshold";
234
224
 
235
- return false;
225
+ return '';
236
226
  }
237
227
 
238
228
  exports.get_spamd_username = function (conn) {
239
- const plugin = this;
240
229
 
241
230
  let user = conn.transaction.notes.spamd_user; // 1st priority
242
231
  if (user && user !== undefined) return user;
243
232
 
244
- if (!plugin.cfg.main.spamd_user) return 'default'; // when not defined
245
- user = plugin.cfg.main.spamd_user;
233
+ if (!this.cfg.main.spamd_user) return 'default'; // when not defined
234
+ user = this.cfg.main.spamd_user;
246
235
 
247
236
  // Enable per-user SA prefs
248
237
  if (user === 'first-recipient') { // special cases
@@ -259,7 +248,6 @@ exports.get_spamd_username = function (conn) {
259
248
  }
260
249
 
261
250
  exports.get_spamd_headers = function (conn, username) {
262
- const plugin = this;
263
251
  // http://svn.apache.org/repos/asf/spamassassin/trunk/spamd/PROTOCOL
264
252
  const headers = [
265
253
  'HEADERS SPAMC/1.4',
@@ -269,7 +257,7 @@ exports.get_spamd_headers = function (conn, username) {
269
257
  `X-Haraka-UUID: ${conn.transaction.uuid}`,
270
258
  ];
271
259
  if (conn.relaying) {
272
- headers.push(`${plugin.cfg.main.spamc_auth_header}: true`);
260
+ headers.push(`${this.cfg.main.spamc_auth_header}: true`);
273
261
  }
274
262
 
275
263
  return headers;
@@ -335,8 +323,7 @@ exports.get_spamd_socket = function (next, conn, headers) {
335
323
  }
336
324
 
337
325
  exports.log_results = function (conn, spamd_response) {
338
- const plugin = this;
339
- const cfg = plugin.cfg.main;
326
+ const cfg = this.cfg.main;
340
327
  const reject_threshold = (conn.relaying) ? (cfg.relay_reject_threshold || cfg.reject_threshold) : cfg.reject_threshold;
341
328
 
342
329
  const human_text = `status=${spamd_response.flag}` +
@@ -345,49 +332,50 @@ exports.log_results = function (conn, spamd_response) {
345
332
  `, reject=${reject_threshold}` +
346
333
  `, tests="${spamd_response.tests}"`;
347
334
 
348
- conn.transaction.results.add(plugin, {
335
+ conn.transaction.results.add(this, {
349
336
  human: human_text,
350
337
  status: spamd_response.flag, score: parseFloat(spamd_response.score),
351
338
  required: parseFloat(spamd_response.reqd), reject: reject_threshold, tests: spamd_response.tests,
352
339
  emit: true});
353
340
  }
354
341
 
355
- exports.should_skip = function (conn) {
356
- const plugin = this;
342
+ exports.should_skip = function (connection = {}) {
343
+ const { transaction } = connection;
344
+ if (!transaction) return true;
357
345
 
358
346
  // a message might be skipped for multiple reasons, store each in results
359
347
  let result = false; // default
360
348
 
361
- const max = plugin.cfg.main.max_size;
349
+ const max = this.cfg.main.max_size;
362
350
  if (max) {
363
- const size = conn.transaction.data_bytes;
351
+ const size = connection.transaction.data_bytes;
364
352
  if (size > max) {
365
- conn.transaction.results.add(plugin, { skip: `size ${utils.prettySize(size)} exceeds max: ${utils.prettySize(max)}`});
353
+ connection.transaction.results.add(this, { skip: `size ${utils.prettySize(size)} exceeds max: ${utils.prettySize(max)}`});
366
354
  result = true;
367
355
  }
368
356
  }
369
357
 
370
- if (plugin.cfg.check.authenticated == false && conn.notes.auth_user) {
371
- conn.transaction.results.add(plugin, { skip: 'authed'});
358
+ if (this.cfg.check.authenticated == false && connection.notes.auth_user) {
359
+ connection.transaction.results.add(this, { skip: 'authed'});
372
360
  result = true;
373
361
  }
374
362
 
375
- if (plugin.cfg.check.relay == false && conn.relaying) {
376
- conn.transaction.results.add(plugin, { skip: 'relay'});
363
+ if (this.cfg.check.relay == false && connection.relaying) {
364
+ connection.transaction.results.add(this, { skip: 'relay'});
377
365
  result = true;
378
366
  }
379
367
 
380
- if (plugin.cfg.check.local_ip == false && conn.remote.is_local) {
381
- conn.transaction.results.add(plugin, { skip: 'local_ip'});
368
+ if (this.cfg.check.local_ip == false && connection.remote.is_local) {
369
+ connection.transaction.results.add(this, { skip: 'local_ip'});
382
370
  result = true;
383
371
  }
384
372
 
385
- if (plugin.cfg.check.private_ip == false && conn.remote.is_private) {
386
- if (plugin.cfg.check.local_ip == true && conn.remote.is_local) {
373
+ if (this.cfg.check.private_ip == false && connection.remote.is_private) {
374
+ if (this.cfg.check.local_ip == true && connection.remote.is_local) {
387
375
  // local IPs are included in private IPs
388
376
  }
389
377
  else {
390
- conn.transaction.results.add(plugin, { skip: 'private_ip'});
378
+ connection.transaction.results.add(this, { skip: 'private_ip'});
391
379
  result = true;
392
380
  }
393
381
  }
package/plugins/status.js CHANGED
@@ -148,7 +148,7 @@ exports.queue_discard = function (file, cb) {
148
148
  }
149
149
 
150
150
  exports.queue_push = function (file, cb) {
151
- const queue = this.outbound.temp_fail_queue.queue;
151
+ const { queue } = this.outbound.temp_fail_queue;
152
152
 
153
153
  for (let i = 0; i < queue.length; i++) {
154
154
  if (queue[i].id !== file) continue;
@@ -214,10 +214,9 @@ exports.call_master = (cmd, cb) => {
214
214
  }
215
215
 
216
216
  exports.call_workers = function (cmd, cb) {
217
- const self = this;
218
217
 
219
218
  async.map(server.cluster.workers, (w, done) => {
220
- self.call_worker(w, cmd, done);
219
+ this.call_worker(w, cmd, done);
221
220
  }, cb);
222
221
  }
223
222
 
package/plugins/tarpit.js CHANGED
@@ -8,30 +8,27 @@ let hooks_to_delay = [
8
8
 
9
9
  exports.register = function () {
10
10
  // Register tarpit function last
11
- const plugin = this;
12
11
 
13
- const cfg = plugin.config.get('tarpit.ini');
14
- if (cfg && cfg.main.hooks_to_delay) {
12
+ const cfg = this.config.get('tarpit.ini');
13
+ if (cfg?.main.hooks_to_delay) {
15
14
  hooks_to_delay = cfg.main.hooks_to_delay.split(/[\s,;]+/);
16
15
  }
17
16
 
18
- for (let i=0; i < hooks_to_delay.length; i++) {
19
- const hook = hooks_to_delay[i];
20
- plugin.register_hook(hook, 'tarpit');
17
+ for (const hook of hooks_to_delay) {
18
+ this.register_hook(hook, 'tarpit');
21
19
  }
22
20
  }
23
21
 
24
22
  exports.tarpit = function (next, connection) {
25
- const plugin = this;
23
+ const { transaction } = connection;
24
+ if (!transaction) return next();
26
25
 
27
26
  let delay = connection.notes.tarpit;
28
27
 
29
- if (!delay && connection.transaction) {
30
- delay = connection.transaction.notes.tarpit;
31
- }
28
+ if (!delay) delay = transaction.notes.tarpit;
32
29
 
33
30
  if (!delay) return next();
34
31
 
35
- connection.loginfo(plugin, `tarpitting response for ${delay}s`);
32
+ connection.loginfo(this, `tarpitting response for ${delay}s`);
36
33
  setTimeout(() => next(), delay * 1000);
37
34
  }
package/plugins/tls.js CHANGED
@@ -21,18 +21,17 @@ exports.shutdown = () => {
21
21
  }
22
22
 
23
23
  exports.advertise_starttls = function (next, connection) {
24
- const plugin = this;
25
24
 
26
25
  // if no TLS setup incomplete/invalid, don't advertise
27
26
  if (!tls_socket.tls_valid) {
28
- plugin.logerror('no valid TLS config');
27
+ this.logerror('no valid TLS config');
29
28
  return next();
30
29
  }
31
30
 
32
31
  /* Caution: do not advertise STARTTLS if already TLS upgraded */
33
32
  if (connection.tls.enabled) return next();
34
33
 
35
- if (plugin.net_utils.ip_in_list(tls_socket.cfg.no_tls_hosts, connection.remote.ip)) {
34
+ if (this.net_utils.ip_in_list(tls_socket.cfg.no_tls_hosts, connection.remote.ip)) {
36
35
  return next();
37
36
  }
38
37
 
@@ -52,20 +51,19 @@ exports.advertise_starttls = function (next, connection) {
52
51
  return enable_tls();
53
52
  }
54
53
 
55
- const redis = server.notes.redis;
54
+ const { redis } = server.notes;
56
55
  const dbkey = `no_tls|${connection.remote.ip}`;
57
56
 
58
- redis.get(dbkey, (err, dbr) => {
59
- if (err) {
60
- connection.results.add(plugin, {err});
61
- return enable_tls();
62
- }
63
-
64
- if (!dbr) return enable_tls();
65
-
66
- connection.results.add(plugin, { msg: 'no_tls'});
67
- return next(CONT, 'STARTTLS disabled because previous attempt failed')
68
- });
57
+ redis.get(dbkey)
58
+ .then(dbr => {
59
+ if (!dbr) return enable_tls();
60
+ connection.results.add(this, { msg: 'no_tls'});
61
+ next(CONT, 'STARTTLS disabled because previous attempt failed')
62
+ })
63
+ .catch(err => {
64
+ connection.results.add(this, {err});
65
+ enable_tls();
66
+ })
69
67
  }
70
68
 
71
69
  exports.set_notls = function (connection) {
@@ -138,7 +136,6 @@ exports.hook_disconnect = (next, connection) => {
138
136
  }
139
137
 
140
138
  exports.emit_upgrade_msg = function (conn, verified, verifyErr, cert, cipher) {
141
- const plugin = this;
142
139
  let msg = 'secured:';
143
140
  if (cipher) {
144
141
  msg += ` cipher=${cipher.name} version=${cipher.version}`;
@@ -154,6 +151,6 @@ exports.emit_upgrade_msg = function (conn, verified, verifyErr, cert, cipher) {
154
151
  if (cert.fingerprint) msg += ` fingerprint=${cert.fingerprint}`;
155
152
  }
156
153
 
157
- conn.loginfo(plugin, msg);
154
+ conn.loginfo(this, msg);
158
155
  return msg;
159
156
  }
@@ -4,26 +4,24 @@ let toobusy;
4
4
  let was_busy = false;
5
5
 
6
6
  exports.register = function () {
7
- const plugin = this;
8
7
 
9
8
  try {
10
9
  toobusy = require('toobusy-js');
11
10
  }
12
11
  catch (e) {
13
- plugin.logerror(e);
14
- plugin.logerror("try: 'npm install -g toobusy-js'");
12
+ this.logerror(e);
13
+ this.logerror("try: 'npm install -g toobusy-js'");
15
14
  return;
16
15
  }
17
16
 
18
- plugin.loadConfig();
17
+ this.loadConfig();
19
18
 
20
- plugin.register_hook('connect', 'check_busy', -100);
19
+ this.register_hook('connect', 'check_busy', -100);
21
20
  }
22
21
 
23
22
  exports.loadConfig = function () {
24
- const plugin = this;
25
- let maxLag = plugin.config.get('toobusy.maxlag','value', () => {
26
- plugin.loadConfig();
23
+ let maxLag = this.config.get('toobusy.maxlag','value', () => {
24
+ this.loadConfig();
27
25
  });
28
26
 
29
27
  maxLag = parseInt(maxLag);
@@ -11,9 +11,8 @@ exports.register = function () {
11
11
  }
12
12
 
13
13
  exports.load_xclient_hosts = function () {
14
- const self = this;
15
14
  const cfg = this.config.get('xclient.hosts', 'list', () => {
16
- self.load_xclient_hosts();
15
+ this.load_xclient_hosts();
17
16
  });
18
17
  const ah = {};
19
18
  for (const i in cfg) {
@@ -23,10 +22,7 @@ exports.load_xclient_hosts = function () {
23
22
  }
24
23
 
25
24
  function xclient_allowed (ip) {
26
- if (ip === '127.0.0.1' || ip === '::1' || allowed_hosts[ip]) {
27
- return true;
28
- }
29
- return false;
25
+ return !!(ip === '127.0.0.1' || ip === '::1' || allowed_hosts[ip]);
30
26
  }
31
27
 
32
28
  exports.hook_capabilities = (next, connection) => {
@@ -37,17 +33,14 @@ exports.hook_capabilities = (next, connection) => {
37
33
  }
38
34
 
39
35
  exports.hook_unrecognized_command = function (next, connection, params) {
40
- if (params[0] !== 'XCLIENT') {
41
- return next();
42
- }
36
+ if (params[0] !== 'XCLIENT') return next();
43
37
 
44
38
  // XCLIENT is not allowed after transaction start
45
- if (connection.transaction) {
46
- return next(DENY,
47
- DSN.proto_unspecified('Mail transaction in progress', 503));
39
+ if (connection?.transaction) {
40
+ return next(DENY, DSN.proto_unspecified('Mail transaction in progress', 503));
48
41
  }
49
42
 
50
- if (!(xclient_allowed(connection.remote.ip))) {
43
+ if (!(xclient_allowed(connection?.remote?.ip))) {
51
44
  return next(DENY, DSN.proto_unspecified('Not authorized', 550));
52
45
  }
53
46
 
@@ -55,8 +48,8 @@ exports.hook_unrecognized_command = function (next, connection, params) {
55
48
  // Process arguments
56
49
  const args = (new String(params[1])).toLowerCase().split(/ /);
57
50
  const xclient = {};
58
- for (let a=0; a < args.length; a++) {
59
- const match = /^([^=]+)=([^ ]+)/.exec(args[a]);
51
+ for (const arg of args) {
52
+ const match = /^([^=]+)=([^ ]+)/.exec(arg);
60
53
  if (match) {
61
54
  connection.logdebug(this, `found key=${match[1]} value=${match[2]}`);
62
55
  switch (match[1]) {
@@ -94,18 +87,17 @@ exports.hook_unrecognized_command = function (next, connection, params) {
94
87
  }
95
88
  break;
96
89
  default:
97
- connection.logwarn(this, `unknown argument: ${args[a]}`);
90
+ connection.logwarn(this, `unknown argument: ${arg}`);
98
91
  }
99
92
  }
100
93
  else {
101
- connection.logwarn(this, `unknown argument: ${args[a]}`);
94
+ connection.logwarn(this, `unknown argument: ${arg}`);
102
95
  }
103
96
  }
104
97
 
105
98
  // Abort if we don't have a valid IP address
106
99
  if (!xclient.addr) {
107
- return next(DENY,
108
- DSN.proto_invalid_cmd_args('No valid IP address found', 501));
100
+ return next(DENY, DSN.proto_invalid_cmd_args('No valid IP address found', 501));
109
101
  }
110
102
 
111
103
  // Apply changes
@@ -125,10 +117,7 @@ exports.hook_unrecognized_command = function (next, connection, params) {
125
117
  }
126
118
  connection.esmtp = (xclient.proto === 'esmtp');
127
119
  connection.xclient = true;
128
- if (!xclient.name) {
129
- return next(NEXT_HOOK, 'lookup_rdns');
130
- }
131
- else {
132
- return next(NEXT_HOOK, 'connect');
133
- }
120
+ if (!xclient.name) return next(NEXT_HOOK, 'lookup_rdns');
121
+
122
+ return next(NEXT_HOOK, 'connect');
134
123
  }