Haraka 3.2.0 → 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.
- package/.githooks/pre-commit +41 -0
- package/.prettierignore +1 -0
- package/.qlty/.gitignore +7 -0
- package/.qlty/configs/.shellcheckrc +1 -0
- package/.qlty/qlty.toml +15 -0
- package/CHANGELOG.md +29 -2
- package/CONTRIBUTORS.md +5 -5
- package/README.md +6 -3
- package/bin/haraka +12 -4
- package/config/connection.ini +6 -0
- package/connection.js +67 -68
- package/contrib/bsd-rc.d/haraka +2 -0
- package/docs/CoreConfig.md +2 -0
- package/docs/HAProxy.md +4 -1
- package/eslint.config.mjs +2 -30
- package/haraka.js +2 -2
- package/line_socket.js +6 -33
- package/outbound/hmail.js +18 -29
- package/outbound/index.js +3 -3
- package/outbound/queue.js +8 -5
- package/package.json +51 -48
- package/plugins/auth/auth_proxy.js +7 -4
- package/plugins/block_me.js +1 -1
- package/plugins/delay_deny.js +1 -1
- package/plugins/queue/qmail-queue.js +1 -1
- package/plugins/queue/quarantine.js +5 -5
- package/plugins/queue/smtp_bridge.js +1 -1
- package/plugins/queue/smtp_proxy.js +2 -2
- package/plugins/status.js +2 -2
- package/plugins/toobusy.js +1 -1
- package/plugins.js +4 -3
- package/server.js +172 -28
- package/smtp_client.js +2 -1
- package/test/connection.js +119 -2
- package/test/fixtures/haproxy_allowed/config/connection.ini +3 -0
- package/test/fixtures/haproxy_disabled/config/connection.ini +3 -0
- package/test/fixtures/haproxy_untrusted/config/connection.ini +3 -0
- package/test/fixtures/line_socket.js +1 -1
- package/test/fixtures/util_hmailitem.js +2 -3
- package/test/outbound/index.js +6 -7
- package/test/outbound/qfile.js +1 -1
- package/test/outbound/queue.js +2 -2
- package/test/plugins/auth/auth_base.js +17 -17
- package/test/plugins/auth/auth_bridge.js +3 -3
- package/test/plugins/auth/auth_vpopmaild.js +3 -3
- package/test/plugins/auth/flat_file.js +16 -21
- package/test/plugins/block_me.js +7 -23
- package/test/plugins/data.signatures.js +17 -20
- package/test/plugins/delay_deny.js +3 -4
- package/test/plugins/prevent_credential_leaks.js +17 -21
- package/test/plugins/process_title.js +12 -6
- package/test/plugins/queue/deliver.js +7 -8
- package/test/plugins/queue/discard.js +3 -4
- package/test/plugins/queue/lmtp.js +5 -6
- package/test/plugins/queue/qmail-queue.js +7 -8
- package/test/plugins/queue/quarantine.js +3 -4
- package/test/plugins/queue/smtp_bridge.js +5 -7
- package/test/plugins/queue/smtp_forward.js +49 -60
- package/test/plugins/queue/smtp_proxy.js +6 -7
- package/test/plugins/rcpt_to.host_list_base.js +6 -9
- package/test/plugins/rcpt_to.in_host_list.js +6 -11
- package/test/plugins/record_envelope_addresses.js +33 -60
- package/test/plugins/reseed_rng.js +3 -3
- package/test/plugins/status.js +4 -5
- package/test/plugins/tarpit.js +3 -4
- package/test/plugins/tls.js +3 -5
- package/test/plugins/toobusy.js +186 -9
- package/test/plugins/xclient.js +7 -4
- package/test/server.js +425 -1
- package/test/smtp_client.js +11 -18
- package/test/tls_socket.js +3 -6
- package/tls_socket.js +3 -3
- package/transaction.js +3 -3
- package/address.js +0 -53
- package/endpoint.js +0 -96
- package/host_pool.js +0 -169
- package/outbound/fsync_writestream.js +0 -44
- package/outbound/timer_queue.js +0 -86
- package/rfc1869.js +0 -93
- package/test/endpoint.js +0 -128
- package/test/host_pool.js +0 -188
- package/test/rfc1869.js +0 -89
|
@@ -2,16 +2,15 @@
|
|
|
2
2
|
const assert = require('node:assert/strict')
|
|
3
3
|
const { describe, it, beforeEach } = require('node:test')
|
|
4
4
|
|
|
5
|
-
const { Address } = require('
|
|
6
|
-
const
|
|
5
|
+
const { Address } = require('@haraka/email-address')
|
|
6
|
+
const { assertResult, makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
const _set_up = () => {
|
|
9
|
-
this.plugin =
|
|
9
|
+
this.plugin = makePlugin('rcpt_to.host_list_base', { register: false })
|
|
10
10
|
this.plugin.cfg = {}
|
|
11
11
|
this.plugin.host_list = {}
|
|
12
12
|
|
|
13
|
-
this.connection =
|
|
14
|
-
this.connection.init_transaction()
|
|
13
|
+
this.connection = makeConnection({ withTxn: true })
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
describe('rcpt_to.host_list_base', () => {
|
|
@@ -78,8 +77,7 @@ describe('rcpt_to.host_list_base', () => {
|
|
|
78
77
|
const { rc, msg } = await callMailHook('<user@example.com>')
|
|
79
78
|
assert.equal(rc, undefined)
|
|
80
79
|
assert.equal(msg, undefined)
|
|
81
|
-
|
|
82
|
-
assert.ok(res.msg.includes('mail_from!local'))
|
|
80
|
+
assertResult(this.connection.transaction, 'rcpt_to.host_list_base', 'msg', /^mail_from!local$/)
|
|
83
81
|
})
|
|
84
82
|
|
|
85
83
|
for (const [desc, setup] of [
|
|
@@ -97,8 +95,7 @@ describe('rcpt_to.host_list_base', () => {
|
|
|
97
95
|
const { rc, msg } = await callMailHook('<user@example.com>')
|
|
98
96
|
assert.equal(rc, undefined)
|
|
99
97
|
assert.equal(msg, undefined)
|
|
100
|
-
|
|
101
|
-
assert.ok(res.pass.includes('mail_from'))
|
|
98
|
+
assertResult(this.connection.transaction, 'rcpt_to.host_list_base', 'pass', /^mail_from$/)
|
|
102
99
|
})
|
|
103
100
|
}
|
|
104
101
|
})
|
|
@@ -2,21 +2,18 @@
|
|
|
2
2
|
const assert = require('node:assert/strict')
|
|
3
3
|
const { describe, it, beforeEach } = require('node:test')
|
|
4
4
|
|
|
5
|
-
const { Address } = require('
|
|
5
|
+
const { Address } = require('@haraka/email-address')
|
|
6
6
|
const fixtures = require('haraka-test-fixtures')
|
|
7
|
+
const { assertResult, makeConnection, makePlugin } = fixtures
|
|
7
8
|
require('haraka-constants').import(global)
|
|
8
9
|
|
|
9
10
|
const _set_up = () => {
|
|
10
|
-
this.plugin =
|
|
11
|
+
this.plugin = makePlugin('rcpt_to.in_host_list', { register: false })
|
|
11
12
|
this.plugin.inherits('rcpt_to.host_list_base')
|
|
12
13
|
this.plugin.cfg = {}
|
|
13
14
|
this.plugin.host_list = {}
|
|
14
15
|
|
|
15
|
-
this.connection =
|
|
16
|
-
this.connection.transaction = {
|
|
17
|
-
results: new fixtures.results(this.connection),
|
|
18
|
-
notes: {},
|
|
19
|
-
}
|
|
16
|
+
this.connection = makeConnection({ withTxn: true })
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
describe('in_host_list', () => {
|
|
@@ -81,8 +78,7 @@ describe('in_host_list', () => {
|
|
|
81
78
|
const { rc, msg } = await callMailHook('<user@example.com>')
|
|
82
79
|
assert.equal(rc, undefined)
|
|
83
80
|
assert.equal(msg, undefined)
|
|
84
|
-
|
|
85
|
-
assert.ok(res.msg.includes('mail_from!local'))
|
|
81
|
+
assertResult(this.connection.transaction, 'rcpt_to.in_host_list', 'msg', /^mail_from!local$/)
|
|
86
82
|
})
|
|
87
83
|
|
|
88
84
|
for (const [desc, setup] of [
|
|
@@ -100,8 +96,7 @@ describe('in_host_list', () => {
|
|
|
100
96
|
const { rc, msg } = await callMailHook('<user@example.com>')
|
|
101
97
|
assert.equal(rc, undefined)
|
|
102
98
|
assert.equal(msg, undefined)
|
|
103
|
-
|
|
104
|
-
assert.ok(res.pass.includes('mail_from'))
|
|
99
|
+
assertResult(this.connection.transaction, 'rcpt_to.in_host_list', 'pass', /^mail_from$/)
|
|
105
100
|
})
|
|
106
101
|
}
|
|
107
102
|
})
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
const assert = require('node:assert')
|
|
4
4
|
const { describe, it, beforeEach } = require('node:test')
|
|
5
5
|
|
|
6
|
-
const {
|
|
7
|
-
const fixtures = require('haraka-test-fixtures')
|
|
6
|
+
const { callMail, callRcpt, makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
8
7
|
|
|
9
8
|
const _set_up = () => {
|
|
10
|
-
this.plugin =
|
|
11
|
-
this.connection =
|
|
12
|
-
this.connection.init_transaction()
|
|
9
|
+
this.plugin = makePlugin('record_envelope_addresses')
|
|
10
|
+
this.connection = makeConnection({ withTxn: true })
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
describe('record_envelope_addresses', () => {
|
|
@@ -17,77 +15,52 @@ describe('record_envelope_addresses', () => {
|
|
|
17
15
|
|
|
18
16
|
describe('hook_mail', () => {
|
|
19
17
|
it('adds X-Envelope-From header from MAIL FROM address', (t, done) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
done()
|
|
27
|
-
},
|
|
28
|
-
this.connection,
|
|
29
|
-
[addr],
|
|
30
|
-
)
|
|
18
|
+
callMail(this.plugin, this.connection, 'sender@example.com').then(() => {
|
|
19
|
+
const vals = this.connection.transaction.header.get_all('X-Envelope-From')
|
|
20
|
+
assert.equal(vals.length, 1, 'header was added')
|
|
21
|
+
assert.equal(vals[0], 'sender@example.com')
|
|
22
|
+
done()
|
|
23
|
+
})
|
|
31
24
|
})
|
|
32
25
|
|
|
33
26
|
it('does not throw when connection has no transaction', (t, done) => {
|
|
34
27
|
this.connection.transaction = null
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
()
|
|
38
|
-
|
|
39
|
-
done()
|
|
40
|
-
},
|
|
41
|
-
this.connection,
|
|
42
|
-
[addr],
|
|
43
|
-
)
|
|
28
|
+
callMail(this.plugin, this.connection, 'sender@example.com').then(() => {
|
|
29
|
+
assert.ok(true, 'next was called without error')
|
|
30
|
+
done()
|
|
31
|
+
})
|
|
44
32
|
})
|
|
45
33
|
})
|
|
46
34
|
|
|
47
35
|
describe('hook_rcpt', () => {
|
|
48
36
|
it('adds X-Envelope-To header from RCPT TO address', (t, done) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
done()
|
|
56
|
-
},
|
|
57
|
-
this.connection,
|
|
58
|
-
[addr],
|
|
59
|
-
)
|
|
37
|
+
callRcpt(this.plugin, this.connection, 'rcpt@example.com').then(() => {
|
|
38
|
+
const vals = this.connection.transaction.header.get_all('X-Envelope-To')
|
|
39
|
+
assert.equal(vals.length, 1, 'header was added')
|
|
40
|
+
assert.equal(vals[0], 'rcpt@example.com')
|
|
41
|
+
done()
|
|
42
|
+
})
|
|
60
43
|
})
|
|
61
44
|
|
|
62
45
|
it('adds X-Envelope-To header for each recipient', (t, done) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
done()
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
this.plugin.hook_rcpt(next, this.connection, [addr1])
|
|
77
|
-
this.plugin.hook_rcpt(next, this.connection, [addr2])
|
|
46
|
+
Promise.all([
|
|
47
|
+
callRcpt(this.plugin, this.connection, 'one@example.com'),
|
|
48
|
+
callRcpt(this.plugin, this.connection, 'two@example.com'),
|
|
49
|
+
]).then(() => {
|
|
50
|
+
const vals = this.connection.transaction.header.get_all('X-Envelope-To')
|
|
51
|
+
assert.equal(vals.length, 2, 'two headers added')
|
|
52
|
+
assert.equal(vals[0], 'one@example.com')
|
|
53
|
+
assert.equal(vals[1], 'two@example.com')
|
|
54
|
+
done()
|
|
55
|
+
})
|
|
78
56
|
})
|
|
79
57
|
|
|
80
58
|
it('does not throw when connection has no transaction', (t, done) => {
|
|
81
59
|
this.connection.transaction = null
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
()
|
|
85
|
-
|
|
86
|
-
done()
|
|
87
|
-
},
|
|
88
|
-
this.connection,
|
|
89
|
-
[addr],
|
|
90
|
-
)
|
|
60
|
+
callRcpt(this.plugin, this.connection, 'rcpt@example.com').then(() => {
|
|
61
|
+
assert.ok(true, 'next was called without error')
|
|
62
|
+
done()
|
|
63
|
+
})
|
|
91
64
|
})
|
|
92
65
|
})
|
|
93
66
|
})
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
const assert = require('node:assert/strict')
|
|
4
4
|
const { describe, it } = require('node:test')
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const { makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
describe('reseed_rng', () => {
|
|
9
9
|
describe('hook_init_child', () => {
|
|
10
10
|
it('calls Math.seedrandom with a hex string and calls next', (t, done) => {
|
|
11
|
-
const plugin =
|
|
11
|
+
const plugin = makePlugin('reseed_rng', { register: false })
|
|
12
12
|
let called = false
|
|
13
13
|
let calledArg
|
|
14
14
|
Math.seedrandom = (arg) => {
|
|
@@ -26,7 +26,7 @@ describe('reseed_rng', () => {
|
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
it('throws when Math.seedrandom is not defined', () => {
|
|
29
|
-
const plugin =
|
|
29
|
+
const plugin = makePlugin('reseed_rng', { register: false })
|
|
30
30
|
delete Math.seedrandom
|
|
31
31
|
assert.throws(() => plugin.hook_init_child(() => {}), /Math\.seedrandom is not a function/)
|
|
32
32
|
})
|
package/test/plugins/status.js
CHANGED
|
@@ -4,16 +4,15 @@ 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 outbound = require('../../outbound')
|
|
8
|
-
const TimerQueue = require('
|
|
9
|
-
|
|
10
|
-
const Connection = fixtures.connection
|
|
9
|
+
const { TimerQueue } = require('haraka-utils')
|
|
11
10
|
|
|
12
11
|
const _set_up = () => {
|
|
13
|
-
this.plugin =
|
|
12
|
+
this.plugin = makePlugin('status', { register: false })
|
|
14
13
|
this.plugin.outbound = outbound
|
|
15
14
|
|
|
16
|
-
this.connection =
|
|
15
|
+
this.connection = makeConnection()
|
|
17
16
|
this.connection.remote.is_local = true
|
|
18
17
|
}
|
|
19
18
|
|
package/test/plugins/tarpit.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
const assert = require('node:assert/strict')
|
|
4
4
|
const { describe, it, beforeEach } = require('node:test')
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
describe('tarpit', () => {
|
|
9
9
|
let plugin
|
|
10
10
|
|
|
11
11
|
beforeEach(() => {
|
|
12
|
-
plugin =
|
|
12
|
+
plugin = makePlugin('tarpit', { register: false })
|
|
13
13
|
plugin.config.get = () => ({ main: {} })
|
|
14
14
|
})
|
|
15
15
|
|
|
@@ -40,8 +40,7 @@ describe('tarpit', () => {
|
|
|
40
40
|
let conn
|
|
41
41
|
|
|
42
42
|
beforeEach(() => {
|
|
43
|
-
conn =
|
|
44
|
-
conn.init_transaction()
|
|
43
|
+
conn = makeConnection({ withTxn: true })
|
|
45
44
|
})
|
|
46
45
|
|
|
47
46
|
it('calls next immediately when no transaction', (t, done) => {
|
package/test/plugins/tls.js
CHANGED
|
@@ -4,15 +4,13 @@ const assert = require('node:assert/strict')
|
|
|
4
4
|
const path = require('node:path')
|
|
5
5
|
const { describe, it, beforeEach } = require('node:test')
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const Plugin = fixtures.plugin
|
|
7
|
+
const { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
9
8
|
|
|
10
9
|
const _set_up = () => {
|
|
11
|
-
this.plugin =
|
|
12
|
-
this.connection =
|
|
10
|
+
this.plugin = makePlugin('tls', { register: false, configDir: 'test' })
|
|
11
|
+
this.connection = makeConnection()
|
|
13
12
|
|
|
14
13
|
// use test/config instead of ./config
|
|
15
|
-
this.plugin.config = this.plugin.config.module_config(path.resolve('test'))
|
|
16
14
|
this.plugin.net_utils.config = this.plugin.net_utils.config.module_config(path.resolve('test'))
|
|
17
15
|
|
|
18
16
|
this.plugin.tls_opts = {}
|
package/test/plugins/toobusy.js
CHANGED
|
@@ -1,21 +1,198 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('node:assert/strict')
|
|
4
|
-
const { describe, it } = require('node:test')
|
|
4
|
+
const { beforeEach, describe, it } = require('node:test')
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
|
+
require('haraka-constants').import(global)
|
|
7
8
|
|
|
8
9
|
describe('toobusy', () => {
|
|
10
|
+
let plugin
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
plugin = makePlugin('toobusy', { register: false })
|
|
14
|
+
})
|
|
15
|
+
|
|
9
16
|
describe('register', () => {
|
|
10
|
-
it('
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
plugin.register_hook = () => {
|
|
15
|
-
registered = true
|
|
17
|
+
it('registers connect hook with correct priority', () => {
|
|
18
|
+
const hooks = []
|
|
19
|
+
plugin.register_hook = function (hook, name, priority) {
|
|
20
|
+
hooks.push({ hook, name, priority })
|
|
16
21
|
}
|
|
22
|
+
|
|
23
|
+
plugin.register()
|
|
24
|
+
|
|
25
|
+
assert.equal(hooks.length, 1, 'should register one hook')
|
|
26
|
+
assert.equal(hooks[0].hook, 'connect')
|
|
27
|
+
assert.equal(hooks[0].name, 'check_busy')
|
|
28
|
+
assert.equal(hooks[0].priority, -100)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('loads config on register', () => {
|
|
32
|
+
let loadConfigCalled = false
|
|
33
|
+
const originalLoadConfig = plugin.loadConfig
|
|
34
|
+
plugin.loadConfig = function () {
|
|
35
|
+
loadConfigCalled = true
|
|
36
|
+
return originalLoadConfig.call(this)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
plugin.register()
|
|
40
|
+
|
|
41
|
+
assert.equal(loadConfigCalled, true, 'loadConfig should be called')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('handles missing toobusy-js gracefully', () => {
|
|
17
45
|
assert.doesNotThrow(() => plugin.register())
|
|
18
|
-
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe('loadConfig', () => {
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
plugin.register()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('gets toobusy.maxlag config value', () => {
|
|
55
|
+
let configArgs = []
|
|
56
|
+
|
|
57
|
+
plugin.config.get = function (key, type, callback) {
|
|
58
|
+
configArgs = [key, type]
|
|
59
|
+
return '70'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
plugin.loadConfig()
|
|
63
|
+
|
|
64
|
+
assert.equal(configArgs[0], 'toobusy.maxlag')
|
|
65
|
+
assert.equal(configArgs[1], 'value')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('passes callback to config.get for hot reload', () => {
|
|
69
|
+
let callbackProvided = false
|
|
70
|
+
|
|
71
|
+
plugin.config.get = function (key, type, callback) {
|
|
72
|
+
callbackProvided = typeof callback === 'function'
|
|
73
|
+
return '70'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
plugin.loadConfig()
|
|
77
|
+
|
|
78
|
+
assert.equal(callbackProvided, true, 'callback should be provided for hot reload')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('handles zero maxLag value', () => {
|
|
82
|
+
plugin.config.get = () => '0'
|
|
83
|
+
|
|
84
|
+
assert.doesNotThrow(() => {
|
|
85
|
+
plugin.loadConfig()
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('handles non-numeric maxLag value', () => {
|
|
90
|
+
plugin.config.get = () => 'notanumber'
|
|
91
|
+
|
|
92
|
+
assert.doesNotThrow(() => {
|
|
93
|
+
plugin.loadConfig()
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('handles empty string maxLag value', () => {
|
|
98
|
+
plugin.config.get = () => ''
|
|
99
|
+
|
|
100
|
+
assert.doesNotThrow(() => {
|
|
101
|
+
plugin.loadConfig()
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('parses numeric maxLag as integer', () => {
|
|
106
|
+
plugin.config.get = () => '100'
|
|
107
|
+
|
|
108
|
+
assert.doesNotThrow(() => {
|
|
109
|
+
plugin.loadConfig()
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('supports reload via callback', () => {
|
|
114
|
+
let callbackFn = null
|
|
115
|
+
|
|
116
|
+
plugin.config.get = function (key, type, callback) {
|
|
117
|
+
callbackFn = callback
|
|
118
|
+
return '70'
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
plugin.loadConfig()
|
|
122
|
+
|
|
123
|
+
assert.equal(typeof callbackFn, 'function', 'callback should be provided')
|
|
124
|
+
assert.doesNotThrow(() => {
|
|
125
|
+
if (callbackFn) callbackFn()
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
describe('check_busy', () => {
|
|
131
|
+
beforeEach(() => {
|
|
132
|
+
plugin.register()
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('calls next without args when not busy', (t, done) => {
|
|
136
|
+
plugin.config.get = () => '70'
|
|
137
|
+
plugin.loadConfig()
|
|
138
|
+
|
|
139
|
+
plugin.check_busy(function (...args) {
|
|
140
|
+
assert.equal(args.length, 0, 'should call next with no arguments')
|
|
141
|
+
done()
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('initializes was_busy state', (t, done) => {
|
|
146
|
+
plugin.config.get = () => '70'
|
|
147
|
+
plugin.loadConfig()
|
|
148
|
+
|
|
149
|
+
plugin.check_busy(function () {
|
|
150
|
+
done()
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('is a callable function', () => {
|
|
155
|
+
assert.equal(typeof plugin.check_busy, 'function')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('does not log when not busy', (t, done) => {
|
|
159
|
+
plugin.config.get = () => '70'
|
|
160
|
+
plugin.loadConfig()
|
|
161
|
+
|
|
162
|
+
let logCount = 0
|
|
163
|
+
plugin.logcrit = function () {
|
|
164
|
+
logCount++
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
plugin.check_busy(function () {
|
|
168
|
+
plugin.check_busy(function () {
|
|
169
|
+
assert.equal(logCount, 0, 'should not log when not busy')
|
|
170
|
+
done()
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('accepts next callback', (t, done) => {
|
|
176
|
+
plugin.config.get = () => '70'
|
|
177
|
+
plugin.loadConfig()
|
|
178
|
+
|
|
179
|
+
const nextFn = function () {
|
|
180
|
+
done()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
assert.doesNotThrow(() => {
|
|
184
|
+
plugin.check_busy(nextFn)
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it('works with connection context', (t, done) => {
|
|
189
|
+
plugin.config.get = () => '70'
|
|
190
|
+
plugin.loadConfig()
|
|
191
|
+
|
|
192
|
+
const conn = makeConnection()
|
|
193
|
+
plugin.check_busy.call(conn, function () {
|
|
194
|
+
done()
|
|
195
|
+
})
|
|
19
196
|
})
|
|
20
197
|
})
|
|
21
198
|
})
|
package/test/plugins/xclient.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
const assert = require('node:assert/strict')
|
|
4
4
|
const { describe, it, beforeEach } = require('node:test')
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
const _set_up = () => {
|
|
9
|
-
this.plugin =
|
|
10
|
-
this.connection =
|
|
9
|
+
this.plugin = makePlugin('xclient', { register: false })
|
|
10
|
+
this.connection = makeConnection()
|
|
11
11
|
this.connection.capabilities = []
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -45,7 +45,10 @@ describe('xclient', () => {
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
desc: 'denies XCLIENT when transaction is in progress',
|
|
48
|
-
setup: () =>
|
|
48
|
+
setup: () => {
|
|
49
|
+
this.connection = makeConnection({ withTxn: true })
|
|
50
|
+
this.connection.capabilities = []
|
|
51
|
+
},
|
|
49
52
|
params: ['XCLIENT', 'ADDR=127.0.0.1'],
|
|
50
53
|
check: (code) => assert.equal(code, DENY),
|
|
51
54
|
},
|