haraka 3.3.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/.prettierignore +1 -0
- package/CHANGELOG.md +8 -4
- package/bin/haraka +1 -1
- package/connection.js +4 -2
- package/contrib/bsd-rc.d/haraka +2 -0
- package/outbound/hmail.js +1 -1
- package/outbound/index.js +1 -1
- package/outbound/queue.js +1 -1
- package/package.json +22 -21
- package/plugins.js +4 -3
- package/test/connection.js +5 -2
- package/test/fixtures/util_hmailitem.js +1 -1
- package/test/outbound/index.js +2 -2
- package/test/plugins/auth/auth_base.js +1 -1
- package/test/plugins/queue/smtp_forward.js +1 -1
- package/test/plugins/rcpt_to.host_list_base.js +1 -1
- package/test/plugins/rcpt_to.in_host_list.js +1 -1
- package/test/plugins/toobusy.js +186 -9
- package/test/smtp_client.js +1 -1
- package/.claude/settings.local.json +0 -28
- package/CLAUDE.md +0 -40
- package/GEMINI.md +0 -38
- package/address.js +0 -53
- package/config/dhparams.pem +0 -8
- package/config/me +0 -1
- package/config/tls_cert.pem +0 -23
- package/config/tls_key.pem +0 -28
- package/coverage/coverage-final.json +0 -2
- package/coverage/coverage-summary.json +0 -33
- package/coverage/tmp/coverage-79131-1779241025146-0.json +0 -1
- package/coverage/tmp/coverage-79132-1779240999690-0.json +0 -1
- package/coverage/tmp/coverage-79172-1779241000095-0.json +0 -1
- package/coverage/tmp/coverage-79210-1779241000156-0.json +0 -1
- package/coverage/tmp/coverage-79211-1779241000209-0.json +0 -1
- package/coverage/tmp/coverage-79212-1779241000266-0.json +0 -1
- package/coverage/tmp/coverage-79213-1779241000441-0.json +0 -1
- package/coverage/tmp/coverage-79214-1779241000626-0.json +0 -1
- package/coverage/tmp/coverage-79215-1779241000795-0.json +0 -1
- package/coverage/tmp/coverage-79216-1779241000965-0.json +0 -1
- package/coverage/tmp/coverage-79218-1779241001013-0.json +0 -1
- package/coverage/tmp/coverage-79219-1779241001179-0.json +0 -1
- package/coverage/tmp/coverage-79220-1779241006249-0.json +0 -1
- package/coverage/tmp/coverage-79227-1779241011453-0.json +0 -1
- package/coverage/tmp/coverage-79229-1779241011537-0.json +0 -1
- package/coverage/tmp/coverage-79230-1779241011647-0.json +0 -1
- package/coverage/tmp/coverage-79231-1779241011765-0.json +0 -1
- package/coverage/tmp/coverage-79232-1779241011841-0.json +0 -1
- package/coverage/tmp/coverage-79233-1779241011909-0.json +0 -1
- package/coverage/tmp/coverage-79234-1779241011984-0.json +0 -1
- package/coverage/tmp/coverage-79235-1779241012055-0.json +0 -1
- package/coverage/tmp/coverage-79236-1779241012230-0.json +0 -1
- package/coverage/tmp/coverage-79237-1779241012300-0.json +0 -1
- package/coverage/tmp/coverage-79238-1779241012368-0.json +0 -1
- package/coverage/tmp/coverage-79239-1779241012438-0.json +0 -1
- package/coverage/tmp/coverage-79240-1779241012511-0.json +0 -1
- package/coverage/tmp/coverage-79241-1779241012582-0.json +0 -1
- package/coverage/tmp/coverage-79242-1779241012652-0.json +0 -1
- package/coverage/tmp/coverage-79243-1779241012814-0.json +0 -1
- package/coverage/tmp/coverage-79244-1779241012931-0.json +0 -1
- package/coverage/tmp/coverage-79245-1779241013007-0.json +0 -1
- package/coverage/tmp/coverage-79246-1779241013106-0.json +0 -1
- package/coverage/tmp/coverage-79247-1779241013178-0.json +0 -1
- package/coverage/tmp/coverage-79248-1779241013244-0.json +0 -1
- package/coverage/tmp/coverage-79249-1779241013409-0.json +0 -1
- package/coverage/tmp/coverage-79250-1779241013697-0.json +0 -1
- package/coverage/tmp/coverage-79251-1779241013847-0.json +0 -1
- package/coverage/tmp/coverage-79252-1779241014288-0.json +0 -1
- package/coverage/tmp/coverage-79253-1779241014378-0.json +0 -1
- package/coverage/tmp/coverage-79254-1779241014428-0.json +0 -1
- package/coverage/tmp/coverage-79255-1779241021774-0.json +0 -1
- package/coverage/tmp/coverage-80382-1779241021949-0.json +0 -1
- package/coverage/tmp/coverage-80383-1779241025019-0.json +0 -1
- package/coverage/tmp/coverage-80384-1779241025133-0.json +0 -1
- package/queue/1772642154987_1775581346001_4_82235_TGwgfd_2_mattbook-m3.home.simerson.net +0 -0
package/.prettierignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
4
4
|
|
|
5
5
|
### Unreleased
|
|
6
6
|
|
|
7
|
-
### [3.3.
|
|
7
|
+
### [3.3.1] - 2026-06-12
|
|
8
8
|
|
|
9
|
-
- fix(
|
|
9
|
+
- fix(conn): flag soft queue denials in results
|
|
10
|
+
- feat: expose fetch to plugins
|
|
11
|
+
- change: remove @haraka/email-address wrapper #3598
|
|
12
|
+
- change: log when MFROM or RCPT fail to parse #3581
|
|
13
|
+
- fix: change package name from Haraka to haraka #3596
|
|
14
|
+
- fix(haraka): wrap util.createFile in a try #3595
|
|
10
15
|
- fix(conn): update local and remote results after proxy #3593
|
|
11
16
|
- feat(conn): add main.postel option #3592
|
|
12
|
-
- change: log when MFROM or RCPT fail to parse #3581
|
|
13
17
|
- feat: proxy support for smtps (465) #3577
|
|
14
18
|
- refactor(auth_proxy): use net_utils.endpoint #3584
|
|
15
19
|
- refactor: move endpoint, HostPool, LineSocket to net-utils #3583
|
|
@@ -1891,4 +1895,4 @@ config files.
|
|
|
1891
1895
|
[3.1.7]: https://github.com/haraka/Haraka/releases/tag/v3.1.7
|
|
1892
1896
|
[3.2.0]: https://github.com/haraka/Haraka/releases/tag/v3.2.0
|
|
1893
1897
|
[3.2.1]: https://github.com/haraka/Haraka/releases/tag/v3.2.1
|
|
1894
|
-
[3.3.
|
|
1898
|
+
[3.3.1]: https://github.com/haraka/Haraka/releases/tag/v3.3.1
|
package/bin/haraka
CHANGED
|
@@ -414,7 +414,7 @@ if (parsed.version) {
|
|
|
414
414
|
plugins.load_plugins(parsed.test && parsed.test[0] !== 'all' ? parsed.test : null)
|
|
415
415
|
const Connection = require(path.join(base, 'connection'))
|
|
416
416
|
// var Transaction = require(path.join(base, "transaction"));
|
|
417
|
-
const Address = require('
|
|
417
|
+
const Address = require('@haraka/email-address').Address
|
|
418
418
|
const Notes = require('haraka-notes')
|
|
419
419
|
const constants = require('haraka-constants')
|
|
420
420
|
const client = {
|
package/connection.js
CHANGED
|
@@ -11,7 +11,7 @@ const constants = require('haraka-constants')
|
|
|
11
11
|
const net_utils = require('haraka-net-utils')
|
|
12
12
|
const Notes = require('haraka-notes')
|
|
13
13
|
const utils = require('haraka-utils')
|
|
14
|
-
const { Address } = require('
|
|
14
|
+
const { Address } = require('@haraka/email-address')
|
|
15
15
|
const ResultStore = require('haraka-results')
|
|
16
16
|
|
|
17
17
|
// Haraka libs
|
|
@@ -1698,9 +1698,11 @@ class Connection {
|
|
|
1698
1698
|
break
|
|
1699
1699
|
case constants.deny:
|
|
1700
1700
|
case constants.denydisconnect:
|
|
1701
|
+
this.transaction.results.add(res_as, { fail: msg })
|
|
1702
|
+
break
|
|
1701
1703
|
case constants.denysoft:
|
|
1702
1704
|
case constants.denysoftdisconnect:
|
|
1703
|
-
this.transaction.results.add(res_as, { fail: msg })
|
|
1705
|
+
this.transaction.results.add(res_as, { fail: msg, soft: true })
|
|
1704
1706
|
break
|
|
1705
1707
|
case constants.cont:
|
|
1706
1708
|
break
|
package/contrib/bsd-rc.d/haraka
CHANGED
package/outbound/hmail.js
CHANGED
|
@@ -7,7 +7,7 @@ const dns = require('node:dns')
|
|
|
7
7
|
const net = require('node:net')
|
|
8
8
|
const path = require('node:path')
|
|
9
9
|
|
|
10
|
-
const { Address } = require('
|
|
10
|
+
const { Address } = require('@haraka/email-address')
|
|
11
11
|
const config = require('haraka-config')
|
|
12
12
|
const constants = require('haraka-constants')
|
|
13
13
|
const DSN = require('haraka-dsn')
|
package/outbound/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require('node:fs/promises')
|
|
4
4
|
const path = require('node:path')
|
|
5
5
|
|
|
6
|
-
const { Address } = require('
|
|
6
|
+
const { Address } = require('@haraka/email-address')
|
|
7
7
|
const config = require('haraka-config')
|
|
8
8
|
const constants = require('haraka-constants')
|
|
9
9
|
const net_utils = require('haraka-net-utils')
|
package/outbound/queue.js
CHANGED
|
@@ -4,7 +4,7 @@ const child_process = require('node:child_process')
|
|
|
4
4
|
const fs = require('node:fs/promises')
|
|
5
5
|
const path = require('node:path')
|
|
6
6
|
|
|
7
|
-
const { Address } = require('
|
|
7
|
+
const { Address } = require('@haraka/email-address')
|
|
8
8
|
const config = require('haraka-config')
|
|
9
9
|
const utils = require('haraka-utils')
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"author": "Matt Sergeant <helpme@gmail.com>
|
|
2
|
+
"author": "Matt Sergeant <helpme@gmail.com>",
|
|
3
3
|
"name": "haraka",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "An SMTP Server project.",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"server",
|
|
10
10
|
"email"
|
|
11
11
|
],
|
|
12
|
-
"version": "3.3.
|
|
12
|
+
"version": "3.3.1",
|
|
13
13
|
"homepage": "http://haraka.github.io",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
@@ -20,22 +20,22 @@
|
|
|
20
20
|
"node": ">=20"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@haraka/email-address": "~3.1.
|
|
24
|
-
"haraka-config": "~1.6.
|
|
23
|
+
"@haraka/email-address": "~3.1.6",
|
|
24
|
+
"haraka-config": "~1.6.3",
|
|
25
25
|
"haraka-constants": "~1.0.8",
|
|
26
26
|
"haraka-dsn": "~1.2.0",
|
|
27
27
|
"haraka-email-message": "~1.4.0",
|
|
28
|
-
"haraka-net-utils": "~1.9.
|
|
28
|
+
"haraka-net-utils": "~1.9.2",
|
|
29
29
|
"haraka-notes": "~1.1.3",
|
|
30
30
|
"haraka-plugin-redis": "~2.1.0",
|
|
31
|
-
"haraka-results": "~2.
|
|
32
|
-
"haraka-tld": "~1.3.
|
|
33
|
-
"haraka-utils": "~2.2.
|
|
31
|
+
"haraka-results": "~2.4.0",
|
|
32
|
+
"haraka-tld": "~1.3.6",
|
|
33
|
+
"haraka-utils": "~2.2.1",
|
|
34
34
|
"ipaddr.js": "~2.4.0",
|
|
35
|
-
"node-gyp": "~12.
|
|
36
|
-
"nopt": "~10.0.
|
|
35
|
+
"node-gyp": "~12.4.0",
|
|
36
|
+
"nopt": "~10.0.1",
|
|
37
37
|
"redis": "~6.0.0",
|
|
38
|
-
"semver": "~7.8.
|
|
38
|
+
"semver": "~7.8.4"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"@haraka/ocsp": "~1.2.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"haraka-plugin-aliases": "~1.1.0",
|
|
44
44
|
"haraka-plugin-asn": "~2.2.0",
|
|
45
45
|
"haraka-plugin-attachment": "~1.2.1",
|
|
46
|
-
"haraka-plugin-bounce": "~2.2.
|
|
46
|
+
"haraka-plugin-bounce": "~2.2.1",
|
|
47
47
|
"haraka-plugin-clamd": "~1.0.3",
|
|
48
48
|
"haraka-plugin-dcc": "~1.0.3",
|
|
49
49
|
"haraka-plugin-dkim": "~1.2.0",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"haraka-plugin-geoip": "~1.1.2",
|
|
54
54
|
"haraka-plugin-greylist": "~1.2.1",
|
|
55
55
|
"haraka-plugin-headers": "~1.2.0",
|
|
56
|
-
"haraka-plugin-helo.checks": "~1.1.
|
|
57
|
-
"haraka-plugin-karma": "~2.5.
|
|
56
|
+
"haraka-plugin-helo.checks": "~1.1.3",
|
|
57
|
+
"haraka-plugin-karma": "~2.5.2",
|
|
58
58
|
"haraka-plugin-known-senders": "~1.2.0",
|
|
59
|
-
"haraka-plugin-limit": "~1.3.
|
|
59
|
+
"haraka-plugin-limit": "~1.3.2",
|
|
60
60
|
"haraka-plugin-mail_from.is_resolvable": "~1.3.0",
|
|
61
61
|
"haraka-plugin-messagesniffer": "~1.0.2",
|
|
62
62
|
"haraka-plugin-qmail-deliverable": "~1.4.0",
|
|
@@ -64,21 +64,22 @@
|
|
|
64
64
|
"haraka-plugin-rspamd": "~1.6.0",
|
|
65
65
|
"haraka-plugin-spamassassin": "~1.1.0",
|
|
66
66
|
"haraka-plugin-spf": "~1.3.0",
|
|
67
|
-
"haraka-plugin-syslog": "~1.1.
|
|
67
|
+
"haraka-plugin-syslog": "~1.1.2",
|
|
68
68
|
"haraka-plugin-uribl": "~2.0.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@haraka/eslint-config": "~3.0.0",
|
|
72
72
|
"haraka-test-fixtures": "^1.7.1",
|
|
73
|
-
"mock-require": "~3.0.3"
|
|
73
|
+
"mock-require": "~3.0.3",
|
|
74
|
+
"toobusy-js": "^0.5.1"
|
|
74
75
|
},
|
|
75
76
|
"bugs": {
|
|
76
77
|
"mail": "haraka.mail@gmail.com",
|
|
77
78
|
"url": "https://github.com/haraka/Haraka/issues"
|
|
78
79
|
},
|
|
79
80
|
"bin": {
|
|
80
|
-
"haraka": "
|
|
81
|
-
"haraka_grep": "
|
|
81
|
+
"haraka": "bin/haraka",
|
|
82
|
+
"haraka_grep": "bin/haraka_grep"
|
|
82
83
|
},
|
|
83
84
|
"scripts": {
|
|
84
85
|
"prepare": "git rev-parse --git-dir >/dev/null 2>&1 && git config core.hooksPath .githooks || true",
|
|
@@ -89,8 +90,8 @@
|
|
|
89
90
|
"prettier:fix": "npx prettier . --write --log-level=warn",
|
|
90
91
|
"qlty": "qlty smells --all",
|
|
91
92
|
"test": "sh ./run_tests",
|
|
92
|
-
"test:coverage": "node --test --test-concurrency=1 --experimental-test-coverage",
|
|
93
|
-
"test:coverage:lcov": "mkdir -p coverage && node --test --test-concurrency=1 --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage/lcov.info",
|
|
93
|
+
"test:coverage": "node --test --test-concurrency=1 --experimental-test-coverage --test-coverage-include=*.js --test-coverage-include=plugins/**/*.js --test-coverage-include=outbound/*.js",
|
|
94
|
+
"test:coverage:lcov": "mkdir -p coverage && node --test --test-concurrency=1 --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage/lcov.info --test-coverage-include=*.js --test-coverage-include=plugins/**/*.js --test-coverage-include=outbound/*.js",
|
|
94
95
|
"versions": "npx npm-dep-mgr check",
|
|
95
96
|
"versions:fix": "npx npm-dep-mgr update"
|
|
96
97
|
},
|
package/plugins.js
CHANGED
|
@@ -197,11 +197,12 @@ class Plugin {
|
|
|
197
197
|
__filename: pp,
|
|
198
198
|
__dirname: path.dirname(pp),
|
|
199
199
|
exports: this,
|
|
200
|
-
|
|
200
|
+
fetch,
|
|
201
201
|
clearTimeout,
|
|
202
|
-
setInterval,
|
|
203
202
|
clearInterval,
|
|
204
203
|
process,
|
|
204
|
+
setInterval,
|
|
205
|
+
setTimeout,
|
|
205
206
|
Buffer,
|
|
206
207
|
Math,
|
|
207
208
|
server: plugins.server,
|
|
@@ -585,7 +586,7 @@ function get_denyfn(object, hook, params, retval, msg, respond_method) {
|
|
|
585
586
|
switch (deny_retval) {
|
|
586
587
|
case constants.ok:
|
|
587
588
|
// Override rejection
|
|
588
|
-
object.loginfo(`deny(soft?)
|
|
589
|
+
object.loginfo(`deny(soft?) overridden by deny hook${deny_msg ? ': deny_msg' : ''}`)
|
|
589
590
|
// Restore hooks_to_run with saved copy so that
|
|
590
591
|
// any other plugins on this hook can also run.
|
|
591
592
|
if (object.saved_hooks_to_run.length > 0) {
|
package/test/connection.js
CHANGED
|
@@ -5,7 +5,7 @@ const assert = require('node:assert/strict')
|
|
|
5
5
|
|
|
6
6
|
const constants = require('haraka-constants')
|
|
7
7
|
const DSN = require('haraka-dsn')
|
|
8
|
-
const { Address } = require('
|
|
8
|
+
const { Address } = require('@haraka/email-address')
|
|
9
9
|
|
|
10
10
|
const connection = require('../connection')
|
|
11
11
|
const Server = require('../server')
|
|
@@ -508,7 +508,10 @@ describe('connection', () => {
|
|
|
508
508
|
assert.equal(this.connection.msg_count.tempfail, 1)
|
|
509
509
|
assert.equal(this.connection.transaction.msg_status, 'deferred')
|
|
510
510
|
assert.equal(harness.calls.reset, 1)
|
|
511
|
-
assert.deepEqual(harness.calls.results[0], {
|
|
511
|
+
assert.deepEqual(harness.calls.results[0], {
|
|
512
|
+
fail: 'Message denied temporarily',
|
|
513
|
+
soft: true,
|
|
514
|
+
})
|
|
512
515
|
} finally {
|
|
513
516
|
harness.restore()
|
|
514
517
|
}
|
package/test/outbound/index.js
CHANGED
|
@@ -210,7 +210,7 @@ describe('outbound', () => {
|
|
|
210
210
|
it('yields to setImmediate before opening process_delivery pipes', async () => {
|
|
211
211
|
const stream = require('node:stream')
|
|
212
212
|
const Transaction = require('../../transaction')
|
|
213
|
-
const Address = require('
|
|
213
|
+
const Address = require('@haraka/email-address').Address
|
|
214
214
|
const outbound = require('../../outbound')
|
|
215
215
|
const plugins = require('../../plugins')
|
|
216
216
|
|
|
@@ -270,7 +270,7 @@ describe('outbound', () => {
|
|
|
270
270
|
|
|
271
271
|
it('adds missing Message-Id/Date and prepends Received before queueing', async () => {
|
|
272
272
|
process.env.HARAKA_TEST_DIR = path.resolve('test')
|
|
273
|
-
const Address = require('
|
|
273
|
+
const Address = require('@haraka/email-address').Address
|
|
274
274
|
const outbound = require('../../outbound')
|
|
275
275
|
const plugins = require('../../plugins')
|
|
276
276
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const assert = require('node:assert')
|
|
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 { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
const utils = require('haraka-utils')
|
|
8
8
|
|
|
@@ -5,7 +5,7 @@ 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('
|
|
8
|
+
const { Address } = require('@haraka/email-address')
|
|
9
9
|
const { makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
10
10
|
const Notes = require('haraka-notes')
|
|
11
11
|
|
|
@@ -2,7 +2,7 @@
|
|
|
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 { assertResult, makeConnection, makePlugin } = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
const _set_up = () => {
|
|
@@ -2,7 +2,7 @@
|
|
|
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
7
|
const { assertResult, makeConnection, makePlugin } = fixtures
|
|
8
8
|
require('haraka-constants').import(global)
|
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 { makePlugin } = require('haraka-test-fixtures')
|
|
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/smtp_client.js
CHANGED
|
@@ -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('
|
|
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')
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(npm test:*)",
|
|
5
|
-
"Bash(grep -r 3388 . --include=*.md --include=*.js)",
|
|
6
|
-
"Bash(git show-ref:*)",
|
|
7
|
-
"Bash(git symbolic-ref:*)",
|
|
8
|
-
"Bash(curl -s https://api.github.com/repos/haraka/Haraka/issues/3388)",
|
|
9
|
-
"WebFetch(domain:github.com)",
|
|
10
|
-
"Bash(npx c8:*)",
|
|
11
|
-
"Bash(node:*)",
|
|
12
|
-
"Bash(npx mocha:*)",
|
|
13
|
-
"Bash(npm run:*)",
|
|
14
|
-
"Bash(gh issue *)",
|
|
15
|
-
"Bash(git -C /Users/matt/git/haraka/Haraka log --oneline --all)",
|
|
16
|
-
"Bash(git *)",
|
|
17
|
-
"Bash(cat)",
|
|
18
|
-
"Read(//tmp/**)",
|
|
19
|
-
"Bash(bash /tmp/check_patterns.sh)",
|
|
20
|
-
"Bash(npx prettier *)",
|
|
21
|
-
"Bash(npx eslint *)",
|
|
22
|
-
"Bash(perl -0pi -e 's/ const plugin = makePlugin\\\\\\(\\\\\\)\\\\n//g' test/plugins/prevent_credential_leaks.js)",
|
|
23
|
-
"Bash(perl -0pi -e 's/makePlugin\\\\\\(\\\\\\)\\\\./plugin./g; s/ const plugin = makePlugin\\\\\\(\\\\\\)\\\\n//g' test/plugins/process_title.js)",
|
|
24
|
-
"Bash(perl -0pi -e 's/ const plugin = makePlugin\\\\\\(\\\\\\)\\\\n//g; s/ const conn = fixtures\\\\.connection\\\\.createConnection\\\\\\(\\\\\\)\\\\n conn\\\\.transaction = null/ conn.transaction = null/g; s/ const conn = makeConnection\\\\\\(\\\\\\)\\\\n//g' test/plugins/delay_deny.js)",
|
|
25
|
-
"Bash(gh pr *)"
|
|
26
|
-
]
|
|
27
|
-
}
|
|
28
|
-
}
|
package/CLAUDE.md
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
This document provides foundational mandates and expert guidance. These instructions take precedence over general workflows.
|
|
2
|
-
|
|
3
|
-
## Technical Standards
|
|
4
|
-
|
|
5
|
-
- Consistency: Compatibiilty is important, only break it for Good Cause.
|
|
6
|
-
- Research: Identify the relevant RFC(s). Analyze existing implementation and verify conformance.
|
|
7
|
-
- JS features: this project targets LTS versions of Node.js and/or modern web browsers.
|
|
8
|
-
- ES2024 features should be preferred over legacy patterns.
|
|
9
|
-
- When updating files, add `node:` prefixes to any Node.js built-in `require()` calls that lack them (e.g. `require('fs')` → `require('node:fs')`)
|
|
10
|
-
- Use Conventional Commit format for all commit messages.
|
|
11
|
-
- Prefer for..(of|in) iterators over forEach
|
|
12
|
-
- Prefer node:readline for parsing files into lines
|
|
13
|
-
|
|
14
|
-
## Testing
|
|
15
|
-
|
|
16
|
-
- Empirical Reproduction: For bug fixes, first create a failing test case in the corresponding test file.
|
|
17
|
-
- Coverage: Every new feature MUST have a corresponding test file with high coverage.
|
|
18
|
-
- Linting & Formatting: Adhere to the project's `eslint` and `prettier` configurations.
|
|
19
|
-
- Migrate existing tests from mocha to `node --test`
|
|
20
|
-
- when loading node:assert, load it as node:assert/strict
|
|
21
|
-
|
|
22
|
-
## Tooling Commands
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# Test
|
|
26
|
-
npm run test # Run full test suite
|
|
27
|
-
npm run test:coverage # Run tests with coverage
|
|
28
|
-
node --test test/path/to/file.js # Run a single test file (node:test packages)
|
|
29
|
-
|
|
30
|
-
# Lint & Format
|
|
31
|
-
npm run lint # Check for linting errors.
|
|
32
|
-
npm run lint:fix # Auto-fix lint issues
|
|
33
|
-
npm run prettier # Check formatting
|
|
34
|
-
npm run prettier:fix # Auto-format
|
|
35
|
-
npm run format # prettier:fix + lint:fix (run before committing)
|
|
36
|
-
|
|
37
|
-
# Dependency version management
|
|
38
|
-
npm run versions # Check for version drift
|
|
39
|
-
npm run versions:fix # Update versions
|
|
40
|
-
```
|
package/GEMINI.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
This document provides foundational mandates and expert guidance. These instructions take precedence over general workflows.
|
|
2
|
-
|
|
3
|
-
## Technical Standards
|
|
4
|
-
- Don't change the code unless specifically asked.
|
|
5
|
-
- Consistency: Compatibiilty is important, only break it for Good Cause.
|
|
6
|
-
- Research: Identify the relevant RFC(s). Analyze existing implementation and verify conformance.
|
|
7
|
-
- JS features: this project targets LTS versions of Node.js and/or modern web browsers. Therefore, JS2024 features should be preferred over legacy patterns.
|
|
8
|
-
- When updating files, add `node:` prefixes to any Node.js built-in `require()` calls that lack them (e.g. `require('fs')` → `require('node:fs')`)
|
|
9
|
-
- Use Conventional Commit format for all commit messages.
|
|
10
|
-
- Prefer for..(of|in) iterators over forEach
|
|
11
|
-
- Prefer node:readline for parsing files into lines
|
|
12
|
-
|
|
13
|
-
## Testing
|
|
14
|
-
- Empirical Reproduction: For bug fixes, first create a failing test case in the corresponding test file.
|
|
15
|
-
- Coverage: Every new feature MUST have a corresponding test file with high coverage.
|
|
16
|
-
- Linting & Formatting: Adhere to the project's `eslint` and `prettier` configurations.
|
|
17
|
-
- Migrate existing tests from mocha to `node --test`
|
|
18
|
-
- when loading node:assert, prefer to load it as node:assert/strict
|
|
19
|
-
|
|
20
|
-
## Tooling Commands
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# Test
|
|
24
|
-
npm run test # Run full test suite
|
|
25
|
-
npm run test:coverage # Run tests with coverage
|
|
26
|
-
node --test test/path/to/file.js # Run a single test file (node:test packages)
|
|
27
|
-
|
|
28
|
-
# Lint & Format
|
|
29
|
-
npm run lint # Check for linting errors.
|
|
30
|
-
npm run lint:fix # Auto-fix lint issues
|
|
31
|
-
npm run prettier # Check formatting
|
|
32
|
-
npm run prettier:fix # Auto-format
|
|
33
|
-
npm run format # prettier:fix + lint:fix (run before committing)
|
|
34
|
-
|
|
35
|
-
# Dependency version management
|
|
36
|
-
npm run versions # Check for version drift
|
|
37
|
-
npm run versions:fix # Update versions
|
|
38
|
-
```
|