Haraka 3.1.0 → 3.1.2

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 (160) hide show
  1. package/.prettierignore +4 -0
  2. package/CONTRIBUTORS.md +5 -5
  3. package/Changes.md +69 -50
  4. package/Plugins.md +3 -1
  5. package/README.md +1 -1
  6. package/bin/haraka +475 -478
  7. package/config/outbound.ini +3 -0
  8. package/connection.js +1072 -1108
  9. package/docs/Connection.md +29 -30
  10. package/docs/CoreConfig.md +38 -39
  11. package/docs/CustomReturnCodes.md +0 -1
  12. package/docs/HAProxy.md +2 -2
  13. package/docs/Header.md +1 -1
  14. package/docs/Logging.md +29 -5
  15. package/docs/Outbound.md +93 -78
  16. package/docs/Plugins.md +103 -108
  17. package/docs/Transaction.md +49 -51
  18. package/docs/Tutorial.md +127 -143
  19. package/docs/deprecated/access.md +0 -1
  20. package/docs/deprecated/backscatterer.md +2 -3
  21. package/docs/deprecated/connect.rdns_access.md +18 -27
  22. package/docs/deprecated/data.headers.md +0 -1
  23. package/docs/deprecated/data.nomsgid.md +1 -2
  24. package/docs/deprecated/data.noreceived.md +1 -2
  25. package/docs/deprecated/data.rfc5322_header_checks.md +1 -2
  26. package/docs/deprecated/dkim_sign.md +13 -17
  27. package/docs/deprecated/dkim_verify.md +9 -17
  28. package/docs/deprecated/dnsbl.md +36 -38
  29. package/docs/deprecated/dnswl.md +41 -43
  30. package/docs/deprecated/lookup_rdns.strict.md +21 -34
  31. package/docs/deprecated/mail_from.access.md +17 -25
  32. package/docs/deprecated/mail_from.blocklist.md +9 -12
  33. package/docs/deprecated/mail_from.nobounces.md +1 -2
  34. package/docs/deprecated/rcpt_to.access.md +20 -27
  35. package/docs/deprecated/rcpt_to.blocklist.md +10 -13
  36. package/docs/deprecated/rcpt_to.routes.md +0 -1
  37. package/docs/deprecated/rdns.regexp.md +13 -15
  38. package/docs/plugins/aliases.md +89 -89
  39. package/docs/plugins/auth/auth_bridge.md +5 -7
  40. package/docs/plugins/auth/auth_ldap.md +11 -14
  41. package/docs/plugins/auth/auth_proxy.md +10 -12
  42. package/docs/plugins/auth/auth_vpopmaild.md +5 -6
  43. package/docs/plugins/auth/flat_file.md +4 -4
  44. package/docs/plugins/block_me.md +3 -3
  45. package/docs/plugins/data.signatures.md +1 -2
  46. package/docs/plugins/delay_deny.md +3 -4
  47. package/docs/plugins/max_unrecognized_commands.md +4 -4
  48. package/docs/plugins/prevent_credential_leaks.md +6 -6
  49. package/docs/plugins/process_title.md +18 -18
  50. package/docs/plugins/queue/deliver.md +2 -3
  51. package/docs/plugins/queue/discard.md +4 -4
  52. package/docs/plugins/queue/lmtp.md +1 -3
  53. package/docs/plugins/queue/qmail-queue.md +7 -9
  54. package/docs/plugins/queue/quarantine.md +16 -21
  55. package/docs/plugins/queue/rabbitmq.md +8 -11
  56. package/docs/plugins/queue/rabbitmq_amqplib.md +43 -39
  57. package/docs/plugins/queue/smtp_bridge.md +7 -10
  58. package/docs/plugins/queue/smtp_forward.md +42 -34
  59. package/docs/plugins/queue/smtp_proxy.md +30 -29
  60. package/docs/plugins/queue/test.md +1 -3
  61. package/docs/plugins/rcpt_to.in_host_list.md +6 -6
  62. package/docs/plugins/rcpt_to.max_count.md +1 -1
  63. package/docs/plugins/record_envelope_addresses.md +3 -3
  64. package/docs/plugins/reseed_rng.md +6 -6
  65. package/docs/plugins/status.md +9 -8
  66. package/docs/plugins/tarpit.md +7 -11
  67. package/docs/plugins/tls.md +12 -17
  68. package/docs/plugins/toobusy.md +4 -4
  69. package/docs/plugins/xclient.md +3 -3
  70. package/docs/tutorials/Migrating_from_v1_to_v2.md +19 -41
  71. package/docs/tutorials/SettingUpOutbound.md +6 -9
  72. package/endpoint.js +35 -38
  73. package/eslint.config.mjs +22 -19
  74. package/haraka.js +42 -47
  75. package/host_pool.js +75 -79
  76. package/http/html/404.html +45 -49
  77. package/http/html/index.html +39 -28
  78. package/http/package.json +2 -4
  79. package/line_socket.js +27 -28
  80. package/logger.js +182 -201
  81. package/outbound/client_pool.js +34 -27
  82. package/outbound/config.js +64 -59
  83. package/outbound/fsync_writestream.js +24 -25
  84. package/outbound/hmail.js +888 -835
  85. package/outbound/index.js +194 -187
  86. package/outbound/qfile.js +49 -52
  87. package/outbound/queue.js +197 -190
  88. package/outbound/timer_queue.js +41 -43
  89. package/outbound/tls.js +68 -61
  90. package/outbound/todo.js +11 -11
  91. package/package.json +38 -33
  92. package/plugins/.eslintrc.yaml +0 -1
  93. package/plugins/auth/auth_base.js +123 -127
  94. package/plugins/auth/auth_bridge.js +7 -7
  95. package/plugins/auth/auth_proxy.js +121 -126
  96. package/plugins/auth/auth_vpopmaild.js +84 -85
  97. package/plugins/auth/flat_file.js +18 -17
  98. package/plugins/block_me.js +31 -31
  99. package/plugins/data.signatures.js +13 -13
  100. package/plugins/delay_deny.js +65 -61
  101. package/plugins/prevent_credential_leaks.js +23 -23
  102. package/plugins/process_title.js +125 -128
  103. package/plugins/profile.js +5 -5
  104. package/plugins/queue/deliver.js +3 -3
  105. package/plugins/queue/discard.js +13 -14
  106. package/plugins/queue/lmtp.js +16 -17
  107. package/plugins/queue/qmail-queue.js +54 -55
  108. package/plugins/queue/quarantine.js +68 -70
  109. package/plugins/queue/rabbitmq.js +80 -87
  110. package/plugins/queue/rabbitmq_amqplib.js +75 -54
  111. package/plugins/queue/smtp_bridge.js +16 -16
  112. package/plugins/queue/smtp_forward.js +175 -179
  113. package/plugins/queue/smtp_proxy.js +69 -71
  114. package/plugins/queue/test.js +9 -9
  115. package/plugins/rcpt_to.host_list_base.js +30 -34
  116. package/plugins/rcpt_to.in_host_list.js +19 -19
  117. package/plugins/record_envelope_addresses.js +4 -4
  118. package/plugins/reseed_rng.js +4 -4
  119. package/plugins/status.js +90 -97
  120. package/plugins/tarpit.js +25 -14
  121. package/plugins/tls.js +68 -68
  122. package/plugins/toobusy.js +21 -23
  123. package/plugins/xclient.js +51 -53
  124. package/plugins.js +276 -293
  125. package/rfc1869.js +30 -35
  126. package/server.js +308 -299
  127. package/smtp_client.js +244 -228
  128. package/test/.eslintrc.yaml +0 -1
  129. package/test/connection.js +127 -134
  130. package/test/endpoint.js +53 -47
  131. package/test/fixtures/line_socket.js +12 -12
  132. package/test/fixtures/util_hmailitem.js +89 -85
  133. package/test/host_pool.js +90 -92
  134. package/test/installation/plugins/base_plugin.js +2 -2
  135. package/test/installation/plugins/folder_plugin/index.js +2 -3
  136. package/test/installation/plugins/inherits.js +3 -3
  137. package/test/installation/plugins/load_first.js +2 -3
  138. package/test/installation/plugins/plugin.js +1 -3
  139. package/test/installation/plugins/tls.js +2 -4
  140. package/test/logger.js +135 -116
  141. package/test/outbound/hmail.js +49 -35
  142. package/test/outbound/index.js +118 -101
  143. package/test/outbound/qfile.js +51 -53
  144. package/test/outbound_bounce_net_errors.js +84 -69
  145. package/test/outbound_bounce_rfc3464.js +235 -165
  146. package/test/plugins/auth/auth_base.js +420 -279
  147. package/test/plugins/auth/auth_vpopmaild.js +38 -39
  148. package/test/plugins/queue/smtp_forward.js +126 -104
  149. package/test/plugins/rcpt_to.host_list_base.js +85 -67
  150. package/test/plugins/rcpt_to.in_host_list.js +159 -112
  151. package/test/plugins/status.js +71 -64
  152. package/test/plugins/tls.js +37 -34
  153. package/test/plugins.js +97 -92
  154. package/test/rfc1869.js +19 -26
  155. package/test/server.js +293 -272
  156. package/test/smtp_client.js +180 -176
  157. package/test/tls_socket.js +62 -66
  158. package/test/transaction.js +159 -160
  159. package/tls_socket.js +331 -333
  160. package/transaction.js +129 -137
@@ -1,49 +1,47 @@
1
1
  // Stop accepting new connections when we are too busy
2
2
 
3
- let toobusy;
4
- let was_busy = false;
3
+ let toobusy
4
+ let was_busy = false
5
5
 
6
6
  exports.register = function () {
7
-
8
7
  try {
9
- toobusy = require('toobusy-js');
10
- }
11
- catch (e) {
12
- this.logerror(e);
13
- this.logerror("try: 'npm install -g toobusy-js'");
14
- return;
8
+ toobusy = require('toobusy-js')
9
+ } catch (e) {
10
+ this.logerror(e)
11
+ this.logerror("try: 'npm install -g toobusy-js'")
12
+ return
15
13
  }
16
14
 
17
- this.loadConfig();
15
+ this.loadConfig()
18
16
 
19
- this.register_hook('connect', 'check_busy', -100);
17
+ this.register_hook('connect', 'check_busy', -100)
20
18
  }
21
19
 
22
20
  exports.loadConfig = function () {
23
- let maxLag = this.config.get('toobusy.maxlag','value', () => {
24
- this.loadConfig();
25
- });
21
+ let maxLag = this.config.get('toobusy.maxlag', 'value', () => {
22
+ this.loadConfig()
23
+ })
26
24
 
27
- maxLag = parseInt(maxLag);
25
+ maxLag = parseInt(maxLag)
28
26
  if (maxLag) {
29
27
  // This will throw an exception on error
30
- toobusy.maxLag(maxLag);
28
+ toobusy.maxLag(maxLag)
31
29
  }
32
30
  }
33
31
 
34
32
  exports.check_busy = function (next, connection) {
35
33
  if (!toobusy()) {
36
- was_busy = false;
37
- return next();
34
+ was_busy = false
35
+ return next()
38
36
  }
39
37
 
40
38
  if (!was_busy) {
41
- was_busy = true;
39
+ was_busy = true
42
40
  // Log a CRIT error at the first occurrence
43
- const currentLag = toobusy.lag();
44
- const maxLag = toobusy.maxLag();
45
- this.logcrit(`deferring connections: lag=${currentLag} max=${maxLag}`);
41
+ const currentLag = toobusy.lag()
42
+ const maxLag = toobusy.maxLag()
43
+ this.logcrit(`deferring connections: lag=${currentLag} max=${maxLag}`)
46
44
  }
47
45
 
48
- return next(DENYSOFTDISCONNECT, 'Too busy; please try again later');
46
+ return next(DENYSOFTDISCONNECT, 'Too busy; please try again later')
49
47
  }
@@ -1,124 +1,122 @@
1
1
  // Implementation of XCLIENT protocol
2
2
  // See http://www.postfix.org/XCLIENT_README.html
3
3
 
4
- const net = require('node:net');
4
+ const net = require('node:net')
5
5
 
6
- const utils = require('haraka-utils');
7
- const DSN = require('haraka-dsn');
8
- let allowed_hosts = {};
6
+ const utils = require('haraka-utils')
7
+ const DSN = require('haraka-dsn')
8
+ let allowed_hosts = {}
9
9
 
10
10
  exports.register = function () {
11
- this.load_xclient_hosts();
11
+ this.load_xclient_hosts()
12
12
  }
13
13
 
14
14
  exports.load_xclient_hosts = function () {
15
15
  const cfg = this.config.get('xclient.hosts', 'list', () => {
16
- this.load_xclient_hosts();
17
- });
18
- const ah = {};
16
+ this.load_xclient_hosts()
17
+ })
18
+ const ah = {}
19
19
  for (const i in cfg) {
20
- ah[cfg[i]] = true;
20
+ ah[cfg[i]] = true
21
21
  }
22
- allowed_hosts = ah;
22
+ allowed_hosts = ah
23
23
  }
24
24
 
25
- function xclient_allowed (ip) {
26
- return !!(ip === '127.0.0.1' || ip === '::1' || allowed_hosts[ip]);
25
+ function xclient_allowed(ip) {
26
+ return !!(ip === '127.0.0.1' || ip === '::1' || allowed_hosts[ip])
27
27
  }
28
28
 
29
29
  exports.hook_capabilities = (next, connection) => {
30
30
  if (xclient_allowed(connection.remote.ip)) {
31
- connection.capabilities.push('XCLIENT NAME ADDR PROTO HELO LOGIN');
31
+ connection.capabilities.push('XCLIENT NAME ADDR PROTO HELO LOGIN')
32
32
  }
33
- next();
33
+ next()
34
34
  }
35
35
 
36
36
  exports.hook_unrecognized_command = function (next, connection, params) {
37
- if (params[0] !== 'XCLIENT') return next();
37
+ if (params[0] !== 'XCLIENT') return next()
38
38
 
39
39
  // XCLIENT is not allowed after transaction start
40
40
  if (connection?.transaction) {
41
- return next(DENY, DSN.proto_unspecified('Mail transaction in progress', 503));
41
+ return next(DENY, DSN.proto_unspecified('Mail transaction in progress', 503))
42
42
  }
43
43
 
44
- if (!(xclient_allowed(connection?.remote?.ip))) {
45
- return next(DENY, DSN.proto_unspecified('Not authorized', 550));
44
+ if (!xclient_allowed(connection?.remote?.ip)) {
45
+ return next(DENY, DSN.proto_unspecified('Not authorized', 550))
46
46
  }
47
47
 
48
48
  // If we get here - the client is allowed to use XCLIENT
49
49
  // Process arguments
50
- const args = (new String(params[1])).toLowerCase().split(/ /);
51
- const xclient = {};
50
+ const args = new String(params[1]).toLowerCase().split(/ /)
51
+ const xclient = {}
52
52
  for (const arg of args) {
53
- const match = /^([^=]+)=([^ ]+)/.exec(arg);
53
+ const match = /^([^=]+)=([^ ]+)/.exec(arg)
54
54
  if (match) {
55
- connection.logdebug(this, `found key=${match[1]} value=${match[2]}`);
55
+ connection.logdebug(this, `found key=${match[1]} value=${match[2]}`)
56
56
  switch (match[1]) {
57
57
  case 'destaddr':
58
58
  case 'addr': {
59
59
  // IPv6 is prefixed in the XCLIENT protocol
60
- let ipv6;
60
+ let ipv6
61
61
  if ((ipv6 = /^IPV6:(.+)$/i.exec(match[2]))) {
62
62
  // Validate
63
63
  if (net.isIPv6(ipv6[1])) {
64
- xclient[match[1]] = ipv6[1];
64
+ xclient[match[1]] = ipv6[1]
65
65
  }
66
- }
67
- else if (!/\[UNAVAILABLE\]/i.test(match[2])) {
66
+ } else if (!/\[UNAVAILABLE\]/i.test(match[2])) {
68
67
  // IPv4
69
68
  if (net.isIPv4(match[2])) {
70
- xclient[match[1]] = match[2];
69
+ xclient[match[1]] = match[2]
71
70
  }
72
71
  }
73
- break;
72
+ break
74
73
  }
75
74
  case 'proto':
76
75
  // SMTP or ESMTP
77
76
  if (/^e?smtp/i.test(match[2])) {
78
- xclient[match[1]] = match[2];
77
+ xclient[match[1]] = match[2]
79
78
  }
80
- break;
79
+ break
81
80
  case 'name':
82
81
  case 'port':
83
82
  case 'helo':
84
83
  case 'login':
85
84
  case 'destport':
86
85
  if (!/\[(UNAVAILABLE|TEMPUNAVAIL)\]/i.test(match[2])) {
87
- xclient[match[1]] = match[2];
86
+ xclient[match[1]] = match[2]
88
87
  }
89
- break;
88
+ break
90
89
  default:
91
- connection.logwarn(this, `unknown argument: ${arg}`);
90
+ connection.logwarn(this, `unknown argument: ${arg}`)
92
91
  }
93
- }
94
- else {
95
- connection.logwarn(this, `unknown argument: ${arg}`);
92
+ } else {
93
+ connection.logwarn(this, `unknown argument: ${arg}`)
96
94
  }
97
95
  }
98
96
 
99
97
  // Abort if we don't have a valid IP address
100
98
  if (!xclient.addr) {
101
- return next(DENY, DSN.proto_invalid_cmd_args('No valid IP address found', 501));
99
+ return next(DENY, DSN.proto_invalid_cmd_args('No valid IP address found', 501))
102
100
  }
103
101
 
104
102
  // Apply changes
105
- const new_uuid = utils.uuid();
106
- connection.loginfo(this, `new uuid=${new_uuid}`);
107
- connection.uuid = new_uuid;
108
- connection.reset_transaction();
109
- connection.relaying = false;
110
- connection.set('remote.ip', xclient.addr);
111
- connection.set('remote.host', ((xclient.name) ? xclient.name : undefined));
112
- connection.set('remote.login', ((xclient.login) ? xclient.login : undefined));
113
- connection.set('hello.host', ((xclient.helo) ? xclient.helo : undefined));
114
- connection.set('local.ip', ((xclient.destaddr) ? xclient.destaddr : undefined));
115
- connection.set('local.port', ((xclient.destport) ? xclient.destport: undefined));
103
+ const new_uuid = utils.uuid()
104
+ connection.loginfo(this, `new uuid=${new_uuid}`)
105
+ connection.uuid = new_uuid
106
+ connection.reset_transaction()
107
+ connection.relaying = false
108
+ connection.set('remote.ip', xclient.addr)
109
+ connection.set('remote.host', xclient.name ? xclient.name : undefined)
110
+ connection.set('remote.login', xclient.login ? xclient.login : undefined)
111
+ connection.set('hello.host', xclient.helo ? xclient.helo : undefined)
112
+ connection.set('local.ip', xclient.destaddr ? xclient.destaddr : undefined)
113
+ connection.set('local.port', xclient.destport ? xclient.destport : undefined)
116
114
  if (xclient.proto) {
117
- connection.set('hello', 'verb', ((xclient.proto === 'esmtp') ? 'EHLO' : 'HELO'));
115
+ connection.set('hello', 'verb', xclient.proto === 'esmtp' ? 'EHLO' : 'HELO')
118
116
  }
119
- connection.esmtp = (xclient.proto === 'esmtp');
120
- connection.xclient = true;
121
- if (!xclient.name) return next(NEXT_HOOK, 'lookup_rdns');
117
+ connection.esmtp = xclient.proto === 'esmtp'
118
+ connection.xclient = true
119
+ if (!xclient.name) return next(NEXT_HOOK, 'lookup_rdns')
122
120
 
123
- next(NEXT_HOOK, 'connect');
121
+ next(NEXT_HOOK, 'connect')
124
122
  }