Haraka 3.2.1 → 3.3.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 (82) hide show
  1. package/.githooks/pre-commit +41 -0
  2. package/.prettierignore +1 -0
  3. package/.qlty/.gitignore +7 -0
  4. package/.qlty/configs/.shellcheckrc +1 -0
  5. package/.qlty/qlty.toml +15 -0
  6. package/CHANGELOG.md +29 -5
  7. package/CONTRIBUTORS.md +5 -5
  8. package/README.md +6 -3
  9. package/bin/haraka +12 -4
  10. package/config/connection.ini +6 -0
  11. package/connection.js +67 -68
  12. package/contrib/bsd-rc.d/haraka +2 -0
  13. package/docs/CoreConfig.md +2 -0
  14. package/docs/HAProxy.md +4 -1
  15. package/eslint.config.mjs +2 -30
  16. package/haraka.js +2 -2
  17. package/line_socket.js +6 -33
  18. package/outbound/hmail.js +18 -29
  19. package/outbound/index.js +3 -3
  20. package/outbound/queue.js +8 -5
  21. package/package.json +49 -46
  22. package/plugins/auth/auth_proxy.js +7 -4
  23. package/plugins/block_me.js +1 -1
  24. package/plugins/delay_deny.js +1 -1
  25. package/plugins/queue/qmail-queue.js +1 -1
  26. package/plugins/queue/quarantine.js +5 -5
  27. package/plugins/queue/smtp_bridge.js +1 -1
  28. package/plugins/queue/smtp_proxy.js +2 -2
  29. package/plugins/status.js +2 -2
  30. package/plugins/toobusy.js +1 -1
  31. package/plugins.js +4 -3
  32. package/server.js +172 -28
  33. package/smtp_client.js +2 -1
  34. package/test/connection.js +119 -2
  35. package/test/fixtures/haproxy_allowed/config/connection.ini +3 -0
  36. package/test/fixtures/haproxy_disabled/config/connection.ini +3 -0
  37. package/test/fixtures/haproxy_untrusted/config/connection.ini +3 -0
  38. package/test/fixtures/line_socket.js +1 -1
  39. package/test/fixtures/util_hmailitem.js +2 -3
  40. package/test/outbound/index.js +6 -7
  41. package/test/outbound/qfile.js +1 -1
  42. package/test/outbound/queue.js +2 -2
  43. package/test/plugins/auth/auth_base.js +17 -17
  44. package/test/plugins/auth/auth_bridge.js +3 -3
  45. package/test/plugins/auth/auth_vpopmaild.js +3 -3
  46. package/test/plugins/auth/flat_file.js +16 -21
  47. package/test/plugins/block_me.js +7 -23
  48. package/test/plugins/data.signatures.js +17 -20
  49. package/test/plugins/delay_deny.js +3 -4
  50. package/test/plugins/prevent_credential_leaks.js +17 -21
  51. package/test/plugins/process_title.js +12 -6
  52. package/test/plugins/queue/deliver.js +7 -8
  53. package/test/plugins/queue/discard.js +3 -4
  54. package/test/plugins/queue/lmtp.js +5 -6
  55. package/test/plugins/queue/qmail-queue.js +7 -8
  56. package/test/plugins/queue/quarantine.js +3 -4
  57. package/test/plugins/queue/smtp_bridge.js +5 -7
  58. package/test/plugins/queue/smtp_forward.js +49 -60
  59. package/test/plugins/queue/smtp_proxy.js +6 -7
  60. package/test/plugins/rcpt_to.host_list_base.js +6 -9
  61. package/test/plugins/rcpt_to.in_host_list.js +6 -11
  62. package/test/plugins/record_envelope_addresses.js +33 -60
  63. package/test/plugins/reseed_rng.js +3 -3
  64. package/test/plugins/status.js +4 -5
  65. package/test/plugins/tarpit.js +3 -4
  66. package/test/plugins/tls.js +3 -5
  67. package/test/plugins/toobusy.js +186 -9
  68. package/test/plugins/xclient.js +7 -4
  69. package/test/server.js +425 -1
  70. package/test/smtp_client.js +11 -18
  71. package/test/tls_socket.js +3 -6
  72. package/tls_socket.js +3 -3
  73. package/transaction.js +3 -3
  74. package/address.js +0 -53
  75. package/endpoint.js +0 -96
  76. package/host_pool.js +0 -169
  77. package/outbound/fsync_writestream.js +0 -44
  78. package/outbound/timer_queue.js +0 -86
  79. package/rfc1869.js +0 -93
  80. package/test/endpoint.js +0 -128
  81. package/test/host_pool.js +0 -188
  82. package/test/rfc1869.js +0 -89
package/test/server.js CHANGED
@@ -4,14 +4,33 @@ const { describe, it, beforeEach, afterEach } = require('node:test')
4
4
  const assert = require('node:assert/strict')
5
5
  const { createHmac } = require('node:crypto')
6
6
  const net = require('node:net')
7
+ const { once } = require('node:events')
7
8
  const path = require('node:path')
8
9
  const tls = require('node:tls')
9
10
  const constants = require('haraka-constants')
11
+ const net_utils = require('haraka-net-utils')
10
12
 
11
- const endpoint = require('../endpoint')
13
+ const { endpoint } = require('haraka-net-utils')
12
14
  const message = require('haraka-email-message')
13
15
  const { get_client } = require('../smtp_client')
14
16
 
17
+ function fixtureConfig(name) {
18
+ const testRoot = path.resolve('test')
19
+ return require('haraka-config').module_config(testRoot, path.resolve('test/fixtures', name))
20
+ }
21
+
22
+ function useHaproxyFixture(server, name) {
23
+ const originalConfig = net_utils.config
24
+ const originalConnectionCfg = server.connection.cfg
25
+ const config = fixtureConfig(name)
26
+ net_utils.config = config
27
+ server.connection.cfg = config.get('connection.ini', { booleans: ['+haproxy.enabled'] })
28
+ return () => {
29
+ net_utils.config = originalConfig
30
+ server.connection.cfg = originalConnectionCfg
31
+ }
32
+ }
33
+
15
34
  // ─── CRAM-MD5 helper ──────────────────────────────────────────────────────────
16
35
 
17
36
  /** Compute a CRAM-MD5 response to a server challenge. */
@@ -124,6 +143,35 @@ const sendMessage = ({
124
143
  )
125
144
  })
126
145
 
146
+ const listen = (server, host = '127.0.0.1') =>
147
+ new Promise((resolve, reject) => {
148
+ server.once('error', reject)
149
+ server.listen(0, host, () => {
150
+ server.removeListener('error', reject)
151
+ resolve()
152
+ })
153
+ })
154
+
155
+ const close = (server) =>
156
+ new Promise((resolve) => {
157
+ server.close(resolve)
158
+ })
159
+
160
+ const withTimeout = (promise, ms, msg) =>
161
+ new Promise((resolve, reject) => {
162
+ const timer = setTimeout(() => reject(new Error(msg)), ms)
163
+ promise.then(
164
+ (result) => {
165
+ clearTimeout(timer)
166
+ resolve(result)
167
+ },
168
+ (err) => {
169
+ clearTimeout(timer)
170
+ reject(err)
171
+ },
172
+ )
173
+ })
174
+
127
175
  // ─── Tests ────────────────────────────────────────────────────────────────────
128
176
 
129
177
  describe('server', () => {
@@ -241,6 +289,382 @@ describe('server', () => {
241
289
  const count = await new Promise((res) => server.getConnections((err, n) => res(n)))
242
290
  assert.equal(count, 0)
243
291
  })
292
+
293
+ it('accepts PROXY v1 before the SMTPS TLS handshake', async () => {
294
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
295
+ this.server.cfg.main.smtps_port = 0
296
+
297
+ // PROXY-before-TLS takes slightly longer than the default 10 ms timeout on Windows,
298
+ // use 50 ms timeout to avoid flaky tests (default is 300000 ms).
299
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 50)
300
+ const tlsErrors = []
301
+ let raw
302
+ let client
303
+
304
+ server.on('tlsClientError', (err) => {
305
+ tlsErrors.push(err)
306
+ })
307
+
308
+ try {
309
+ await listen(server)
310
+
311
+ raw = net.connect(server.address().port, '127.0.0.1')
312
+ await withTimeout(
313
+ Promise.race([
314
+ once(raw, 'connect'),
315
+ once(raw, 'error').then(([err]) => {
316
+ throw err
317
+ }),
318
+ ]),
319
+ 3000,
320
+ 'SMTPS TCP connection timed out',
321
+ )
322
+
323
+ raw.write('PROXY TCP4 127.0.0.1 127.0.0.1 42310 465\r\n')
324
+ client = tls.connect({
325
+ socket: raw,
326
+ rejectUnauthorized: false,
327
+ servername: 'localhost',
328
+ })
329
+
330
+ await withTimeout(
331
+ Promise.race([
332
+ once(client, 'secureConnect'),
333
+ once(client, 'error').then(([err]) => {
334
+ throw err
335
+ }),
336
+ ]),
337
+ 3000,
338
+ 'SMTPS PROXY handshake timed out',
339
+ )
340
+ const [banner] = await withTimeout(once(client, 'data'), 3000, 'SMTPS PROXY banner timed out')
341
+ assert.match(banner.toString(), /^220 /)
342
+ assert.equal(tlsErrors.length, 0)
343
+ } finally {
344
+ if (client) client.destroy()
345
+ else if (raw) raw.destroy()
346
+ await close(server)
347
+ restoreHaproxyConfig()
348
+ }
349
+ })
350
+
351
+ it('accepts direct SMTPS from a PROXY-allowed peer', async () => {
352
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
353
+ this.server.cfg.main.smtps_port = 0
354
+
355
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 1000)
356
+ const tlsErrors = []
357
+ let client
358
+
359
+ server.on('tlsClientError', (err) => {
360
+ tlsErrors.push(err)
361
+ })
362
+
363
+ try {
364
+ await listen(server)
365
+
366
+ client = tls.connect({
367
+ port: server.address().port,
368
+ host: '127.0.0.1',
369
+ rejectUnauthorized: false,
370
+ servername: 'localhost',
371
+ })
372
+
373
+ await withTimeout(
374
+ Promise.race([
375
+ once(client, 'secureConnect'),
376
+ once(client, 'error').then(([err]) => {
377
+ throw err
378
+ }),
379
+ ]),
380
+ 3000,
381
+ 'direct SMTPS handshake timed out',
382
+ )
383
+ const [banner] = await withTimeout(once(client, 'data'), 3000, 'direct SMTPS banner timed out')
384
+ assert.match(banner.toString(), /^220 /)
385
+ assert.equal(tlsErrors.length, 0)
386
+ } finally {
387
+ if (client) client.destroy()
388
+ await close(server)
389
+ restoreHaproxyConfig()
390
+ }
391
+ })
392
+
393
+ it('preserves TLS server events for SMTPS connections', async () => {
394
+ this.server.cfg.main.smtps_port = 0
395
+
396
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
397
+ let ocspRequests = 0
398
+ let first
399
+ let second
400
+
401
+ server.tlsServer.on('OCSPRequest', (cert, issuer, cb) => {
402
+ ocspRequests++
403
+ cb()
404
+ })
405
+
406
+ try {
407
+ await listen(server)
408
+
409
+ first = tls.connect({
410
+ port: server.address().port,
411
+ host: '127.0.0.1',
412
+ rejectUnauthorized: false,
413
+ requestOCSP: true,
414
+ servername: 'localhost',
415
+ maxVersion: 'TLSv1.2',
416
+ })
417
+
418
+ await withTimeout(
419
+ Promise.race([
420
+ once(first, 'secureConnect'),
421
+ once(first, 'error').then(([err]) => {
422
+ throw err
423
+ }),
424
+ ]),
425
+ 3000,
426
+ 'first SMTPS handshake timed out',
427
+ )
428
+ const session = first.getSession()
429
+ first.destroy()
430
+ await withTimeout(once(first, 'close'), 3000, 'first SMTPS close timed out')
431
+
432
+ second = tls.connect({
433
+ port: server.address().port,
434
+ host: '127.0.0.1',
435
+ rejectUnauthorized: false,
436
+ requestOCSP: true,
437
+ servername: 'localhost',
438
+ maxVersion: 'TLSv1.2',
439
+ session,
440
+ })
441
+
442
+ await withTimeout(
443
+ Promise.race([
444
+ once(second, 'secureConnect'),
445
+ once(second, 'error').then(([err]) => {
446
+ throw err
447
+ }),
448
+ ]),
449
+ 3000,
450
+ 'resumed SMTPS handshake timed out',
451
+ )
452
+
453
+ assert.equal(ocspRequests, 1)
454
+ assert.equal(second.isSessionReused(), true)
455
+ } finally {
456
+ if (second) second.destroy()
457
+ if (first) first.destroy()
458
+ await close(server)
459
+ }
460
+ })
461
+
462
+ it('uses direct TLS for SMTPS when HAProxy support is disabled', async () => {
463
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_disabled')
464
+ this.server.cfg.main.smtps_port = 0
465
+
466
+ let server
467
+ let client
468
+
469
+ try {
470
+ server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
471
+ assert.equal(server.tlsServer, undefined)
472
+
473
+ await listen(server)
474
+
475
+ client = tls.connect({
476
+ port: server.address().port,
477
+ host: '127.0.0.1',
478
+ rejectUnauthorized: false,
479
+ servername: 'localhost',
480
+ })
481
+
482
+ await withTimeout(
483
+ Promise.race([
484
+ once(client, 'secureConnect'),
485
+ once(client, 'error').then(([err]) => {
486
+ throw err
487
+ }),
488
+ ]),
489
+ 3000,
490
+ 'direct TLS fallback handshake timed out',
491
+ )
492
+ } finally {
493
+ if (client) client.destroy()
494
+ if (server) await close(server)
495
+ restoreHaproxyConfig()
496
+ }
497
+ })
498
+
499
+ it('accepts direct SMTPS from an untrusted PROXY peer', async () => {
500
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_untrusted')
501
+ this.server.cfg.main.smtps_port = 0
502
+
503
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
504
+ let client
505
+
506
+ try {
507
+ await listen(server)
508
+
509
+ client = tls.connect({
510
+ port: server.address().port,
511
+ host: '127.0.0.1',
512
+ rejectUnauthorized: false,
513
+ servername: 'localhost',
514
+ })
515
+
516
+ await withTimeout(
517
+ Promise.race([
518
+ once(client, 'secureConnect'),
519
+ once(client, 'error').then(([err]) => {
520
+ throw err
521
+ }),
522
+ ]),
523
+ 3000,
524
+ 'untrusted direct SMTPS handshake timed out',
525
+ )
526
+ } finally {
527
+ if (client) client.destroy()
528
+ await close(server)
529
+ restoreHaproxyConfig()
530
+ }
531
+ })
532
+
533
+ it('rejects malformed SMTPS PROXY lines before TLS', async () => {
534
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
535
+ this.server.cfg.main.smtps_port = 0
536
+
537
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
538
+ let raw
539
+
540
+ try {
541
+ await listen(server)
542
+
543
+ raw = net.connect(server.address().port, '127.0.0.1')
544
+ await withTimeout(once(raw, 'connect'), 3000, 'malformed PROXY TCP connection timed out')
545
+ raw.write('PROXY TCP4 nope 127.0.0.1 42310 465\r\n')
546
+
547
+ const [response] = await withTimeout(once(raw, 'data'), 3000, 'malformed PROXY response timed out')
548
+ assert.match(response.toString(), /^421 Invalid PROXY format/)
549
+ } finally {
550
+ if (raw) raw.destroy()
551
+ await close(server)
552
+ restoreHaproxyConfig()
553
+ }
554
+ })
555
+
556
+ it('rejects oversized SMTPS PROXY lines before TLS', async () => {
557
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
558
+ this.server.cfg.main.smtps_port = 0
559
+
560
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
561
+ let raw
562
+
563
+ try {
564
+ await listen(server)
565
+
566
+ raw = net.connect(server.address().port, '127.0.0.1')
567
+ await withTimeout(once(raw, 'connect'), 3000, 'oversized PROXY TCP connection timed out')
568
+ raw.write(`PROXY ${'x'.repeat(513)}`)
569
+
570
+ const [response] = await withTimeout(once(raw, 'data'), 3000, 'oversized PROXY response timed out')
571
+ assert.match(response.toString(), /^421 Invalid PROXY format/)
572
+ } finally {
573
+ if (raw) raw.destroy()
574
+ await close(server)
575
+ restoreHaproxyConfig()
576
+ }
577
+ })
578
+
579
+ it('times out waiting for SMTPS PROXY from an allowed peer', async () => {
580
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
581
+ const originalSetTimeout = global.setTimeout
582
+ global.setTimeout = (fn, ms, ...args) => originalSetTimeout(fn, ms === 30 * 1000 ? 20 : ms, ...args)
583
+ this.server.cfg.main.smtps_port = 0
584
+
585
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 10)
586
+ let raw
587
+
588
+ try {
589
+ await listen(server)
590
+
591
+ raw = net.connect(server.address().port, '127.0.0.1')
592
+ await withTimeout(once(raw, 'connect'), 3000, 'PROXY timeout TCP connection timed out')
593
+
594
+ const [response] = await withTimeout(once(raw, 'data'), 3000, 'PROXY timeout response timed out')
595
+ assert.match(response.toString(), /^421 PROXY timeout/)
596
+ } finally {
597
+ global.setTimeout = originalSetTimeout
598
+ if (raw) raw.destroy()
599
+ await close(server)
600
+ restoreHaproxyConfig()
601
+ }
602
+ })
603
+
604
+ it('accepts byte-by-byte direct SMTPS from a PROXY-allowed peer', async () => {
605
+ const restoreHaproxyConfig = useHaproxyFixture(this.server, 'haproxy_allowed')
606
+ this.server.cfg.main.smtps_port = 0
607
+
608
+ const server = await this.server.get_smtp_server(endpoint('127.0.0.1:0'), 1000)
609
+ let raw
610
+ let client
611
+
612
+ try {
613
+ await listen(server)
614
+
615
+ raw = net.connect(server.address().port, '127.0.0.1')
616
+ await withTimeout(once(raw, 'connect'), 3000, 'fragmented direct SMTPS TCP connection timed out')
617
+
618
+ const write = raw.write.bind(raw)
619
+ raw.write = (chunk, encoding, cb) => {
620
+ if (typeof encoding === 'function') {
621
+ cb = encoding
622
+ encoding = undefined
623
+ }
624
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)
625
+ let pos = 0
626
+ const write_next = () => {
627
+ if (pos >= buffer.length) {
628
+ if (cb) cb()
629
+ return
630
+ }
631
+ write(buffer.subarray(pos, pos + 1))
632
+ pos++
633
+ setImmediate(write_next)
634
+ }
635
+ write_next()
636
+ return true
637
+ }
638
+
639
+ client = tls.connect({
640
+ socket: raw,
641
+ rejectUnauthorized: false,
642
+ servername: 'localhost',
643
+ })
644
+
645
+ await withTimeout(
646
+ Promise.race([
647
+ once(client, 'secureConnect'),
648
+ once(client, 'error').then(([err]) => {
649
+ throw err
650
+ }),
651
+ ]),
652
+ 3000,
653
+ 'fragmented direct SMTPS handshake timed out',
654
+ )
655
+ const [banner] = await withTimeout(
656
+ once(client, 'data'),
657
+ 3000,
658
+ 'fragmented direct SMTPS banner timed out',
659
+ )
660
+ assert.match(banner.toString(), /^220 /)
661
+ } finally {
662
+ if (client) client.destroy()
663
+ else if (raw) raw.destroy()
664
+ await close(server)
665
+ restoreHaproxyConfig()
666
+ }
667
+ })
244
668
  })
245
669
 
246
670
  // ── get_http_docroot ──────────────────────────────────────────────────────
@@ -5,7 +5,7 @@ const assert = require('node:assert/strict')
5
5
  const { PassThrough } = require('node:stream')
6
6
  const path = require('node:path')
7
7
 
8
- const { Address } = require('../address')
8
+ const { Address } = require('@haraka/email-address')
9
9
  const fixtures = require('haraka-test-fixtures')
10
10
  const net_utils = require('haraka-net-utils')
11
11
  const message = require('haraka-email-message')
@@ -57,19 +57,18 @@ function restoreTlsConnect() {
57
57
  }
58
58
 
59
59
  function makeConnection(overrides = {}) {
60
- const conn = fixtures.connection.createConnection()
60
+ const conn = fixtures.makeConnection({ ip: '1.2.3.4' })
61
61
  conn.server = { notes: {} }
62
62
  conn.hello = { host: 'client.example.com' }
63
63
  conn.local = { host: 'relay.example.com' }
64
- conn.remote = { ip: '1.2.3.4' }
65
64
  conn.transaction = null
66
65
  return Object.assign(conn, overrides)
67
66
  }
68
67
 
69
68
  function makePlugin() {
70
- const p = new fixtures.plugin('queue/smtp_forward')
71
- p.config = p.config.module_config(path.resolve('test'))
72
- p.register()
69
+ const p = fixtures.makePlugin('queue/smtp_forward', {
70
+ configDir: path.resolve('test'),
71
+ })
73
72
  p.tls_options = {}
74
73
  return p
75
74
  }
@@ -228,7 +227,7 @@ describe('SMTPClient line handler', () => {
228
227
  client.command = 'starttls'
229
228
  client.tls_options = { servername: 'mx.example.com' }
230
229
  let upgradeCalled = false
231
- client.socket.upgrade = (opts, cb) => {
230
+ client.socket.upgrade = () => {
232
231
  upgradeCalled = true
233
232
  }
234
233
  client.socket.emit('line', '220 Go ahead\r\n')
@@ -249,10 +248,7 @@ describe('SMTPClient line handler', () => {
249
248
  it('returns early after bad_code when state is not ACTIVE', () => {
250
249
  client.command = 'mail'
251
250
  client.state = STATE.IDLE
252
- let heloFired = false
253
- client.on('helo', () => {
254
- heloFired = true
255
- }) // shouldn't fire
251
+ client.on('helo', () => {}) // shouldn't fire
256
252
  let badCodeFired = false
257
253
  client.on('bad_code', () => {
258
254
  badCodeFired = true
@@ -344,7 +340,7 @@ describe('SMTPClient socket connect event', () => {
344
340
  socket.setTimeout = (ms) => {
345
341
  lastTimeout = ms
346
342
  }
347
- const client = makeClient({ socket, idle_timeout: 120 })
343
+ makeClient({ socket, idle_timeout: 120 })
348
344
  socket.emit('connect')
349
345
  assert.equal(lastTimeout, 120_000)
350
346
  })
@@ -513,7 +509,7 @@ describe('SMTPClient#start_data', () => {
513
509
  const client = makeClient()
514
510
  let pipeTarget = null
515
511
  const mockStream = {
516
- pipe: (dest, opts) => {
512
+ pipe: (dest) => {
517
513
  pipeTarget = dest
518
514
  },
519
515
  }
@@ -591,7 +587,7 @@ describe('SMTPClient#upgrade', () => {
591
587
  it('delegates to socket.upgrade with tls_options', () => {
592
588
  const socket = makeSocket()
593
589
  let upgradeOpts = null
594
- socket.upgrade = (opts, cb) => {
590
+ socket.upgrade = (opts) => {
595
591
  upgradeOpts = opts
596
592
  }
597
593
  const client = makeClient({ socket })
@@ -964,7 +960,7 @@ describe('smtp_client.get_client_plugin', () => {
964
960
  })
965
961
 
966
962
  it('reuses existing host_pool from server.notes', async () => {
967
- const HostPool = require('../host_pool')
963
+ const { HostPool } = require('haraka-net-utils')
968
964
  const pool = new HostPool('10.0.0.3:25')
969
965
  conn.server.notes.host_pool = pool
970
966
  await getClientPlugin({ forwarding_host_pool: '10.0.0.3:25' })
@@ -1021,7 +1017,6 @@ describe('smtp_client.get_client_plugin', () => {
1021
1017
  return s
1022
1018
  }
1023
1019
 
1024
- const written = []
1025
1020
  const mockPlugin = makePlugin()
1026
1021
 
1027
1022
  smtp_client_module.get_client_plugin(
@@ -1257,8 +1252,6 @@ describe('smtp_client full session (auth)', () => {
1257
1252
 
1258
1253
  describe('smtp_client', () => {
1259
1254
  it('testUpgradeIsCalledOnSTARTTLS', () => {
1260
- const plugin = makePlugin()
1261
-
1262
1255
  const cmds = {}
1263
1256
  let upgradeArgs = {}
1264
1257
 
@@ -8,9 +8,6 @@ const tls = require('node:tls')
8
8
  const fs = require('node:fs')
9
9
  const { EventEmitter } = require('node:events')
10
10
 
11
- // Mock dependencies before requiring the target
12
- const mock = require('node:test').mock
13
-
14
11
  const tls_socket = require('../tls_socket')
15
12
 
16
13
  const TEST_CERT = fs.readFileSync(path.join(__dirname, 'config/tls_cert.pem'))
@@ -55,12 +52,12 @@ test('tls_socket', async (t) => {
55
52
  })
56
53
  })
57
54
 
58
- await t.test('pluggableStream', async (t) => {
55
+ await t.test('pluggableStream', async () => {
59
56
  // This is a class inside the file, but not exported.
60
57
  // We can test it via createServer or connect if we mock net.
61
58
  })
62
59
 
63
- await t.test('connect', async (t) => {
60
+ await t.test('connect', async () => {
64
61
  // Exercise the `new tls.connect` bug
65
62
  // We can't easily catch the 'new' keyword usage without proxying tls.connect
66
63
  assert.strictEqual(typeof tls_socket.connect, 'function')
@@ -141,7 +138,7 @@ test('tls_socket', async (t) => {
141
138
  })
142
139
  })
143
140
 
144
- await t.test('getSocketOpts', async (t) => {
141
+ await t.test('getSocketOpts', async () => {
145
142
  // Exercise the typo path (would requires failing config.getDir)
146
143
  assert.strictEqual(typeof tls_socket.getSocketOpts, 'function')
147
144
  })
package/tls_socket.js CHANGED
@@ -95,7 +95,7 @@ class pluggableStream extends stream.Stream {
95
95
  }
96
96
  }
97
97
 
98
- clean(data) {
98
+ clean() {
99
99
  if (this.targetsocket?.removeAllListeners) {
100
100
  for (const name of ['data', 'secure', 'secureConnect', 'end', 'close', 'error', 'drain']) {
101
101
  this.targetsocket.removeAllListeners(name)
@@ -540,7 +540,7 @@ exports.getSocketOpts = async (name) => {
540
540
  function pipe(cleartext, socket) {
541
541
  cleartext.socket = socket
542
542
 
543
- function onError(e) {}
543
+ function onError() {}
544
544
 
545
545
  function onClose() {
546
546
  socket.removeListener('error', onError)
@@ -570,7 +570,7 @@ exports.ensureDhparams = (done) => {
570
570
  log.debug(data)
571
571
  })
572
572
 
573
- o.stderr.on('data', (data) => {
573
+ o.stderr.on('data', () => {
574
574
  // this is the status gibberish `openssl dhparam` spews as it works
575
575
  })
576
576
 
package/transaction.js CHANGED
@@ -45,7 +45,7 @@ class Transaction {
45
45
  if (this.body) return
46
46
 
47
47
  this.body = new message.Body(this.header)
48
- this.body.on('mime_boundary', (m) => this.incr_mime_count())
48
+ this.body.on('mime_boundary', () => this.incr_mime_count())
49
49
 
50
50
  for (const hook of this.attachment_start_hooks) {
51
51
  this.body.on('attachment_start', hook)
@@ -226,7 +226,7 @@ class Transaction {
226
226
  if (this.found_hb_sep) this.reset_headers()
227
227
  }
228
228
 
229
- attachment_hooks(start, data, end) {
229
+ attachment_hooks(start) {
230
230
  this.parse_body = true
231
231
  this.attachment_start_hooks.push(start)
232
232
  }
@@ -255,7 +255,7 @@ class Transaction {
255
255
  }
256
256
  }
257
257
 
258
- incr_mime_count(line) {
258
+ incr_mime_count() {
259
259
  this.mime_part_count++
260
260
  }
261
261
  }