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/logger.js
CHANGED
|
@@ -1,305 +1,287 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
// Log class
|
|
3
3
|
|
|
4
|
-
const util
|
|
5
|
-
const tty
|
|
4
|
+
const util = require('node:util')
|
|
5
|
+
const tty = require('node:tty')
|
|
6
6
|
|
|
7
|
-
const config
|
|
8
|
-
const constants = require('haraka-constants')
|
|
7
|
+
const config = require('haraka-config')
|
|
8
|
+
const constants = require('haraka-constants')
|
|
9
9
|
|
|
10
|
-
let plugins
|
|
10
|
+
let plugins
|
|
11
11
|
|
|
12
|
-
const regex = /(^$|[ ="\\])
|
|
13
|
-
const escape_replace_regex = /["\\]/g
|
|
12
|
+
const regex = /(^$|[ ="\\])/
|
|
13
|
+
const escape_replace_regex = /["\\]/g
|
|
14
14
|
|
|
15
|
-
function stringify
|
|
16
|
-
let str = ''
|
|
17
|
-
let key
|
|
15
|
+
function stringify(obj) {
|
|
16
|
+
let str = ''
|
|
17
|
+
let key
|
|
18
18
|
for (key in obj) {
|
|
19
|
-
let v = obj[key]
|
|
19
|
+
let v = obj[key]
|
|
20
20
|
if (v == null) {
|
|
21
|
-
str += `${key}=""
|
|
22
|
-
continue
|
|
21
|
+
str += `${key}="" `
|
|
22
|
+
continue
|
|
23
23
|
}
|
|
24
|
-
v = v.toString()
|
|
24
|
+
v = v.toString()
|
|
25
25
|
if (regex.test(v)) {
|
|
26
|
-
str += `${key}="${v.replace(escape_replace_regex, '\\$&')}"
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
str += `${key}=${v} `;
|
|
26
|
+
str += `${key}="${v.replace(escape_replace_regex, '\\$&')}" `
|
|
27
|
+
} else {
|
|
28
|
+
str += `${key}=${v} `
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
return str.trim()
|
|
31
|
+
return str.trim()
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
const logger = exports
|
|
34
|
+
const logger = exports
|
|
36
35
|
|
|
37
36
|
logger.levels = {
|
|
38
|
-
DATA:
|
|
37
|
+
DATA: 9,
|
|
39
38
|
PROTOCOL: 8,
|
|
40
|
-
DEBUG:
|
|
41
|
-
INFO:
|
|
42
|
-
NOTICE:
|
|
43
|
-
WARN:
|
|
44
|
-
ERROR:
|
|
45
|
-
CRIT:
|
|
46
|
-
ALERT:
|
|
47
|
-
EMERG:
|
|
39
|
+
DEBUG: 7,
|
|
40
|
+
INFO: 6,
|
|
41
|
+
NOTICE: 5,
|
|
42
|
+
WARN: 4,
|
|
43
|
+
ERROR: 3,
|
|
44
|
+
CRIT: 2,
|
|
45
|
+
ALERT: 1,
|
|
46
|
+
EMERG: 0,
|
|
48
47
|
}
|
|
49
48
|
const level_names = Object.keys(logger.levels)
|
|
50
49
|
|
|
51
50
|
for (const le in logger.levels) {
|
|
52
|
-
logger.levels[`LOG${le}`] = logger.levels[le]
|
|
53
|
-
logger[`LOG${le}`] = logger.levels[le]
|
|
51
|
+
logger.levels[`LOG${le}`] = logger.levels[le]
|
|
52
|
+
logger[`LOG${le}`] = logger.levels[le]
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
logger.formats = {
|
|
57
|
-
DEFAULT:
|
|
58
|
-
LOGFMT:
|
|
59
|
-
JSON:
|
|
56
|
+
DEFAULT: 'DEFAULT',
|
|
57
|
+
LOGFMT: 'LOGFMT',
|
|
58
|
+
JSON: 'JSON',
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
logger.loglevel
|
|
63
|
-
logger.format
|
|
64
|
-
logger.timestamps
|
|
65
|
-
logger.deferred_logs = []
|
|
66
|
-
logger.name
|
|
61
|
+
logger.loglevel = logger.levels.WARN
|
|
62
|
+
logger.format = logger.formats.DEFAULT
|
|
63
|
+
logger.timestamps = false
|
|
64
|
+
logger.deferred_logs = []
|
|
65
|
+
logger.name = 'logger'
|
|
67
66
|
|
|
68
67
|
logger.colors = {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
DATA: 'green',
|
|
69
|
+
PROTOCOL: 'green',
|
|
70
|
+
DEBUG: 'grey',
|
|
71
|
+
INFO: 'cyan',
|
|
72
|
+
NOTICE: 'blue',
|
|
73
|
+
WARN: 'red',
|
|
74
|
+
ERROR: 'red',
|
|
75
|
+
CRIT: 'red',
|
|
76
|
+
ALERT: 'red',
|
|
77
|
+
EMERG: 'red',
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
const stdout_is_tty = tty.isatty(process.stdout.fd)
|
|
80
|
+
const stdout_is_tty = tty.isatty(process.stdout.fd)
|
|
82
81
|
|
|
83
82
|
logger._init = function () {
|
|
84
|
-
this.load_log_ini()
|
|
85
|
-
this._init_loglevel()
|
|
86
|
-
this._init_timestamps()
|
|
83
|
+
this.load_log_ini()
|
|
84
|
+
this._init_loglevel()
|
|
85
|
+
this._init_timestamps()
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
logger.load_log_ini = function () {
|
|
90
|
-
this.cfg = config.get(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.
|
|
101
|
-
this.
|
|
89
|
+
this.cfg = config.get(
|
|
90
|
+
'log.ini',
|
|
91
|
+
{
|
|
92
|
+
booleans: ['+main.timestamps'],
|
|
93
|
+
},
|
|
94
|
+
() => {
|
|
95
|
+
this.load_log_ini()
|
|
96
|
+
},
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
this.set_loglevel(this.cfg.main.level)
|
|
100
|
+
this.set_timestamps(this.cfg.main.timestamps)
|
|
101
|
+
this.set_format(this.cfg.main.format)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
logger.colorize = (color, str) => {
|
|
105
|
-
if (!util.inspect.colors[color]) {
|
|
106
|
-
|
|
105
|
+
if (!util.inspect.colors[color]) {
|
|
106
|
+
return str
|
|
107
|
+
} // unknown color
|
|
108
|
+
return `\u001b[${util.inspect.colors[color][0]}m${str}\u001b[${util.inspect.colors[color][1]}m`
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
logger.dump_logs = cb => {
|
|
111
|
+
logger.dump_logs = (cb) => {
|
|
110
112
|
while (logger.deferred_logs.length > 0) {
|
|
111
|
-
const log_item = logger.deferred_logs.shift()
|
|
112
|
-
plugins.run_hooks('log', logger, log_item)
|
|
113
|
+
const log_item = logger.deferred_logs.shift()
|
|
114
|
+
plugins.run_hooks('log', logger, log_item)
|
|
113
115
|
}
|
|
114
116
|
// Run callback after flush
|
|
115
|
-
if (cb) process.stdout.write('', cb)
|
|
116
|
-
return true
|
|
117
|
+
if (cb) process.stdout.write('', cb)
|
|
118
|
+
return true
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
logger.dump_and_exit = function (code) {
|
|
120
122
|
this.dump_logs(() => {
|
|
121
|
-
if (typeof code === 'function') return code()
|
|
122
|
-
process.exit(code)
|
|
123
|
-
})
|
|
123
|
+
if (typeof code === 'function') return code()
|
|
124
|
+
process.exit(code)
|
|
125
|
+
})
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
logger.log = (level, data, logobj) => {
|
|
127
129
|
if (level === 'PROTOCOL') {
|
|
128
|
-
data = data.replace(/\n/g, '\\n')
|
|
130
|
+
data = data.replace(/\n/g, '\\n')
|
|
129
131
|
}
|
|
130
|
-
data = data.replace(/\r/g, '\\r').replace(/\n$/, '')
|
|
132
|
+
data = data.replace(/\r/g, '\\r').replace(/\n$/, '')
|
|
131
133
|
|
|
132
|
-
const item = { level, data, obj: logobj}
|
|
134
|
+
const item = { level, data, obj: logobj }
|
|
133
135
|
|
|
134
136
|
// buffer until plugins are loaded
|
|
135
|
-
const emptyPluginList = !plugins || Array.isArray(plugins.plugin_list) && !plugins.plugin_list.length
|
|
137
|
+
const emptyPluginList = !plugins || (Array.isArray(plugins.plugin_list) && !plugins.plugin_list.length)
|
|
136
138
|
if (emptyPluginList) {
|
|
137
|
-
logger.deferred_logs.push(item)
|
|
138
|
-
return true
|
|
139
|
+
logger.deferred_logs.push(item)
|
|
140
|
+
return true
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
// process buffered logs
|
|
142
144
|
while (logger.deferred_logs.length > 0) {
|
|
143
|
-
const log_item = logger.deferred_logs.shift()
|
|
144
|
-
plugins.run_hooks('log', logger, log_item)
|
|
145
|
+
const log_item = logger.deferred_logs.shift()
|
|
146
|
+
plugins.run_hooks('log', logger, log_item)
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
plugins.run_hooks('log', logger, item)
|
|
148
|
-
return true
|
|
149
|
+
plugins.run_hooks('log', logger, item)
|
|
150
|
+
return true
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
logger.log_respond = (retval, msg, data) => {
|
|
152
154
|
// any other return code is irrelevant
|
|
153
|
-
if (retval !== constants.cont) return false
|
|
155
|
+
if (retval !== constants.cont) return false
|
|
154
156
|
|
|
155
|
-
let timestamp_string = ''
|
|
156
|
-
if (logger.timestamps) timestamp_string = `${new Date().toISOString()}
|
|
157
|
+
let timestamp_string = ''
|
|
158
|
+
if (logger.timestamps) timestamp_string = `${new Date().toISOString()} `
|
|
157
159
|
|
|
158
|
-
const color = logger.colors[data.level]
|
|
160
|
+
const color = logger.colors[data.level]
|
|
159
161
|
if (color && stdout_is_tty) {
|
|
160
|
-
process.stdout.write(`${timestamp_string}${logger.colorize(color,data.data)}\n`)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
process.stdout.write(`${timestamp_string}${data.data}\n`);
|
|
162
|
+
process.stdout.write(`${timestamp_string}${logger.colorize(color, data.data)}\n`)
|
|
163
|
+
} else {
|
|
164
|
+
process.stdout.write(`${timestamp_string}${data.data}\n`)
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
return true
|
|
167
|
+
return true
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
logger.set_loglevel = function (level) {
|
|
170
|
-
if (level === undefined || level === null) return
|
|
171
|
+
if (level === undefined || level === null) return
|
|
171
172
|
|
|
172
|
-
const loglevel_num = parseInt(level)
|
|
173
|
+
const loglevel_num = parseInt(level)
|
|
173
174
|
if (typeof level === 'string') {
|
|
174
|
-
this.log('INFO', `loglevel: ${level.toUpperCase()}`)
|
|
175
|
-
logger.loglevel = logger.levels[level.toUpperCase()]
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
logger.loglevel = loglevel_num;
|
|
175
|
+
this.log('INFO', `loglevel: ${level.toUpperCase()}`)
|
|
176
|
+
logger.loglevel = logger.levels[level.toUpperCase()]
|
|
177
|
+
} else {
|
|
178
|
+
logger.loglevel = loglevel_num
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
if (!Number.isInteger(logger.loglevel)) {
|
|
182
|
-
this.log('WARN', `invalid loglevel: ${level} defaulting to LOGWARN`)
|
|
183
|
-
logger.loglevel = logger.levels.WARN
|
|
182
|
+
this.log('WARN', `invalid loglevel: ${level} defaulting to LOGWARN`)
|
|
183
|
+
logger.loglevel = logger.levels.WARN
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
logger.set_format = function (format) {
|
|
188
188
|
if (format) {
|
|
189
|
-
logger.format = logger.formats[format.toUpperCase()]
|
|
190
|
-
this.log('INFO', `log format: ${format.toUpperCase()}`)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
logger.format = null;
|
|
189
|
+
logger.format = logger.formats[format.toUpperCase()]
|
|
190
|
+
this.log('INFO', `log format: ${format.toUpperCase()}`)
|
|
191
|
+
} else {
|
|
192
|
+
logger.format = null
|
|
194
193
|
}
|
|
195
194
|
if (!logger.format) {
|
|
196
|
-
this.log('WARN', `invalid log format: ${format} defaulting to DEFAULT`)
|
|
197
|
-
logger.format = logger.formats.DEFAULT
|
|
195
|
+
this.log('WARN', `invalid log format: ${format} defaulting to DEFAULT`)
|
|
196
|
+
logger.format = logger.formats.DEFAULT
|
|
198
197
|
}
|
|
199
198
|
}
|
|
200
199
|
|
|
201
200
|
logger._init_loglevel = function () {
|
|
202
|
-
|
|
203
201
|
const _loglevel = config.get('loglevel', 'value', () => {
|
|
204
|
-
this._init_loglevel()
|
|
205
|
-
})
|
|
202
|
+
this._init_loglevel()
|
|
203
|
+
})
|
|
206
204
|
|
|
207
|
-
this.set_loglevel(_loglevel)
|
|
205
|
+
this.set_loglevel(_loglevel)
|
|
208
206
|
}
|
|
209
207
|
|
|
210
|
-
logger.would_log = level => {
|
|
211
|
-
if (logger.loglevel < level) return false
|
|
212
|
-
return true
|
|
208
|
+
logger.would_log = (level) => {
|
|
209
|
+
if (logger.loglevel < level) return false
|
|
210
|
+
return true
|
|
213
211
|
}
|
|
214
212
|
|
|
215
|
-
logger.set_timestamps = value => {
|
|
216
|
-
logger.timestamps = !!value
|
|
213
|
+
logger.set_timestamps = (value) => {
|
|
214
|
+
logger.timestamps = !!value
|
|
217
215
|
}
|
|
218
216
|
|
|
219
217
|
logger._init_timestamps = function () {
|
|
220
|
-
|
|
221
218
|
const _timestamps = config.get('log_timestamps', 'value', () => {
|
|
222
|
-
this._init_timestamps()
|
|
223
|
-
})
|
|
219
|
+
this._init_timestamps()
|
|
220
|
+
})
|
|
224
221
|
|
|
225
222
|
// If we've already been toggled to true by the cfg, we should respect this.
|
|
226
|
-
this.set_timestamps(logger.timestamps || _timestamps)
|
|
223
|
+
this.set_timestamps(logger.timestamps || _timestamps)
|
|
227
224
|
}
|
|
228
225
|
|
|
229
|
-
logger._init()
|
|
230
|
-
|
|
231
|
-
logger.log_if_level = (level, key, origin) => function () {
|
|
232
|
-
if (logger.loglevel < logger[key]) return;
|
|
226
|
+
logger._init()
|
|
233
227
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
origin: (origin || 'core'),
|
|
238
|
-
message: ''
|
|
239
|
-
};
|
|
228
|
+
logger.log_if_level = (level, key, origin) =>
|
|
229
|
+
function () {
|
|
230
|
+
if (logger.loglevel < logger[key]) return
|
|
240
231
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
232
|
+
let logobj = {
|
|
233
|
+
level,
|
|
234
|
+
uuid: '-',
|
|
235
|
+
origin: origin || 'core',
|
|
236
|
+
message: '',
|
|
245
237
|
}
|
|
246
|
-
if (!data) continue;
|
|
247
238
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (data
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
logger.format === logger.formats.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
239
|
+
for (const data of arguments) {
|
|
240
|
+
if (typeof data !== 'object') {
|
|
241
|
+
logobj.message += data
|
|
242
|
+
continue
|
|
243
|
+
}
|
|
244
|
+
if (!data) continue
|
|
245
|
+
|
|
246
|
+
// if the object is a connection, add the connection id
|
|
247
|
+
if (data.constructor?.name === 'Connection') {
|
|
248
|
+
logobj.uuid = data.uuid
|
|
249
|
+
if (data.tran_count > 0) logobj.uuid += `.${data.tran_count}`
|
|
250
|
+
} else if (data instanceof plugins.Plugin) {
|
|
251
|
+
logobj.origin = data.name
|
|
252
|
+
} else if (Object.hasOwn(data, 'name')) {
|
|
253
|
+
// outbound
|
|
254
|
+
logobj.origin = data.name
|
|
255
|
+
if (Object.hasOwn(data, 'uuid')) logobj.uuid = data.uuid
|
|
256
|
+
if (data.todo?.uuid) logobj.uuid = data.todo.uuid // outbound/hmail
|
|
257
|
+
} else if (logger.format === logger.formats.LOGFMT && data.constructor === Object) {
|
|
258
|
+
logobj = Object.assign(logobj, data)
|
|
259
|
+
} else if (logger.format === logger.formats.JSON && data.constructor === Object) {
|
|
260
|
+
logobj = Object.assign(logobj, data)
|
|
261
|
+
} else if (Object.hasOwn(data, 'uuid')) {
|
|
262
|
+
// outbound/client_pool
|
|
263
|
+
logobj.uuid = data.uuid
|
|
264
|
+
} else if (data.constructor === Object) {
|
|
265
|
+
if (!logobj.message.endsWith(' ')) logobj.message += ' '
|
|
266
|
+
logobj.message += stringify(data)
|
|
267
|
+
} else {
|
|
268
|
+
logobj.message += util.inspect(data)
|
|
269
|
+
}
|
|
278
270
|
}
|
|
279
|
-
}
|
|
280
271
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
level,
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
break
|
|
294
|
-
case logger.formats.DEFAULT:
|
|
295
|
-
default:
|
|
296
|
-
logger.log(
|
|
297
|
-
level,
|
|
298
|
-
`[${logobj.level}] [${logobj.uuid}] [${logobj.origin}] ${logobj.message}`
|
|
299
|
-
);
|
|
272
|
+
switch (logger.format) {
|
|
273
|
+
case logger.formats.LOGFMT:
|
|
274
|
+
logger.log(level, stringify(logobj))
|
|
275
|
+
break
|
|
276
|
+
case logger.formats.JSON:
|
|
277
|
+
logger.log(level, JSON.stringify(logobj))
|
|
278
|
+
break
|
|
279
|
+
case logger.formats.DEFAULT:
|
|
280
|
+
default:
|
|
281
|
+
logger.log(level, `[${logobj.level}] [${logobj.uuid}] [${logobj.origin}] ${logobj.message}`)
|
|
282
|
+
}
|
|
283
|
+
return true
|
|
300
284
|
}
|
|
301
|
-
return true;
|
|
302
|
-
}
|
|
303
285
|
|
|
304
286
|
logger.add_log_methods = (object, logName) => {
|
|
305
287
|
if (!object) return
|
|
@@ -307,15 +289,14 @@ logger.add_log_methods = (object, logName) => {
|
|
|
307
289
|
if (typeof object === 'function') {
|
|
308
290
|
// add logging methods to class prototypes (Connection, Plugin, etc.)
|
|
309
291
|
|
|
310
|
-
for (const level of level_names.map(l => l.toLowerCase())) {
|
|
292
|
+
for (const level of level_names.map((l) => l.toLowerCase())) {
|
|
311
293
|
object.prototype[`log${level}`] = (function (level) {
|
|
312
294
|
return function () {
|
|
313
|
-
logger[level].apply(logger, [
|
|
314
|
-
}
|
|
315
|
-
})(`log${level}`)
|
|
295
|
+
logger[level].apply(logger, [this, ...arguments])
|
|
296
|
+
}
|
|
297
|
+
})(`log${level}`)
|
|
316
298
|
}
|
|
317
|
-
}
|
|
318
|
-
else if (typeof object === 'object') {
|
|
299
|
+
} else if (typeof object === 'object') {
|
|
319
300
|
// add logging methods to objects
|
|
320
301
|
|
|
321
302
|
for (const level of level_names) {
|
|
@@ -328,14 +309,14 @@ logger.add_log_methods = (object, logName) => {
|
|
|
328
309
|
}
|
|
329
310
|
|
|
330
311
|
for (const fnName of fnNames) {
|
|
331
|
-
if (Object.hasOwn(object, fnName)) continue
|
|
332
|
-
object[fnName] = logger.log_if_level(level, `LOG${level}`, logName)
|
|
312
|
+
if (Object.hasOwn(object, fnName)) continue // already added
|
|
313
|
+
object[fnName] = logger.log_if_level(level, `LOG${level}`, logName)
|
|
333
314
|
}
|
|
334
315
|
}
|
|
335
316
|
}
|
|
336
317
|
}
|
|
337
318
|
|
|
338
|
-
logger.add_log_methods(logger)
|
|
319
|
+
logger.add_log_methods(logger)
|
|
339
320
|
|
|
340
321
|
// load these down here so it sees all the logger methods compiled above
|
|
341
|
-
plugins = require('./plugins')
|
|
322
|
+
plugins = require('./plugins')
|
package/outbound/client_pool.js
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
|
-
const util = require('node:util')
|
|
3
|
+
const util = require('node:util')
|
|
4
4
|
|
|
5
|
-
const utils = require('haraka-utils')
|
|
5
|
+
const utils = require('haraka-utils')
|
|
6
6
|
const net_utils = require('haraka-net-utils')
|
|
7
7
|
|
|
8
|
-
const tls_socket = require('../tls_socket')
|
|
9
|
-
const logger = require('../logger')
|
|
10
|
-
const obc
|
|
8
|
+
const tls_socket = require('../tls_socket')
|
|
9
|
+
const logger = require('../logger')
|
|
10
|
+
const obc = require('./config')
|
|
11
11
|
|
|
12
12
|
exports.name = 'outbound'
|
|
13
13
|
|
|
14
14
|
// Get a socket for the given attributes.
|
|
15
15
|
exports.get_client = function (mx, callback) {
|
|
16
|
-
const socketArgs = mx.path ? { path: mx.path } : { port: mx.port, host: mx.exchange, localAddress: mx.bind }
|
|
16
|
+
const socketArgs = mx.path ? { path: mx.path } : { port: mx.port, host: mx.exchange, localAddress: mx.bind }
|
|
17
17
|
|
|
18
|
-
const socket = tls_socket.connect(socketArgs)
|
|
19
|
-
net_utils.add_line_processor(socket)
|
|
18
|
+
const socket = tls_socket.connect(socketArgs)
|
|
19
|
+
net_utils.add_line_processor(socket)
|
|
20
20
|
|
|
21
|
-
socket.name = `outbound::${JSON.stringify(socketArgs)}
|
|
22
|
-
socket.__uuid = utils.uuid()
|
|
23
|
-
socket.setTimeout(obc.cfg.connect_timeout * 1000)
|
|
21
|
+
socket.name = `outbound::${JSON.stringify(socketArgs)}`
|
|
22
|
+
socket.__uuid = utils.uuid()
|
|
23
|
+
socket.setTimeout(obc.cfg.connect_timeout * 1000)
|
|
24
24
|
|
|
25
|
-
logger.debug(exports, `created ${socket.name}`, { uuid: socket.__uuid })
|
|
25
|
+
logger.debug(exports, `created ${socket.name}`, { uuid: socket.__uuid })
|
|
26
26
|
|
|
27
27
|
socket.once('connect', () => {
|
|
28
|
-
socket.removeAllListeners('error')
|
|
29
|
-
socket.removeAllListeners('timeout')
|
|
30
|
-
callback(null, socket)
|
|
28
|
+
socket.removeAllListeners('error') // these get added after callback
|
|
29
|
+
socket.removeAllListeners('timeout')
|
|
30
|
+
callback(null, socket)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
socket.once('error', err => {
|
|
34
|
-
socket.end()
|
|
35
|
-
socket.removeAllListeners()
|
|
36
|
-
socket.destroy()
|
|
37
|
-
const errMsg = err.message
|
|
38
|
-
err.message
|
|
39
|
-
err instanceof AggregateError
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
callback(errMsg, null)
|
|
33
|
+
socket.once('error', (err) => {
|
|
34
|
+
socket.end()
|
|
35
|
+
socket.removeAllListeners()
|
|
36
|
+
socket.destroy()
|
|
37
|
+
const errMsg = err.message
|
|
38
|
+
? err.message
|
|
39
|
+
: err instanceof AggregateError
|
|
40
|
+
? err.map((e) => e.message).join(', ')
|
|
41
|
+
: util.inspect(err, { depth: 3 })
|
|
42
|
+
callback(errMsg, null)
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
socket.once('timeout', () => {
|
|
46
|
-
socket.end()
|
|
47
|
-
socket.removeAllListeners()
|
|
48
|
-
socket.destroy()
|
|
49
|
-
callback(`connection timed out to ${socket.name}`, null)
|
|
46
|
+
socket.end()
|
|
47
|
+
socket.removeAllListeners()
|
|
48
|
+
socket.destroy()
|
|
49
|
+
callback(`connection timed out to ${socket.name}`, null)
|
|
50
50
|
})
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
exports.release_client = (socket, mx) => {
|
|
54
54
|
let logMsg = `release_client: ${socket.name}`
|
|
55
55
|
if (mx.bind) logMsg += ` from ${mx.bind}`
|
|
56
|
-
logger.debug(exports, logMsg)
|
|
57
|
-
socket.removeAllListeners()
|
|
58
|
-
socket.destroy()
|
|
56
|
+
logger.debug(exports, logMsg)
|
|
57
|
+
socket.removeAllListeners()
|
|
58
|
+
socket.destroy()
|
|
59
59
|
}
|