Haraka 3.1.1 → 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.
- package/.prettierignore +4 -0
- package/CONTRIBUTORS.md +5 -5
- package/Changes.md +62 -50
- package/Plugins.md +3 -1
- package/README.md +1 -1
- package/bin/haraka +475 -479
- package/config/outbound.ini +3 -0
- package/connection.js +1072 -1108
- package/docs/Connection.md +29 -30
- package/docs/CoreConfig.md +38 -39
- package/docs/CustomReturnCodes.md +0 -1
- package/docs/HAProxy.md +2 -2
- package/docs/Header.md +1 -1
- package/docs/Logging.md +29 -5
- package/docs/Outbound.md +93 -78
- package/docs/Plugins.md +103 -108
- package/docs/Transaction.md +49 -51
- package/docs/Tutorial.md +127 -143
- package/docs/deprecated/access.md +0 -1
- package/docs/deprecated/backscatterer.md +2 -3
- package/docs/deprecated/connect.rdns_access.md +18 -27
- package/docs/deprecated/data.headers.md +0 -1
- package/docs/deprecated/data.nomsgid.md +1 -2
- package/docs/deprecated/data.noreceived.md +1 -2
- package/docs/deprecated/data.rfc5322_header_checks.md +1 -2
- package/docs/deprecated/dkim_sign.md +13 -17
- package/docs/deprecated/dkim_verify.md +9 -17
- package/docs/deprecated/dnsbl.md +36 -38
- package/docs/deprecated/dnswl.md +41 -43
- package/docs/deprecated/lookup_rdns.strict.md +21 -34
- package/docs/deprecated/mail_from.access.md +17 -25
- package/docs/deprecated/mail_from.blocklist.md +9 -12
- package/docs/deprecated/mail_from.nobounces.md +1 -2
- package/docs/deprecated/rcpt_to.access.md +20 -27
- package/docs/deprecated/rcpt_to.blocklist.md +10 -13
- package/docs/deprecated/rcpt_to.routes.md +0 -1
- package/docs/deprecated/rdns.regexp.md +13 -15
- package/docs/plugins/aliases.md +89 -89
- package/docs/plugins/auth/auth_bridge.md +5 -7
- package/docs/plugins/auth/auth_ldap.md +11 -14
- package/docs/plugins/auth/auth_proxy.md +10 -12
- package/docs/plugins/auth/auth_vpopmaild.md +5 -6
- package/docs/plugins/auth/flat_file.md +4 -4
- package/docs/plugins/block_me.md +3 -3
- package/docs/plugins/data.signatures.md +1 -2
- package/docs/plugins/delay_deny.md +3 -4
- package/docs/plugins/max_unrecognized_commands.md +4 -4
- package/docs/plugins/prevent_credential_leaks.md +6 -6
- package/docs/plugins/process_title.md +18 -18
- package/docs/plugins/queue/deliver.md +2 -3
- package/docs/plugins/queue/discard.md +4 -4
- package/docs/plugins/queue/lmtp.md +1 -3
- package/docs/plugins/queue/qmail-queue.md +7 -9
- package/docs/plugins/queue/quarantine.md +16 -21
- package/docs/plugins/queue/rabbitmq.md +8 -11
- package/docs/plugins/queue/rabbitmq_amqplib.md +43 -39
- package/docs/plugins/queue/smtp_bridge.md +7 -10
- package/docs/plugins/queue/smtp_forward.md +42 -34
- package/docs/plugins/queue/smtp_proxy.md +30 -29
- package/docs/plugins/queue/test.md +1 -3
- package/docs/plugins/rcpt_to.in_host_list.md +6 -6
- package/docs/plugins/rcpt_to.max_count.md +1 -1
- package/docs/plugins/record_envelope_addresses.md +3 -3
- package/docs/plugins/reseed_rng.md +6 -6
- package/docs/plugins/status.md +9 -8
- package/docs/plugins/tarpit.md +7 -11
- package/docs/plugins/tls.md +12 -17
- package/docs/plugins/toobusy.md +4 -4
- package/docs/plugins/xclient.md +3 -3
- package/docs/tutorials/Migrating_from_v1_to_v2.md +19 -41
- package/docs/tutorials/SettingUpOutbound.md +6 -9
- package/endpoint.js +35 -38
- package/eslint.config.mjs +22 -19
- package/haraka.js +42 -47
- package/host_pool.js +75 -79
- package/http/html/404.html +45 -49
- package/http/html/index.html +39 -28
- package/http/package.json +2 -4
- package/line_socket.js +27 -28
- package/logger.js +182 -201
- package/outbound/client_pool.js +33 -33
- package/outbound/config.js +64 -59
- package/outbound/fsync_writestream.js +24 -25
- package/outbound/hmail.js +888 -835
- package/outbound/index.js +194 -187
- package/outbound/qfile.js +49 -52
- package/outbound/queue.js +197 -190
- package/outbound/timer_queue.js +41 -43
- package/outbound/tls.js +68 -61
- package/outbound/todo.js +11 -11
- package/package.json +32 -32
- package/plugins/.eslintrc.yaml +0 -1
- package/plugins/auth/auth_base.js +123 -127
- package/plugins/auth/auth_bridge.js +7 -7
- package/plugins/auth/auth_proxy.js +121 -126
- package/plugins/auth/auth_vpopmaild.js +84 -85
- package/plugins/auth/flat_file.js +18 -17
- package/plugins/block_me.js +31 -31
- package/plugins/data.signatures.js +13 -13
- package/plugins/delay_deny.js +65 -61
- package/plugins/prevent_credential_leaks.js +23 -23
- package/plugins/process_title.js +125 -128
- package/plugins/profile.js +5 -5
- package/plugins/queue/deliver.js +3 -3
- package/plugins/queue/discard.js +13 -14
- package/plugins/queue/lmtp.js +16 -17
- package/plugins/queue/qmail-queue.js +54 -55
- package/plugins/queue/quarantine.js +68 -70
- package/plugins/queue/rabbitmq.js +80 -87
- package/plugins/queue/rabbitmq_amqplib.js +75 -54
- package/plugins/queue/smtp_bridge.js +16 -16
- package/plugins/queue/smtp_forward.js +175 -179
- package/plugins/queue/smtp_proxy.js +69 -71
- package/plugins/queue/test.js +9 -9
- package/plugins/rcpt_to.host_list_base.js +30 -34
- package/plugins/rcpt_to.in_host_list.js +19 -19
- package/plugins/record_envelope_addresses.js +4 -4
- package/plugins/reseed_rng.js +4 -4
- package/plugins/status.js +90 -97
- package/plugins/tarpit.js +25 -14
- package/plugins/tls.js +68 -68
- package/plugins/toobusy.js +21 -23
- package/plugins/xclient.js +51 -53
- package/plugins.js +276 -293
- package/rfc1869.js +30 -35
- package/server.js +308 -299
- package/smtp_client.js +244 -228
- package/test/.eslintrc.yaml +0 -1
- package/test/connection.js +127 -134
- package/test/endpoint.js +53 -47
- package/test/fixtures/line_socket.js +12 -12
- package/test/fixtures/util_hmailitem.js +89 -85
- package/test/host_pool.js +90 -92
- package/test/installation/plugins/base_plugin.js +2 -2
- package/test/installation/plugins/folder_plugin/index.js +2 -3
- package/test/installation/plugins/inherits.js +3 -3
- package/test/installation/plugins/load_first.js +2 -3
- package/test/installation/plugins/plugin.js +1 -3
- package/test/installation/plugins/tls.js +2 -4
- package/test/logger.js +135 -116
- package/test/outbound/hmail.js +49 -35
- package/test/outbound/index.js +118 -101
- package/test/outbound/qfile.js +51 -53
- package/test/outbound_bounce_net_errors.js +84 -69
- package/test/outbound_bounce_rfc3464.js +235 -165
- package/test/plugins/auth/auth_base.js +420 -279
- package/test/plugins/auth/auth_vpopmaild.js +38 -39
- package/test/plugins/queue/smtp_forward.js +126 -104
- package/test/plugins/rcpt_to.host_list_base.js +85 -67
- package/test/plugins/rcpt_to.in_host_list.js +159 -112
- package/test/plugins/status.js +71 -64
- package/test/plugins/tls.js +37 -34
- package/test/plugins.js +97 -92
- package/test/rfc1869.js +19 -26
- package/test/server.js +293 -272
- package/test/smtp_client.js +180 -176
- package/test/tls_socket.js +62 -66
- package/test/transaction.js +159 -160
- package/tls_socket.js +331 -333
- package/transaction.js +129 -137
package/host_pool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
|
-
const net
|
|
4
|
-
const utils
|
|
3
|
+
const net = require('node:net')
|
|
4
|
+
const utils = require('haraka-utils')
|
|
5
5
|
|
|
6
6
|
/* HostPool:
|
|
7
7
|
*
|
|
@@ -21,31 +21,30 @@ const utils = require('haraka-utils');
|
|
|
21
21
|
* network failure from taking the whole system down.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
const logger = require('./logger')
|
|
24
|
+
const logger = require('./logger')
|
|
25
25
|
|
|
26
26
|
class HostPool {
|
|
27
|
-
|
|
28
27
|
// takes a comma/space-separated list of ip:ports
|
|
29
28
|
// 1.1.1.1:22, 3.3.3.3:44
|
|
30
|
-
constructor
|
|
29
|
+
constructor(hostports_str, retry_secs) {
|
|
31
30
|
const hosts = (hostports_str || '')
|
|
32
31
|
.trim()
|
|
33
32
|
.split(/[\s,]+/)
|
|
34
|
-
.map(hostport => {
|
|
35
|
-
const splithost = hostport.split(/:/)
|
|
36
|
-
if (!
|
|
37
|
-
splithost[1] = 25
|
|
33
|
+
.map((hostport) => {
|
|
34
|
+
const splithost = hostport.split(/:/)
|
|
35
|
+
if (!splithost[1]) {
|
|
36
|
+
splithost[1] = 25
|
|
38
37
|
}
|
|
39
38
|
return {
|
|
40
39
|
host: splithost[0],
|
|
41
|
-
port: splithost[1]
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
this.hostports_str = hostports_str
|
|
45
|
-
this.hosts = utils.shuffle(hosts)
|
|
46
|
-
this.dead_hosts = {}
|
|
47
|
-
this.last_i = 0
|
|
48
|
-
this.retry_secs = retry_secs || 10
|
|
40
|
+
port: splithost[1],
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
this.hostports_str = hostports_str
|
|
44
|
+
this.hosts = utils.shuffle(hosts)
|
|
45
|
+
this.dead_hosts = {} // hostport => true/false
|
|
46
|
+
this.last_i = 0 // the last one we checked
|
|
47
|
+
this.retry_secs = retry_secs || 10
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
/* failed
|
|
@@ -54,30 +53,30 @@ class HostPool {
|
|
|
54
53
|
* this backend host and it'll come out of the pool and put into the recheck
|
|
55
54
|
* timer.
|
|
56
55
|
*/
|
|
57
|
-
failed
|
|
58
|
-
const self = this
|
|
59
|
-
const key = `${host}:${port}
|
|
60
|
-
const retry_msecs = self.retry_secs * 1000
|
|
61
|
-
self.dead_hosts[key] = true
|
|
62
|
-
|
|
63
|
-
function cb_if_still_dead
|
|
64
|
-
logger.warn(`${host} ${key} is still dead, will retry in ${self.retry_secs} secs`)
|
|
65
|
-
self.dead_hosts[key] = true
|
|
56
|
+
failed(host, port) {
|
|
57
|
+
const self = this
|
|
58
|
+
const key = `${host}:${port}`
|
|
59
|
+
const retry_msecs = self.retry_secs * 1000
|
|
60
|
+
self.dead_hosts[key] = true
|
|
61
|
+
|
|
62
|
+
function cb_if_still_dead() {
|
|
63
|
+
logger.warn(`${host} ${key} is still dead, will retry in ${self.retry_secs} secs`)
|
|
64
|
+
self.dead_hosts[key] = true
|
|
66
65
|
// console.log(1);
|
|
67
66
|
setTimeout(() => {
|
|
68
|
-
self.probe_dead_host(host, port, cb_if_still_dead, cb_if_alive)
|
|
69
|
-
}, retry_msecs)
|
|
67
|
+
self.probe_dead_host(host, port, cb_if_still_dead, cb_if_alive)
|
|
68
|
+
}, retry_msecs)
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
function cb_if_alive
|
|
71
|
+
function cb_if_alive() {
|
|
73
72
|
// console.log(2);
|
|
74
|
-
logger.info(`${host} ${key} is back! adding back into pool`)
|
|
75
|
-
delete self.dead_hosts[key]
|
|
73
|
+
logger.info(`${host} ${key} is back! adding back into pool`)
|
|
74
|
+
delete self.dead_hosts[key]
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
setTimeout(() => {
|
|
79
|
-
self.probe_dead_host(host, port, cb_if_still_dead, cb_if_alive)
|
|
80
|
-
}, retry_msecs)
|
|
78
|
+
self.probe_dead_host(host, port, cb_if_still_dead, cb_if_alive)
|
|
79
|
+
}, retry_msecs)
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/* probe_dead_host
|
|
@@ -87,35 +86,32 @@ class HostPool {
|
|
|
87
86
|
* dead_hosts lists, and the next time get_host() is called, it'll be in the
|
|
88
87
|
* mix.
|
|
89
88
|
*/
|
|
90
|
-
probe_dead_host
|
|
91
|
-
host
|
|
92
|
-
){
|
|
93
|
-
logger.info(`probing dead host ${host}:${port}`);
|
|
89
|
+
probe_dead_host(host, port, cb_if_still_dead, cb_if_alive) {
|
|
90
|
+
logger.info(`probing dead host ${host}:${port}`)
|
|
94
91
|
|
|
95
|
-
const connect_timeout_ms = 200
|
|
96
|
-
let s
|
|
92
|
+
const connect_timeout_ms = 200 // keep it snappy
|
|
93
|
+
let s
|
|
97
94
|
try {
|
|
98
|
-
s = this.get_socket()
|
|
95
|
+
s = this.get_socket()
|
|
99
96
|
s.setTimeout(connect_timeout_ms, () => {
|
|
100
97
|
// nobody home, it's still dead
|
|
101
|
-
s.destroy()
|
|
102
|
-
cb_if_still_dead()
|
|
103
|
-
})
|
|
104
|
-
s.on('error', e => {
|
|
98
|
+
s.destroy()
|
|
99
|
+
cb_if_still_dead()
|
|
100
|
+
})
|
|
101
|
+
s.on('error', (e) => {
|
|
105
102
|
// silently catch all errors - assume the port is closed
|
|
106
|
-
s.destroy()
|
|
107
|
-
cb_if_still_dead()
|
|
108
|
-
})
|
|
103
|
+
s.destroy()
|
|
104
|
+
cb_if_still_dead()
|
|
105
|
+
})
|
|
109
106
|
|
|
110
107
|
s.connect(port, host, () => {
|
|
111
|
-
cb_if_alive()
|
|
112
|
-
s.destroy()
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
108
|
+
cb_if_alive()
|
|
109
|
+
s.destroy() // will this conflict with setTimeout's s.destroy?
|
|
110
|
+
})
|
|
111
|
+
} catch (e) {
|
|
116
112
|
// only way to catch run-time javascript errors in here;
|
|
117
|
-
console.log(`ERROR in probe_dead_host, got error ${e}`)
|
|
118
|
-
throw e
|
|
113
|
+
console.log(`ERROR in probe_dead_host, got error ${e}`)
|
|
114
|
+
throw e
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
117
|
|
|
@@ -123,8 +119,8 @@ class HostPool {
|
|
|
123
119
|
*
|
|
124
120
|
* so we can override in unit test
|
|
125
121
|
*/
|
|
126
|
-
get_socket
|
|
127
|
-
return new net.Socket()
|
|
122
|
+
get_socket() {
|
|
123
|
+
return new net.Socket()
|
|
128
124
|
}
|
|
129
125
|
|
|
130
126
|
/* get_host
|
|
@@ -135,39 +131,39 @@ class HostPool {
|
|
|
135
131
|
* anyway. That should make it more forgiving about transient but widespread
|
|
136
132
|
* network problems that make all the hosts look dead.
|
|
137
133
|
*/
|
|
138
|
-
get_host
|
|
139
|
-
let host
|
|
140
|
-
let found
|
|
134
|
+
get_host() {
|
|
135
|
+
let host
|
|
136
|
+
let found
|
|
141
137
|
|
|
142
|
-
let first_i = this.last_i + 1
|
|
143
|
-
if (first_i >= this.hosts.length){
|
|
144
|
-
first_i = 0
|
|
138
|
+
let first_i = this.last_i + 1
|
|
139
|
+
if (first_i >= this.hosts.length) {
|
|
140
|
+
first_i = 0
|
|
145
141
|
}
|
|
146
142
|
|
|
147
|
-
for (let i = 0; i < this.hosts.length; ++i){
|
|
148
|
-
let j = i + first_i
|
|
143
|
+
for (let i = 0; i < this.hosts.length; ++i) {
|
|
144
|
+
let j = i + first_i
|
|
149
145
|
if (j >= this.hosts.length) {
|
|
150
|
-
j -= this.hosts.length
|
|
146
|
+
j -= this.hosts.length
|
|
151
147
|
}
|
|
152
|
-
host = this.hosts[j]
|
|
153
|
-
const key = `${host.host}:${host.port}
|
|
148
|
+
host = this.hosts[j]
|
|
149
|
+
const key = `${host.host}:${host.port}`
|
|
154
150
|
if (this.dead_hosts[key]) {
|
|
155
|
-
continue
|
|
151
|
+
continue
|
|
156
152
|
}
|
|
157
|
-
this.last_i = j
|
|
158
|
-
found = true
|
|
159
|
-
break
|
|
153
|
+
this.last_i = j
|
|
154
|
+
found = true
|
|
155
|
+
break
|
|
160
156
|
}
|
|
161
157
|
if (found) {
|
|
162
|
-
return host
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
158
|
+
return host
|
|
159
|
+
} else {
|
|
165
160
|
logger.warn(
|
|
166
|
-
`no working hosts found, retrying a dead one, config (probably from smtp_forward.forwarding_host_pool) is '${this.hostports_str}'
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
`no working hosts found, retrying a dead one, config (probably from smtp_forward.forwarding_host_pool) is '${this.hostports_str}'`,
|
|
162
|
+
)
|
|
163
|
+
this.last_i = first_i
|
|
164
|
+
return this.hosts[first_i]
|
|
169
165
|
}
|
|
170
166
|
}
|
|
171
167
|
}
|
|
172
168
|
|
|
173
|
-
module.exports = HostPool
|
|
169
|
+
module.exports = HostPool
|
package/http/html/404.html
CHANGED
|
@@ -1,62 +1,58 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Page Not Found</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
line-height: 1.2;
|
|
10
|
+
margin: 0;
|
|
11
|
+
}
|
|
3
12
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
html {
|
|
15
|
-
color: #888;
|
|
16
|
-
display: table;
|
|
17
|
-
font-family: sans-serif;
|
|
18
|
-
height: 100%;
|
|
19
|
-
text-align: center;
|
|
20
|
-
width: 100%;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
body {
|
|
24
|
-
display: table-cell;
|
|
25
|
-
vertical-align: middle;
|
|
26
|
-
margin: 2em auto;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
h1 {
|
|
30
|
-
color: #555;
|
|
31
|
-
font-size: 2em;
|
|
32
|
-
font-weight: 400;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
p {
|
|
36
|
-
margin: 0 auto;
|
|
37
|
-
width: 280px;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@media only screen and (max-width: 280px) {
|
|
13
|
+
html {
|
|
14
|
+
color: #888;
|
|
15
|
+
display: table;
|
|
16
|
+
font-family: sans-serif;
|
|
17
|
+
height: 100%;
|
|
18
|
+
text-align: center;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
41
21
|
|
|
42
|
-
body
|
|
43
|
-
|
|
44
|
-
|
|
22
|
+
body {
|
|
23
|
+
display: table-cell;
|
|
24
|
+
vertical-align: middle;
|
|
25
|
+
margin: 2em auto;
|
|
45
26
|
}
|
|
46
27
|
|
|
47
28
|
h1 {
|
|
48
|
-
|
|
49
|
-
|
|
29
|
+
color: #555;
|
|
30
|
+
font-size: 2em;
|
|
31
|
+
font-weight: 400;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
p {
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
width: 280px;
|
|
50
37
|
}
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
@media only screen and (max-width: 280px) {
|
|
40
|
+
body,
|
|
41
|
+
p {
|
|
42
|
+
width: 95%;
|
|
43
|
+
}
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
h1 {
|
|
46
|
+
font-size: 1.5em;
|
|
47
|
+
margin: 0 0 0.3em;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
60
52
|
|
|
53
|
+
<body>
|
|
54
|
+
<h1>Page Not Found</h1>
|
|
55
|
+
<p>Sorry, but the page you were trying to view does not exist.</p>
|
|
56
|
+
</body>
|
|
61
57
|
</html>
|
|
62
58
|
<!-- IE needs 512+ bytes: https://docs.microsoft.com/archive/blogs/ieinternals/friendly-http-error-pages -->
|
package/http/html/index.html
CHANGED
|
@@ -1,36 +1,47 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
6
|
+
<title></title>
|
|
7
|
+
<meta name="description" content="" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/css/bootstrap.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/css/bootstrap-theme.min.css" />
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
<script src="https://code.jquery.com/jquery-3.5.1.min.js" async></script>
|
|
14
|
+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/js/bootstrap.min.js" async></script>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<!--[if lt IE 7]>
|
|
18
|
+
<p class="browsehappy">
|
|
19
|
+
You are using an <strong>outdated</strong> browser. Please
|
|
20
|
+
<a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.
|
|
21
|
+
</p>
|
|
22
|
+
<![endif]-->
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
</
|
|
24
|
+
<ul id="tabList" class="nav nav-tabs" role="tablist navigation">
|
|
25
|
+
<li class="active">
|
|
26
|
+
<a href="#home" role="tab" data-toggle="tab">Home</a>
|
|
27
|
+
</li>
|
|
28
|
+
</ul>
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
<div id="bodyDivContainer" class="tab-content">
|
|
31
|
+
<div class="tab-pane fade in active" id="home">
|
|
32
|
+
<h1>Haraka, a mail server (MTA).</h1>
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
<p>
|
|
35
|
+
You are visiting an installation of
|
|
36
|
+
<a href="https://haraka.github.io">Haraka</a>.
|
|
37
|
+
</p>
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
<p>
|
|
40
|
+
Haraka is on the
|
|
41
|
+
<a href="https://haraka.github.io">web</a> and
|
|
42
|
+
<a href="https://github.com/haraka/Haraka">GitHub</a>
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</body>
|
|
36
47
|
</html>
|
package/http/package.json
CHANGED
package/line_socket.js
CHANGED
|
@@ -1,52 +1,51 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
// A subclass of Socket which reads data by line
|
|
3
3
|
|
|
4
|
-
const net
|
|
5
|
-
const utils = require('haraka-utils')
|
|
4
|
+
const net = require('node:net')
|
|
5
|
+
const utils = require('haraka-utils')
|
|
6
6
|
|
|
7
|
-
const tls_socket = require('./tls_socket')
|
|
7
|
+
const tls_socket = require('./tls_socket')
|
|
8
8
|
|
|
9
9
|
class Socket extends net.Socket {
|
|
10
|
-
constructor
|
|
11
|
-
super(options)
|
|
12
|
-
setup_line_processor(this)
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super(options)
|
|
12
|
+
setup_line_processor(this)
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function setup_line_processor
|
|
17
|
-
let current_data = ''
|
|
16
|
+
function setup_line_processor(socket) {
|
|
17
|
+
let current_data = ''
|
|
18
18
|
|
|
19
|
-
socket.on('data', function on_socket_data
|
|
20
|
-
current_data += data
|
|
21
|
-
let results
|
|
19
|
+
socket.on('data', function on_socket_data(data) {
|
|
20
|
+
current_data += data
|
|
21
|
+
let results
|
|
22
22
|
while ((results = utils.line_regexp.exec(current_data))) {
|
|
23
|
-
const this_line = results[1]
|
|
24
|
-
current_data = current_data.slice(this_line.length)
|
|
25
|
-
socket.emit('line', this_line)
|
|
23
|
+
const this_line = results[1]
|
|
24
|
+
current_data = current_data.slice(this_line.length)
|
|
25
|
+
socket.emit('line', this_line)
|
|
26
26
|
}
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
socket.on('end', function on_socket_end
|
|
29
|
+
socket.on('end', function on_socket_end() {
|
|
30
30
|
if (current_data.length) {
|
|
31
|
-
socket.emit('line', current_data)
|
|
31
|
+
socket.emit('line', current_data)
|
|
32
32
|
}
|
|
33
|
-
current_data = ''
|
|
33
|
+
current_data = ''
|
|
34
34
|
})
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
exports.Socket = Socket
|
|
37
|
+
exports.Socket = Socket
|
|
38
38
|
|
|
39
39
|
// New interface - uses TLS
|
|
40
40
|
exports.connect = (port, host) => {
|
|
41
|
-
let options = {}
|
|
41
|
+
let options = {}
|
|
42
42
|
if (typeof port === 'object') {
|
|
43
|
-
options = port
|
|
43
|
+
options = port
|
|
44
|
+
} else {
|
|
45
|
+
options.port = port
|
|
46
|
+
options.host = host
|
|
44
47
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
const sock = tls_socket.connect(options);
|
|
50
|
-
setup_line_processor(sock);
|
|
51
|
-
return sock;
|
|
48
|
+
const sock = tls_socket.connect(options)
|
|
49
|
+
setup_line_processor(sock)
|
|
50
|
+
return sock
|
|
52
51
|
}
|