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
@@ -4,6 +4,7 @@ const assert = require('node:assert/strict')
4
4
  const { describe, it, beforeEach } = require('node:test')
5
5
 
6
6
  const fixtures = require('haraka-test-fixtures')
7
+ const { makeConnection, makePlugin } = fixtures
7
8
  const Notes = require('haraka-notes')
8
9
 
9
10
  function makeServer(extra = {}) {
@@ -30,13 +31,14 @@ describe('process_title', () => {
30
31
  let plugin
31
32
 
32
33
  beforeEach(() => {
33
- plugin = new fixtures.plugin('process_title')
34
+ plugin = makePlugin('process_title', { register: false })
34
35
  })
35
36
 
36
37
  describe('hook_connect_init', () => {
37
38
  it('increments connection and concurrent counts', (t, done) => {
38
39
  const server = makeServer()
39
- const conn = fixtures.connection.createConnection({}, server)
40
+ const conn = makeConnection()
41
+ conn.server = server
40
42
  plugin.hook_connect_init((rc) => {
41
43
  assert.equal(rc, undefined)
42
44
  assert.equal(server.notes.pt_connections, 1)
@@ -50,7 +52,8 @@ describe('process_title', () => {
50
52
  describe('hook_disconnect', () => {
51
53
  it('decrements concurrent count when connect_init ran', (t, done) => {
52
54
  const server = makeServer({ pt_connections: 1, pt_concurrent: 1 })
53
- const conn = fixtures.connection.createConnection({}, server)
55
+ const conn = makeConnection()
56
+ conn.server = server
54
57
  conn.notes.pt_connect_run = true
55
58
  plugin.hook_disconnect((rc) => {
56
59
  assert.equal(rc, undefined)
@@ -62,7 +65,8 @@ describe('process_title', () => {
62
65
 
63
66
  it('increments connection count when connect_init did not run', (t, done) => {
64
67
  const server = makeServer({ pt_connections: 0, pt_concurrent: 0 })
65
- const conn = fixtures.connection.createConnection({}, server)
68
+ const conn = makeConnection()
69
+ conn.server = server
66
70
  // pt_connect_run is NOT set: disconnect does connect bookkeeping then decrements
67
71
  plugin.hook_disconnect((rc) => {
68
72
  assert.equal(rc, undefined)
@@ -76,7 +80,8 @@ describe('process_title', () => {
76
80
  describe('hook_rcpt', () => {
77
81
  it('increments recipient count', (t, done) => {
78
82
  const server = makeServer()
79
- const conn = fixtures.connection.createConnection({}, server)
83
+ const conn = makeConnection()
84
+ conn.server = server
80
85
  plugin.hook_rcpt((rc) => {
81
86
  assert.equal(rc, undefined)
82
87
  assert.equal(server.notes.pt_recipients, 1)
@@ -88,7 +93,8 @@ describe('process_title', () => {
88
93
  describe('hook_data', () => {
89
94
  it('increments message count', (t, done) => {
90
95
  const server = makeServer()
91
- const conn = fixtures.connection.createConnection({}, server)
96
+ const conn = makeConnection()
97
+ conn.server = server
92
98
  plugin.hook_data((rc) => {
93
99
  assert.equal(rc, undefined)
94
100
  assert.equal(server.notes.pt_messages, 1)
@@ -5,7 +5,7 @@ const path = require('node:path')
5
5
  const Module = require('node:module')
6
6
  const { describe, it, beforeEach, before, after } = require('node:test')
7
7
 
8
- const fixtures = require('haraka-test-fixtures')
8
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
9
9
 
10
10
  // deliver.js does `require('./outbound')` at the top level. In a running
11
11
  // Haraka that resolves to the core outbound module (Haraka/outbound/index.js),
@@ -40,9 +40,8 @@ after(() => {
40
40
  delete require.cache[outboundPath]
41
41
  })
42
42
 
43
- function makeConnection(opts = {}) {
44
- const conn = fixtures.connection.createConnection()
45
- conn.init_transaction()
43
+ function buildConnection(opts = {}) {
44
+ const conn = makeConnection({ withTxn: true })
46
45
  if (opts.relaying !== undefined) conn.relaying = opts.relaying
47
46
  return conn
48
47
  }
@@ -52,12 +51,12 @@ describe('queue/deliver', () => {
52
51
  let plugin, conn
53
52
 
54
53
  beforeEach(() => {
55
- plugin = new fixtures.plugin('queue/deliver')
54
+ plugin = makePlugin('queue/deliver')
56
55
  mockOutbound.send_trans_email = () => {}
57
56
  })
58
57
 
59
58
  it('calls next() when connection is not relaying', (t, done) => {
60
- conn = makeConnection({ relaying: false })
59
+ conn = buildConnection({ relaying: false })
61
60
  plugin.hook_queue_outbound((rc) => {
62
61
  assert.equal(rc, undefined)
63
62
  done()
@@ -72,7 +71,7 @@ describe('queue/deliver', () => {
72
71
  })
73
72
 
74
73
  it('calls outbound.send_trans_email when relaying is true', (t, done) => {
75
- conn = makeConnection({ relaying: true })
74
+ conn = buildConnection({ relaying: true })
76
75
  mockOutbound.send_trans_email = (txn, next) => {
77
76
  assert.equal(txn, conn.transaction)
78
77
  next(OK)
@@ -84,7 +83,7 @@ describe('queue/deliver', () => {
84
83
  })
85
84
 
86
85
  it('passes transaction to outbound.send_trans_email', (t, done) => {
87
- conn = makeConnection({ relaying: true })
86
+ conn = buildConnection({ relaying: true })
88
87
  let capturedTxn
89
88
  mockOutbound.send_trans_email = (txn, next) => {
90
89
  capturedTxn = txn
@@ -3,7 +3,7 @@
3
3
  const assert = require('node:assert')
4
4
  const { describe, it, beforeEach, before } = require('node:test')
5
5
 
6
- const fixtures = require('haraka-test-fixtures')
6
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
7
7
 
8
8
  before(() => {
9
9
  require('haraka-constants').import(global)
@@ -14,9 +14,8 @@ describe('queue/discard', () => {
14
14
  let plugin, conn
15
15
 
16
16
  beforeEach(() => {
17
- plugin = new fixtures.plugin('queue/discard')
18
- conn = fixtures.connection.createConnection()
19
- conn.init_transaction()
17
+ plugin = makePlugin('queue/discard')
18
+ conn = makeConnection({ withTxn: true })
20
19
  delete process.env.YES_REALLY_DO_DISCARD
21
20
  })
22
21
 
@@ -3,7 +3,7 @@
3
3
  const assert = require('node:assert')
4
4
  const { describe, it, beforeEach, before } = require('node:test')
5
5
 
6
- const fixtures = require('haraka-test-fixtures')
6
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
7
7
 
8
8
  before(() => {
9
9
  require('haraka-constants').import(global)
@@ -14,7 +14,7 @@ describe('queue/lmtp', () => {
14
14
  let plugin
15
15
 
16
16
  beforeEach(() => {
17
- plugin = new fixtures.plugin('queue/lmtp')
17
+ plugin = makePlugin('queue/lmtp', { register: false })
18
18
  plugin.load_lmtp_ini()
19
19
  })
20
20
 
@@ -113,14 +113,13 @@ describe('queue/lmtp', () => {
113
113
  let plugin, conn
114
114
 
115
115
  beforeEach(() => {
116
- plugin = new fixtures.plugin('queue/lmtp')
116
+ plugin = makePlugin('queue/lmtp', { register: false })
117
117
  plugin.load_lmtp_ini()
118
- conn = fixtures.connection.createConnection()
119
- conn.init_transaction()
118
+ conn = makeConnection({ withTxn: true })
120
119
  })
121
120
 
122
121
  it('calls next() when there is no transaction', (t, done) => {
123
- const connNoTxn = fixtures.connection.createConnection()
122
+ const connNoTxn = makeConnection()
124
123
  plugin.hook_queue((rc) => {
125
124
  assert.equal(rc, undefined)
126
125
  done()
@@ -3,7 +3,7 @@
3
3
  const assert = require('node:assert')
4
4
  const { describe, it, beforeEach, before } = require('node:test')
5
5
 
6
- const fixtures = require('haraka-test-fixtures')
6
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
7
7
 
8
8
  before(() => {
9
9
  require('haraka-constants').import(global)
@@ -12,14 +12,14 @@ before(() => {
12
12
  describe('queue/qmail-queue', () => {
13
13
  describe('register', () => {
14
14
  it('throws when qmail-queue binary is not found', () => {
15
- const plugin = new fixtures.plugin('queue/qmail-queue')
15
+ const plugin = makePlugin('queue/qmail-queue', { register: false })
16
16
  assert.throws(() => plugin.register(), /Cannot find qmail-queue binary/)
17
17
  })
18
18
  })
19
19
 
20
20
  describe('load_qmail_queue_ini', () => {
21
21
  it('loads config with enable_outbound boolean', () => {
22
- const plugin = new fixtures.plugin('queue/qmail-queue')
22
+ const plugin = makePlugin('queue/qmail-queue', { register: false })
23
23
  plugin.load_qmail_queue_ini()
24
24
  assert.ok(typeof plugin.cfg.main.enable_outbound === 'boolean')
25
25
  })
@@ -29,15 +29,14 @@ describe('queue/qmail-queue', () => {
29
29
  let plugin, conn
30
30
 
31
31
  beforeEach(() => {
32
- plugin = new fixtures.plugin('queue/qmail-queue')
32
+ plugin = makePlugin('queue/qmail-queue', { register: false })
33
33
  plugin.load_qmail_queue_ini()
34
34
  plugin.queue_exec = '/bin/echo' // use a real binary that exists
35
- conn = fixtures.connection.createConnection()
36
- conn.init_transaction()
35
+ conn = makeConnection({ withTxn: true })
37
36
  })
38
37
 
39
38
  it('calls next() when there is no transaction', (t, done) => {
40
- const connNoTxn = fixtures.connection.createConnection()
39
+ const connNoTxn = makeConnection()
41
40
  plugin.hook_queue((rc) => {
42
41
  assert.equal(rc, undefined)
43
42
  done()
@@ -64,7 +63,7 @@ describe('queue/qmail-queue', () => {
64
63
  describe('build_envelope', () => {
65
64
  let plugin
66
65
  beforeEach(() => {
67
- plugin = new fixtures.plugin('queue/qmail-queue')
66
+ plugin = makePlugin('queue/qmail-queue', { register: false })
68
67
  })
69
68
 
70
69
  it('formats F<sender>\\0(T<rcpt>\\0)*\\0 with no padding', () => {
@@ -3,13 +3,13 @@
3
3
  const assert = require('node:assert')
4
4
  const { describe, it, beforeEach } = require('node:test')
5
5
 
6
- const fixtures = require('haraka-test-fixtures')
6
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
7
7
 
8
8
  describe('queue/quarantine', () => {
9
9
  let plugin
10
10
 
11
11
  beforeEach(() => {
12
- plugin = new fixtures.plugin('queue/quarantine')
12
+ plugin = makePlugin('queue/quarantine', { register: false })
13
13
  plugin.load_quarantine_ini()
14
14
  })
15
15
 
@@ -51,8 +51,7 @@ describe('queue/quarantine', () => {
51
51
  let conn
52
52
 
53
53
  beforeEach(() => {
54
- conn = fixtures.connection.createConnection()
55
- conn.init_transaction()
54
+ conn = makeConnection({ withTxn: true })
56
55
  })
57
56
 
58
57
  it('calls next() when no quarantine conditions are met', (t, done) => {
@@ -3,7 +3,7 @@
3
3
  const assert = require('node:assert')
4
4
  const { describe, it, beforeEach, before } = require('node:test')
5
5
 
6
- const fixtures = require('haraka-test-fixtures')
6
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
7
7
 
8
8
  before(() => {
9
9
  require('haraka-constants').import(global)
@@ -14,14 +14,13 @@ describe('queue/smtp_bridge', () => {
14
14
  let plugin, conn
15
15
 
16
16
  beforeEach(() => {
17
- plugin = new fixtures.plugin('queue/smtp_bridge')
17
+ plugin = makePlugin('queue/smtp_bridge')
18
18
  plugin.load_flat_ini()
19
- conn = fixtures.connection.createConnection()
20
- conn.init_transaction()
19
+ conn = makeConnection({ withTxn: true })
21
20
  })
22
21
 
23
22
  it('calls next() when no transaction', (t, done) => {
24
- const connNoTxn = fixtures.connection.createConnection()
23
+ const connNoTxn = makeConnection()
25
24
  plugin.hook_data_post((rc) => {
26
25
  assert.equal(rc, undefined)
27
26
  done()
@@ -60,8 +59,7 @@ describe('queue/smtp_bridge', () => {
60
59
  let plugin
61
60
 
62
61
  beforeEach(() => {
63
- plugin = new fixtures.plugin('queue/smtp_bridge')
64
- plugin.load_flat_ini()
62
+ plugin = makePlugin('queue/smtp_bridge')
65
63
  })
66
64
 
67
65
  it('returns OK with default priority 10 and configured host', (t, done) => {
@@ -5,8 +5,8 @@ const assert = require('node:assert/strict')
5
5
  const { EventEmitter } = require('node:events')
6
6
  const path = require('node:path')
7
7
 
8
- const { Address } = require('../../../address')
9
- const fixtures = require('haraka-test-fixtures')
8
+ const { Address } = require('@haraka/email-address')
9
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
10
10
  const Notes = require('haraka-notes')
11
11
 
12
12
  // Haraka result codes (haraka-constants)
@@ -16,21 +16,8 @@ const DENYSOFT = 903
16
16
 
17
17
  // ─── Helpers ──────────────────────────────────────────────────────────────────
18
18
 
19
- function makePlugin() {
20
- const p = new fixtures.plugin('queue/smtp_forward')
21
- p.config = p.config.module_config(path.resolve('test'))
22
- p.register()
23
- // Deep-clone cfg to prevent shared haraka-config reference mutations across tests
24
- p.cfg = JSON.parse(JSON.stringify(p.cfg))
25
- return p
26
- }
27
-
28
- function makeConnection() {
29
- const conn = fixtures.connection.createConnection()
30
- conn.init_transaction()
31
- conn.server = { notes: {} }
32
- return conn
33
- }
19
+ // repo `test/` dir (holds config/), independent of cwd
20
+ const TEST_DIR = path.resolve(__dirname, '../..')
34
21
 
35
22
  function makeHmail(notes = {}) {
36
23
  const n = new Notes()
@@ -68,7 +55,7 @@ class MockSMTPClient extends EventEmitter {
68
55
  this.commands.push(data !== undefined ? `${cmd} ${data}` : cmd)
69
56
  }
70
57
 
71
- start_data(stream) {
58
+ start_data() {
72
59
  this.started = true
73
60
  }
74
61
  }
@@ -88,18 +75,17 @@ function stubGetClientPlugin(factory) {
88
75
 
89
76
  describe('smtp_forward register', () => {
90
77
  it('registers the queue hook', () => {
91
- const plugin = makePlugin()
78
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
92
79
  assert.ok(plugin.hooks.queue)
93
80
  })
94
81
 
95
82
  it('registers the get_mx hook', () => {
96
- const plugin = makePlugin()
83
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
97
84
  assert.ok(plugin.hooks.get_mx)
98
85
  })
99
86
 
100
87
  it('registers check_sender hook when check_sender=true', () => {
101
- const plugin = new fixtures.plugin('queue/smtp_forward')
102
- plugin.config = plugin.config.module_config(path.resolve('test'))
88
+ const plugin = makePlugin('queue/smtp_forward', { register: false, configDir: TEST_DIR })
103
89
  plugin.load_smtp_forward_ini = function () {
104
90
  this.cfg = {
105
91
  main: { check_sender: true, check_recipient: true, enable_outbound: true, host: 'localhost', port: 25 },
@@ -110,8 +96,7 @@ describe('smtp_forward register', () => {
110
96
  })
111
97
 
112
98
  it('registers check_recipient hook when check_recipient=true', () => {
113
- const plugin = new fixtures.plugin('queue/smtp_forward')
114
- plugin.config = plugin.config.module_config(path.resolve('test'))
99
+ const plugin = makePlugin('queue/smtp_forward', { register: false, configDir: TEST_DIR })
115
100
  plugin.load_smtp_forward_ini = function () {
116
101
  this.cfg = { main: { check_recipient: true, host: 'localhost', port: 25 } }
117
102
  }
@@ -120,8 +105,7 @@ describe('smtp_forward register', () => {
120
105
  })
121
106
 
122
107
  it('registers queue_outbound hook when enable_outbound=true', () => {
123
- const plugin = new fixtures.plugin('queue/smtp_forward')
124
- plugin.config = plugin.config.module_config(path.resolve('test'))
108
+ const plugin = makePlugin('queue/smtp_forward', { register: false, configDir: TEST_DIR })
125
109
  plugin.load_smtp_forward_ini = function () {
126
110
  this.cfg = { main: { enable_outbound: true, host: 'localhost', port: 25 } }
127
111
  }
@@ -130,8 +114,7 @@ describe('smtp_forward register', () => {
130
114
  })
131
115
 
132
116
  it('aborts registration when load_errs is non-empty', () => {
133
- const plugin = new fixtures.plugin('queue/smtp_forward')
134
- plugin.config = plugin.config.module_config(path.resolve('test'))
117
+ const plugin = makePlugin('queue/smtp_forward', { register: false, configDir: TEST_DIR })
135
118
  plugin.load_smtp_forward_ini = function () {
136
119
  this.cfg = { main: {} }
137
120
  this.load_errs.push('simulated error')
@@ -141,7 +124,7 @@ describe('smtp_forward register', () => {
141
124
  })
142
125
 
143
126
  it('populates tls_options after register (no-op shape)', () => {
144
- const plugin = makePlugin()
127
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
145
128
  assert.ok(plugin.tls_options, 'tls_options should be populated after register')
146
129
  assert.ok(Array.isArray(plugin.tls_options.no_tls_hosts))
147
130
  assert.ok(Array.isArray(plugin.tls_options.force_tls_hosts))
@@ -158,7 +141,7 @@ describe('smtp_forward tls_options', () => {
158
141
  // Redirect tls_socket.config at test/config so tls.ini fixtures load.
159
142
  origTlsConfig = tls_socket.config
160
143
  origTlsCfg = tls_socket.cfg
161
- tls_socket.config = require('haraka-config').module_config(path.resolve('test'))
144
+ tls_socket.config = require('haraka-config').module_config(TEST_DIR)
162
145
  tls_socket.cfg = undefined
163
146
  })
164
147
 
@@ -168,14 +151,14 @@ describe('smtp_forward tls_options', () => {
168
151
  })
169
152
 
170
153
  it('inherits rejectUnauthorized/minVersion/ciphers from tls.ini [main]', () => {
171
- const plugin = makePlugin()
154
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
172
155
  assert.equal(plugin.tls_options.rejectUnauthorized, false)
173
156
  assert.equal(plugin.tls_options.minVersion, 'TLSv1')
174
157
  assert.ok(plugin.tls_options.ciphers)
175
158
  })
176
159
 
177
160
  it('reload re-derives tls_options', () => {
178
- const plugin = makePlugin()
161
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
179
162
  const first = plugin.tls_options
180
163
  plugin.load_smtp_forward_ini()
181
164
  assert.ok(plugin.tls_options)
@@ -188,14 +171,14 @@ describe('smtp_forward tls_options', () => {
188
171
 
189
172
  describe('smtp_forward load_smtp_forward_ini', () => {
190
173
  it('loads configuration from ini file', () => {
191
- const plugin = makePlugin()
174
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
192
175
  assert.ok(plugin.cfg.main)
193
176
  assert.equal(plugin.cfg.main.host, 'localhost')
194
177
  })
195
178
 
196
179
  it('sets up a reload callback', () => {
197
180
  // Calling load_smtp_forward_ini again should not crash
198
- const plugin = makePlugin()
181
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
199
182
  assert.doesNotThrow(() => plugin.load_smtp_forward_ini())
200
183
  assert.ok(plugin.cfg.main)
201
184
  })
@@ -207,8 +190,9 @@ describe('smtp_forward get_config', () => {
207
190
  let plugin, connection
208
191
 
209
192
  beforeEach(() => {
210
- plugin = makePlugin()
211
- connection = makeConnection()
193
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
194
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
195
+ connection = makeConnection({ withTxn: true })
212
196
  })
213
197
 
214
198
  it('returns main cfg when no transaction', () => {
@@ -284,8 +268,8 @@ describe('smtp_forward check_sender', () => {
284
268
  let plugin, connection
285
269
 
286
270
  beforeEach(() => {
287
- plugin = makePlugin()
288
- connection = makeConnection()
271
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
272
+ connection = makeConnection({ withTxn: true })
289
273
  })
290
274
 
291
275
  it('returns without calling next when no transaction', () => {
@@ -363,8 +347,9 @@ describe('smtp_forward set_queue', () => {
363
347
  let plugin, connection
364
348
 
365
349
  beforeEach(() => {
366
- plugin = makePlugin()
367
- connection = makeConnection()
350
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
351
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
352
+ connection = makeConnection({ withTxn: true })
368
353
  })
369
354
 
370
355
  it('returns false when transaction has no notes (no transaction)', () => {
@@ -440,8 +425,8 @@ describe('smtp_forward check_recipient', () => {
440
425
  let plugin, connection
441
426
 
442
427
  beforeEach(() => {
443
- plugin = makePlugin()
444
- connection = makeConnection()
428
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
429
+ connection = makeConnection({ withTxn: true })
445
430
  })
446
431
 
447
432
  it('returns without calling next when no transaction', () => {
@@ -532,8 +517,8 @@ describe('smtp_forward auth', () => {
532
517
  let plugin, connection, smtp_client
533
518
 
534
519
  beforeEach(() => {
535
- plugin = makePlugin()
536
- connection = makeConnection()
520
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
521
+ connection = makeConnection({ withTxn: true })
537
522
  smtp_client = new MockSMTPClient()
538
523
  })
539
524
 
@@ -603,8 +588,9 @@ describe('smtp_forward forward_enabled', () => {
603
588
  let plugin, connection
604
589
 
605
590
  beforeEach(() => {
606
- plugin = makePlugin()
607
- connection = makeConnection()
591
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
592
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
593
+ connection = makeConnection({ withTxn: true })
608
594
  })
609
595
 
610
596
  it('returns false when queue.wants is set to a non smtp_forward value', () => {
@@ -641,10 +627,12 @@ describe('smtp_forward queue_forward', () => {
641
627
  let plugin, connection, restore
642
628
 
643
629
  beforeEach(() => {
644
- plugin = makePlugin()
645
- connection = makeConnection()
646
- connection.transaction.rcpt_to = [new Address('<rcpt@example.com>')]
647
- connection.transaction.mail_from = new Address('<sender@example.com>')
630
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
631
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
632
+ connection = makeConnection({
633
+ mailFrom: '<sender@example.com>',
634
+ rcptTo: ['<rcpt@example.com>'],
635
+ })
648
636
  connection.relaying = false
649
637
  })
650
638
 
@@ -839,8 +827,7 @@ describe('smtp_forward queue_forward', () => {
839
827
 
840
828
  describe('smtp_forward get_mx_next_hop', () => {
841
829
  it('parses smtp URL with port', () => {
842
- const mx = smtp_client_mod.smtp_client // not used; just accessing exports
843
- const plugin = makePlugin()
830
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
844
831
  const mx_val = plugin.get_mx_next_hop('smtp://10.0.0.1:587')
845
832
  assert.equal(mx_val.exchange, '10.0.0.1')
846
833
  assert.equal(mx_val.port, '587')
@@ -848,20 +835,20 @@ describe('smtp_forward get_mx_next_hop', () => {
848
835
  })
849
836
 
850
837
  it('defaults port to 25 for smtp without explicit port', () => {
851
- const plugin = makePlugin()
838
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
852
839
  const mx_val = plugin.get_mx_next_hop('smtp://10.0.0.1')
853
840
  assert.equal(mx_val.port, 25)
854
841
  })
855
842
 
856
843
  it('parses lmtp URL and sets using_lmtp=true with port 24', () => {
857
- const plugin = makePlugin()
844
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
858
845
  const mx_val = plugin.get_mx_next_hop('lmtp://10.0.0.2')
859
846
  assert.equal(mx_val.using_lmtp, true)
860
847
  assert.equal(mx_val.port, 24)
861
848
  })
862
849
 
863
850
  it('extracts auth credentials from URL', () => {
864
- const plugin = makePlugin()
851
+ const plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
865
852
  const mx_val = plugin.get_mx_next_hop('smtp://user:secret@10.0.0.1:25')
866
853
  assert.equal(mx_val.auth_type, 'plain')
867
854
  assert.equal(mx_val.auth_user, 'user')
@@ -875,7 +862,8 @@ describe('smtp_forward get_mx', () => {
875
862
  let plugin, hmail
876
863
 
877
864
  beforeEach(() => {
878
- plugin = makePlugin()
865
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
866
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
879
867
  hmail = makeHmail()
880
868
  })
881
869
 
@@ -894,7 +882,7 @@ describe('smtp_forward get_mx', () => {
894
882
  it('returns no route when queue.wants is not smtp_forward or outbound', (t, done) => {
895
883
  hmail.todo.notes.set('queue.wants', 'some_other_queue')
896
884
  plugin.get_mx(
897
- (code, mx) => {
885
+ (code) => {
898
886
  assert.equal(code, undefined)
899
887
  done()
900
888
  },
@@ -936,7 +924,7 @@ describe('smtp_forward get_mx', () => {
936
924
  it('returns no route (DNS MX) for unconfigured domain when queue.wants=outbound', (t, done) => {
937
925
  hmail.todo.notes.set('queue.wants', 'outbound')
938
926
  plugin.get_mx(
939
- (code, mx) => {
927
+ (code) => {
940
928
  assert.equal(code, undefined)
941
929
  done()
942
930
  },
@@ -996,8 +984,9 @@ describe('smtp_forward is_outbound_enabled', () => {
996
984
  let plugin, connection
997
985
 
998
986
  beforeEach(() => {
999
- plugin = makePlugin()
1000
- connection = makeConnection()
987
+ plugin = makePlugin('queue/smtp_forward', { configDir: TEST_DIR })
988
+ plugin.cfg = JSON.parse(JSON.stringify(plugin.cfg))
989
+ connection = makeConnection({ withTxn: true })
1001
990
  })
1002
991
 
1003
992
  it('enable_outbound is false by default (global)', () => {
@@ -4,7 +4,7 @@ const assert = require('node:assert')
4
4
  const path = require('node:path')
5
5
  const { describe, it, beforeEach, afterEach, before } = require('node:test')
6
6
 
7
- const fixtures = require('haraka-test-fixtures')
7
+ const { makeConnection, makePlugin } = require('haraka-test-fixtures')
8
8
 
9
9
  const tls_socket = require('../../../tls_socket')
10
10
 
@@ -16,10 +16,9 @@ describe('queue/smtp_proxy', () => {
16
16
  let plugin, conn
17
17
 
18
18
  beforeEach(() => {
19
- plugin = new fixtures.plugin('queue/smtp_proxy')
19
+ plugin = makePlugin('queue/smtp_proxy', { register: false })
20
20
  plugin.load_smtp_proxy_ini()
21
- conn = fixtures.connection.createConnection()
22
- conn.init_transaction()
21
+ conn = makeConnection({ withTxn: true })
23
22
  })
24
23
 
25
24
  describe('hook_rset', () => {
@@ -37,7 +36,7 @@ describe('queue/smtp_proxy', () => {
37
36
  released = true
38
37
  },
39
38
  }
40
- plugin.hook_rset((rc) => {
39
+ plugin.hook_rset(() => {
41
40
  assert.equal(released, true)
42
41
  assert.equal(conn.notes.smtp_client, undefined)
43
42
  done()
@@ -77,7 +76,7 @@ describe('queue/smtp_proxy', () => {
77
76
  callNextCalled = true
78
77
  },
79
78
  }
80
- plugin.hook_disconnect((rc) => {
79
+ plugin.hook_disconnect(() => {
81
80
  assert.equal(released, true)
82
81
  assert.equal(callNextCalled, true)
83
82
  assert.equal(conn.notes.smtp_client, undefined)
@@ -88,7 +87,7 @@ describe('queue/smtp_proxy', () => {
88
87
 
89
88
  describe('hook_queue', () => {
90
89
  it('calls next() when transaction is missing', (t, done) => {
91
- const connNoTxn = fixtures.connection.createConnection()
90
+ const connNoTxn = makeConnection()
92
91
  plugin.hook_queue((rc) => {
93
92
  assert.equal(rc, undefined)
94
93
  done()