Haraka 3.1.3 → 3.1.5
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 +2 -0
- package/CONTRIBUTORS.md +23 -1
- package/Changes.md +52 -0
- package/Plugins.md +81 -64
- package/README.md +1 -1
- package/bin/haraka +7 -5
- package/connection.js +15 -19
- package/docs/Plugins.md +1 -1
- package/docs/plugins/aliases.md +0 -2
- package/docs/plugins/queue/qmail-queue.md +0 -1
- package/logger.js +2 -2
- package/outbound/hmail.js +76 -83
- package/outbound/index.js +36 -34
- package/outbound/queue.js +231 -176
- package/package.json +26 -29
- package/plugins/prevent_credential_leaks.js +2 -2
- package/plugins/process_title.js +1 -1
- package/plugins/queue/smtp_forward.js +5 -5
- package/plugins/status.js +8 -5
- package/plugins/tls.js +1 -1
- package/plugins.js +19 -14
- package/rfc1869.js +10 -10
- package/run_tests +8 -2
- package/server.js +15 -10
- package/smtp_client.js +10 -15
- package/test/config/tls/haraka.local.pem +47 -47
- package/test/connection.js +286 -147
- package/test/endpoint.js +5 -4
- package/test/fixtures/line_socket.js +1 -0
- package/test/fixtures/util_hmailitem.js +1 -1
- package/test/host_pool.js +57 -31
- package/test/logger.js +75 -135
- package/test/outbound/bounce_net_errors.js +132 -0
- package/test/outbound/bounce_rfc3464.js +226 -0
- package/test/outbound/hmail.js +140 -104
- package/test/outbound/index.js +61 -101
- package/test/outbound/qfile.js +25 -25
- package/test/outbound/queue.js +233 -0
- package/test/plugins/auth/auth_base.js +39 -44
- package/test/plugins/auth/auth_vpopmaild.js +8 -9
- package/test/plugins/queue/smtp_forward.js +953 -183
- package/test/plugins/rcpt_to.host_list_base.js +58 -93
- package/test/plugins/rcpt_to.in_host_list.js +126 -175
- package/test/plugins/record_envelope_addresses.js +93 -0
- package/test/plugins/status.js +10 -10
- package/test/plugins/tls.js +11 -21
- package/test/plugins/xclient.js +102 -0
- package/test/plugins.js +10 -13
- package/test/rfc1869.js +71 -48
- package/test/server.js +281 -436
- package/test/smtp_client.js +1194 -220
- package/test/tls_socket.js +74 -243
- package/test/transaction.js +486 -201
- package/tls_socket.js +19 -23
- package/transaction.js +33 -10
- package/config/rabbitmq.ini +0 -10
- package/config/rabbitmq_amqplib.ini +0 -19
- package/docs/plugins/queue/rabbitmq.md +0 -34
- package/docs/plugins/queue/rabbitmq_amqplib.md +0 -51
- package/plugins/queue/rabbitmq.js +0 -141
- package/plugins/queue/rabbitmq_amqplib.js +0 -96
- package/test/config/tls/ec.pem +0 -23
- package/test/config/tls/mismatched.pem +0 -49
- package/test/outbound_bounce_net_errors.js +0 -157
- package/test/outbound_bounce_rfc3464.js +0 -366
package/tls_socket.js
CHANGED
|
@@ -159,21 +159,16 @@ exports.parse_x509 = async (string) => {
|
|
|
159
159
|
const res = {}
|
|
160
160
|
if (!string) return res
|
|
161
161
|
|
|
162
|
-
const keyRe =
|
|
162
|
+
const keyRe = /([-]+BEGIN (?:\w+ )?PRIVATE KEY[-]+[^-]*[-]+END (?:\w+ )?PRIVATE KEY[-]+)/gm
|
|
163
163
|
res.keys = string.match(keyRe)
|
|
164
164
|
|
|
165
|
-
const certRe =
|
|
165
|
+
const certRe = /([-]+BEGIN CERTIFICATE[-]+[^-]*[-]+END CERTIFICATE[-]+)/gm
|
|
166
166
|
res.chain = string.match(certRe)
|
|
167
167
|
|
|
168
168
|
if (res.chain?.length) {
|
|
169
|
-
const opensslArgs = [res.chain[0], 'x509', '-noout']
|
|
170
|
-
// shush openssl, https://github.com/openssl/openssl/issues/22893
|
|
171
|
-
// if (['darwin','linux','freebsd'].includes(process.platform))
|
|
172
|
-
// opensslArgs.push('-in', '/dev/stdin')
|
|
173
|
-
|
|
174
169
|
// it's cleaner to call openssl with each of -enddate, -subject, etc, but it costs
|
|
175
170
|
// 40-50ms per spawn with node v21 on a M1 MBP
|
|
176
|
-
const raw = await openssl(
|
|
171
|
+
const raw = await openssl(res.chain[0], 'x509', '-noout', '-enddate', '-subject', '-ext', 'subjectAltName')
|
|
177
172
|
if (!raw) return res
|
|
178
173
|
|
|
179
174
|
res.expire = new Date(raw.match(/notAfter=(.* [A-Z]{3})/)[1])
|
|
@@ -191,7 +186,7 @@ exports.parse_x509 = async (string) => {
|
|
|
191
186
|
}
|
|
192
187
|
|
|
193
188
|
exports.load_tls_ini = (opts) => {
|
|
194
|
-
log.info(
|
|
189
|
+
log.info('loading tls.ini')
|
|
195
190
|
|
|
196
191
|
const cfg = exports.config.get(
|
|
197
192
|
'tls.ini',
|
|
@@ -339,7 +334,7 @@ exports.load_default_opts = () => {
|
|
|
339
334
|
if (!Array.isArray(cfg.key)) cfg.key = [cfg.key]
|
|
340
335
|
if (!Array.isArray(cfg.cert)) cfg.cert = [cfg.cert]
|
|
341
336
|
|
|
342
|
-
if (cfg.key.length
|
|
337
|
+
if (cfg.key.length !== cfg.cert.length) {
|
|
343
338
|
log.error(`number of keys (${cfg.key.length}) not equal to certs (${cfg.cert.length}).`)
|
|
344
339
|
}
|
|
345
340
|
|
|
@@ -454,19 +449,20 @@ exports.get_certs_dir = async (tlsDir) => {
|
|
|
454
449
|
function openssl(crt, ...params) {
|
|
455
450
|
return new Promise((resolve) => {
|
|
456
451
|
let crtTxt = ''
|
|
452
|
+
let errTxt = ''
|
|
457
453
|
|
|
458
|
-
const o = spawn('openssl',
|
|
454
|
+
const o = spawn('openssl', params, { timeout: 2000 })
|
|
459
455
|
o.stdout.on('data', (data) => {
|
|
460
456
|
crtTxt += data
|
|
461
457
|
})
|
|
462
458
|
|
|
463
459
|
o.stderr.on('data', (data) => {
|
|
464
|
-
|
|
460
|
+
errTxt += data
|
|
465
461
|
})
|
|
466
462
|
|
|
467
463
|
o.on('close', (code) => {
|
|
468
464
|
if (code !== 0) {
|
|
469
|
-
|
|
465
|
+
log.error(`openssl ${params.join(' ')} failed with code ${code}: ${errTxt.trim()}`)
|
|
470
466
|
}
|
|
471
467
|
resolve(crtTxt)
|
|
472
468
|
})
|
|
@@ -484,8 +480,7 @@ exports.getSocketOpts = async (name) => {
|
|
|
484
480
|
await this.get_certs_dir('tls')
|
|
485
481
|
} catch (err) {
|
|
486
482
|
if (err.code !== 'ENOENT') {
|
|
487
|
-
|
|
488
|
-
log.error(err)
|
|
483
|
+
log.error(err.message)
|
|
489
484
|
}
|
|
490
485
|
}
|
|
491
486
|
|
|
@@ -519,7 +514,7 @@ exports.ensureDhparams = (done) => {
|
|
|
519
514
|
|
|
520
515
|
log.info(`Generating a 2048 bit dhparams file at ${fpResolved}`)
|
|
521
516
|
|
|
522
|
-
const o = spawn('openssl', ['dhparam', '-out',
|
|
517
|
+
const o = spawn('openssl', ['dhparam', '-out', fpResolved, '2048'], { timeout: 30000 })
|
|
523
518
|
o.stdout.on('data', (data) => {
|
|
524
519
|
// normally empty output
|
|
525
520
|
log.debug(data)
|
|
@@ -586,9 +581,9 @@ exports.shutdown = () => {
|
|
|
586
581
|
|
|
587
582
|
function cleanOcspCache() {
|
|
588
583
|
log.debug(`Cleaning ocspCache. How many keys? ${Object.keys(ocspCache.cache).length}`)
|
|
589
|
-
Object.keys(ocspCache.cache)
|
|
584
|
+
for (const key of Object.keys(ocspCache.cache)) {
|
|
590
585
|
clearTimeout(ocspCache.cache[key].timer)
|
|
591
|
-
}
|
|
586
|
+
}
|
|
592
587
|
}
|
|
593
588
|
|
|
594
589
|
exports.certsByHost = certsByHost
|
|
@@ -615,7 +610,7 @@ function createServer(cb) {
|
|
|
615
610
|
|
|
616
611
|
cryptoSocket.removeAllListeners('data')
|
|
617
612
|
|
|
618
|
-
const options =
|
|
613
|
+
const options = { ...certsByHost['*'] }
|
|
619
614
|
options.server = server // TLSSocket needs server for SNI to work
|
|
620
615
|
|
|
621
616
|
options.rejectUnauthorized = exports.get_rejectUnauthorized(
|
|
@@ -679,21 +674,22 @@ function connect(conn_options = {}) {
|
|
|
679
674
|
const host = conn_options.host
|
|
680
675
|
if (exports.cfg === undefined) exports.load_tls_ini()
|
|
681
676
|
if (exports.cfg.mutual_auth_hosts[host]) {
|
|
682
|
-
options =
|
|
677
|
+
options = { ...options, ...getCertFor(exports.cfg.mutual_auth_hosts[host]) }
|
|
683
678
|
} else if (exports.cfg.mutual_auth_hosts_exclude[host]) {
|
|
684
679
|
// send no client cert
|
|
685
680
|
} else if (exports.cfg.main.mutual_tls) {
|
|
686
|
-
options =
|
|
681
|
+
options = { ...options, ...getCertFor(host) }
|
|
687
682
|
}
|
|
688
683
|
}
|
|
689
684
|
options.socket = cryptoSocket
|
|
690
685
|
|
|
691
|
-
const cleartext =
|
|
686
|
+
const cleartext = tls.connect(options)
|
|
692
687
|
|
|
693
688
|
pipe(cleartext, cryptoSocket)
|
|
694
689
|
|
|
695
690
|
cleartext.on('error', (err) => {
|
|
696
|
-
|
|
691
|
+
err.source = 'tls'
|
|
692
|
+
socket.emit('error', err)
|
|
697
693
|
})
|
|
698
694
|
|
|
699
695
|
cleartext.once('secureConnect', () => {
|
package/transaction.js
CHANGED
|
@@ -55,9 +55,12 @@ class Transaction {
|
|
|
55
55
|
|
|
56
56
|
for (const o of this.body_filters) {
|
|
57
57
|
this.body.add_filter((ct, enc, buf) => {
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
58
|
+
if (!ct) return buf
|
|
59
|
+
const ct_lc = String(ct).toLowerCase().trim()
|
|
60
|
+
const re_match = util.types.isRegExp(o.ct_match) && o.ct_match.test(ct_lc)
|
|
61
|
+
const ct_begins = ct_lc.indexOf(String(o.ct_match).toLowerCase()) === 0
|
|
62
|
+
if (re_match || ct_begins) return o.filter(ct, enc, buf) || buf
|
|
63
|
+
return buf
|
|
61
64
|
})
|
|
62
65
|
}
|
|
63
66
|
}
|
|
@@ -133,7 +136,7 @@ class Transaction {
|
|
|
133
136
|
// is this the end of headers line?
|
|
134
137
|
if (this.header_pos === 0 && (line[0] === 0x0a || (line[0] === 0x0d && line[1] === 0x0a))) {
|
|
135
138
|
this.header.parse(this.header_lines)
|
|
136
|
-
this.header_pos = this.
|
|
139
|
+
this.header_pos = this.header.header_list ? this.header.header_list.length : -1
|
|
137
140
|
this.found_hb_sep = true
|
|
138
141
|
if (this.parse_body) this.ensure_body()
|
|
139
142
|
} else if (this.header_pos === 0) {
|
|
@@ -143,6 +146,7 @@ class Transaction {
|
|
|
143
146
|
this.header_lines.push(line.toString(this.encoding).replace(/\r\n$/, '\n'))
|
|
144
147
|
}
|
|
145
148
|
} else if (this.parse_body) {
|
|
149
|
+
this.ensure_body()
|
|
146
150
|
let new_line = line
|
|
147
151
|
if (new_line[0] === 0x2e) new_line = new_line.slice(1) // Strip leading "."
|
|
148
152
|
|
|
@@ -169,13 +173,23 @@ class Transaction {
|
|
|
169
173
|
}
|
|
170
174
|
const body_lines = this.header_lines.splice(header_pos + 1)
|
|
171
175
|
this.header.parse(this.header_lines)
|
|
172
|
-
this.header_pos =
|
|
176
|
+
this.header_pos = this.header.header_list ? this.header.header_list.length : -1
|
|
177
|
+
this.found_hb_sep = true
|
|
178
|
+
|
|
179
|
+
// We MUST add an empty line to the message_stream so that it knows
|
|
180
|
+
// where the headers end. Otherwise it skips everything.
|
|
181
|
+
if (!this.discard_data) this.message_stream.add_line(Buffer.from('\r\n'))
|
|
182
|
+
|
|
173
183
|
if (this.parse_body) {
|
|
174
184
|
this.ensure_body()
|
|
175
185
|
for (const bodyLine of body_lines) {
|
|
176
186
|
this.body.parse_more(bodyLine)
|
|
177
187
|
}
|
|
178
188
|
}
|
|
189
|
+
|
|
190
|
+
for (const bodyLine of body_lines) {
|
|
191
|
+
if (!this.discard_data) this.message_stream.add_line(Buffer.from(`${bodyLine}\n`))
|
|
192
|
+
}
|
|
179
193
|
}
|
|
180
194
|
if (this.header_pos && this.parse_body) {
|
|
181
195
|
const line = this.add_dot_stuffing_and_ensure_crlf_newlines(this.body.parse_end())
|
|
@@ -195,22 +209,21 @@ class Transaction {
|
|
|
195
209
|
|
|
196
210
|
add_header(key, value) {
|
|
197
211
|
this.header.add_end(key, value)
|
|
198
|
-
if (this.
|
|
212
|
+
if (this.found_hb_sep) this.reset_headers()
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
add_leading_header(key, value) {
|
|
202
216
|
this.header.add(key, value)
|
|
203
|
-
if (this.
|
|
217
|
+
if (this.found_hb_sep) this.reset_headers()
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
reset_headers() {
|
|
207
|
-
|
|
208
|
-
this.header_pos = header_lines.length
|
|
221
|
+
this.header_pos = this.header.header_list ? this.header.header_list.length : -1
|
|
209
222
|
}
|
|
210
223
|
|
|
211
224
|
remove_header(key) {
|
|
212
225
|
this.header.remove(key)
|
|
213
|
-
if (this.
|
|
226
|
+
if (this.found_hb_sep) this.reset_headers()
|
|
214
227
|
}
|
|
215
228
|
|
|
216
229
|
attachment_hooks(start, data, end) {
|
|
@@ -230,6 +243,16 @@ class Transaction {
|
|
|
230
243
|
add_body_filter(ct_match, filter) {
|
|
231
244
|
this.parse_body = true
|
|
232
245
|
this.body_filters.push({ ct_match, filter })
|
|
246
|
+
if (this.body) {
|
|
247
|
+
this.body.add_filter((ct, enc, buf) => {
|
|
248
|
+
if (!ct) return buf
|
|
249
|
+
const ct_lc = String(ct).toLowerCase().trim()
|
|
250
|
+
const re_match = util.types.isRegExp(ct_match) && ct_match.test(ct_lc)
|
|
251
|
+
const ct_begins = ct_lc.indexOf(String(ct_match).toLowerCase()) === 0
|
|
252
|
+
if (re_match || ct_begins) return filter(ct, enc, buf) || buf
|
|
253
|
+
return buf
|
|
254
|
+
})
|
|
255
|
+
}
|
|
233
256
|
}
|
|
234
257
|
|
|
235
258
|
incr_mime_count(line) {
|
package/config/rabbitmq.ini
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
[rabbitmq]
|
|
2
|
-
host = localhost
|
|
3
|
-
port = 5672
|
|
4
|
-
user = guest
|
|
5
|
-
password = guest
|
|
6
|
-
exchangeName = email_messages
|
|
7
|
-
exchangeType = direct
|
|
8
|
-
queueName = emails
|
|
9
|
-
deliveryMode = 2
|
|
10
|
-
confirm = true
|
|
11
|
-
durable = true
|
|
12
|
-
autoDelete = false
|
|
13
|
-
|
|
14
|
-
; Optional queue arguments
|
|
15
|
-
; [queue_args]
|
|
16
|
-
; x-dead-letter-exchange =
|
|
17
|
-
; x-dead-letter-routing-key = emails_dlq
|
|
18
|
-
; x-overflow = reject-publish
|
|
19
|
-
; x-queue-type = quorum
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# queue/rabbitmq
|
|
2
|
-
|
|
3
|
-
This plugin delivers mails to rabbitmq queue for further processing.
|
|
4
|
-
|
|
5
|
-
## Configuration
|
|
6
|
-
|
|
7
|
-
- `config/rabbitmq.ini`
|
|
8
|
-
This config file provides server address and port of rabbitmq server to deliver with other configs of queues and exchange.
|
|
9
|
-
|
|
10
|
-
Example:
|
|
11
|
-
|
|
12
|
-
[rabbitmq]
|
|
13
|
-
; This is name of exchange.
|
|
14
|
-
exchangeName = emailMessages
|
|
15
|
-
; ip and port of the server.
|
|
16
|
-
server_ip = localhost
|
|
17
|
-
server_port = 5672
|
|
18
|
-
; user and password
|
|
19
|
-
user = guest
|
|
20
|
-
password = guest
|
|
21
|
-
; name of the queue which reader will read
|
|
22
|
-
queueName = email
|
|
23
|
-
; This is for making it persistant while publishing message
|
|
24
|
-
deliveryMode = 2
|
|
25
|
-
; If true it will require ack for marking it complete from worker
|
|
26
|
-
confirm = true
|
|
27
|
-
; Again for persistance passed while creating queue
|
|
28
|
-
durable = true
|
|
29
|
-
; if true will delete queue if publisher quits
|
|
30
|
-
autoDelete = false
|
|
31
|
-
; type of the exchange
|
|
32
|
-
exchangeType = direct
|
|
33
|
-
|
|
34
|
-
More information about rabbitmq can be found at https://www.rabbitmq.com/
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# queue/rabbitmq_amqplib
|
|
2
|
-
|
|
3
|
-
This plugin delivers emails to RabbitMQ queue for further processing. Based on `queue/rabbitmq` but using `amqplib`.
|
|
4
|
-
|
|
5
|
-
## Dependency
|
|
6
|
-
|
|
7
|
-
- `amqplib` - https://github.com/squaremo/amqp.node
|
|
8
|
-
|
|
9
|
-
## Configuration
|
|
10
|
-
|
|
11
|
-
- `config/rabbitmq.ini` - Connection, exchange and queue settings
|
|
12
|
-
|
|
13
|
-
Example:
|
|
14
|
-
|
|
15
|
-
[rabbitmq]
|
|
16
|
-
; Connection
|
|
17
|
-
; Protocol. Either "amqp" or "amqps"
|
|
18
|
-
protocol = amqp
|
|
19
|
-
host = localhost
|
|
20
|
-
port = 5672
|
|
21
|
-
;Virtual Host. Start with "/". Leave blank or not use if you don't want to use virtual hosts.
|
|
22
|
-
vhost = /haraka
|
|
23
|
-
;Credentials
|
|
24
|
-
user = guest
|
|
25
|
-
password = guest
|
|
26
|
-
; Exchange
|
|
27
|
-
exchangeName = email_messages
|
|
28
|
-
exchangeType = direct
|
|
29
|
-
; Queue
|
|
30
|
-
queueName = emails
|
|
31
|
-
confirm = true
|
|
32
|
-
durable = true
|
|
33
|
-
autoDelete = false
|
|
34
|
-
; Message
|
|
35
|
-
deliveryMode = 2
|
|
36
|
-
priority = 1
|
|
37
|
-
|
|
38
|
-
; Optional exchange arguments
|
|
39
|
-
; More information about exchange x-arguments can be found at https://www.rabbitmq.com/docs/exchanges#optional-arguments
|
|
40
|
-
[exchange_args]
|
|
41
|
-
alternate-exchange =
|
|
42
|
-
|
|
43
|
-
; Optional queue arguments
|
|
44
|
-
; More information about queue x-arguments can be found at https://www.rabbitmq.com/queues.html#optional-arguments
|
|
45
|
-
[queue_args]
|
|
46
|
-
x-dead-letter-exchange =
|
|
47
|
-
x-dead-letter-routing-key = emails_dlq
|
|
48
|
-
x-overflow = reject-publish
|
|
49
|
-
x-queue-type = quorum
|
|
50
|
-
|
|
51
|
-
More information about RabbitMQ can be found at https://www.rabbitmq.com/
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
const amqp = require('amqp')
|
|
2
|
-
|
|
3
|
-
let rabbitqueue
|
|
4
|
-
let exchangeName
|
|
5
|
-
let queueName
|
|
6
|
-
let deliveryMode
|
|
7
|
-
let connExchange_
|
|
8
|
-
let connQueue_
|
|
9
|
-
let routing_
|
|
10
|
-
exports.exchangeMapping = {}
|
|
11
|
-
|
|
12
|
-
//This method registers the hook and try to initialize the connection to rabbitmq server for later use.
|
|
13
|
-
exports.register = function () {
|
|
14
|
-
this.logdebug('About to connect and initialize queue object')
|
|
15
|
-
this.init_rabbitmq_server()
|
|
16
|
-
this.logdebug(`Finished initiating : ${exports.exchangeMapping[exchangeName + queueName]}`)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
//Actual magic of publishing message to rabbit when email comes happen here.
|
|
20
|
-
exports.hook_queue = function (next, connection) {
|
|
21
|
-
if (!connection?.transaction) return next()
|
|
22
|
-
|
|
23
|
-
//Calling the get_data method and when it gets the data on callback, publish the message to queue with routing key.
|
|
24
|
-
connection.transaction.message_stream.get_data((buffere) => {
|
|
25
|
-
const exchangeData = exports.exchangeMapping[exchangeName + queueName]
|
|
26
|
-
this.logdebug(`Sending the data: ${queueName} Routing : ${exchangeData} exchange :${connExchange_}`)
|
|
27
|
-
if (connExchange_ && routing_) {
|
|
28
|
-
//This is publish function of rabbitmq amqp library, currently direct queue is configured and routing is fixed.
|
|
29
|
-
//Needs to be changed.
|
|
30
|
-
connExchange_.publish(routing_, buffere, { deliveryMode }, (error) => {
|
|
31
|
-
if (error) {
|
|
32
|
-
//There was some error while sending the email to queue.
|
|
33
|
-
this.logdebug('queueFailure: #{JSON.stringify(error)}')
|
|
34
|
-
exports.init_rabbitmq_server()
|
|
35
|
-
next()
|
|
36
|
-
} else {
|
|
37
|
-
//Queueing was successful, send ok as reply
|
|
38
|
-
this.logdebug('queueSuccess')
|
|
39
|
-
next(OK, 'Successfully Queued! in rabbitmq')
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
} else {
|
|
43
|
-
//Seems like connExchange is not defined , lets create one for next call
|
|
44
|
-
exports.init_rabbitmq_server()
|
|
45
|
-
next()
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
//This initializes the connection to rabbitmq server, It reads values from rabbitmq.ini file in config directory.
|
|
51
|
-
exports.init_rabbitmq_server = function () {
|
|
52
|
-
// this is called during init of rabbitmq
|
|
53
|
-
|
|
54
|
-
//Read the config file rabbitmq
|
|
55
|
-
const config = this.config.get('rabbitmq.ini')
|
|
56
|
-
//Just putting the defaults
|
|
57
|
-
const options = {}
|
|
58
|
-
let confirm = true
|
|
59
|
-
let durable = true
|
|
60
|
-
let autoDelete = false
|
|
61
|
-
let exchangeType = 'direct'
|
|
62
|
-
|
|
63
|
-
//Getting the values from config file rabbitmq.ini
|
|
64
|
-
if (config.rabbitmq) {
|
|
65
|
-
options.host = config.rabbitmq.server_ip || '127.0.0.1'
|
|
66
|
-
options.port = config.rabbitmq.server_port || '5672'
|
|
67
|
-
options.login = config.rabbitmq.user || 'guest'
|
|
68
|
-
options.password = config.rabbitmq.password || 'guest'
|
|
69
|
-
exchangeName = config.rabbitmq.exchangeName || 'emailMessages'
|
|
70
|
-
exchangeType = config.rabbitmq.exchangeType || 'direct'
|
|
71
|
-
confirm = config.rabbitmq.confirm === 'true' || true
|
|
72
|
-
durable = config.rabbitmq.durable === 'true' || true
|
|
73
|
-
autoDelete = config.rabbitmq.autoDelete === 'true' || false
|
|
74
|
-
deliveryMode = config.rabbitmq.deliveryMode || 2
|
|
75
|
-
queueName = config.rabbitmq.queueName || 'emails'
|
|
76
|
-
} else {
|
|
77
|
-
//If config file is not available , lets get the default values
|
|
78
|
-
queueName = 'emails'
|
|
79
|
-
exchangeName = 'emailMessages'
|
|
80
|
-
deliveryMode = 2
|
|
81
|
-
durable = true
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
//Create connection to the rabbitmq server
|
|
85
|
-
this.logdebug('About to Create connection with server')
|
|
86
|
-
rabbitqueue = amqp.createConnection(options)
|
|
87
|
-
|
|
88
|
-
//Declaring listerner on error on connection.
|
|
89
|
-
rabbitqueue.on('error', (error) => {
|
|
90
|
-
this.logerror(`There was some error on the connection : ${error}`)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
//Declaring listerner on close on connection.
|
|
94
|
-
rabbitqueue.on('close', (close) => {
|
|
95
|
-
this.logdebug(` Connection is being closed : ${close}`)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
/* Declaring the function to perform when connection is established and ready, function involves like:
|
|
99
|
-
* 1. Creating or connecting to Exchange.
|
|
100
|
-
* 2. Creating or connecting to Queue.
|
|
101
|
-
* 3. Binding the Exchange and Queue.
|
|
102
|
-
* 4. Saving some variables in global to be used while publishing message.
|
|
103
|
-
*/
|
|
104
|
-
|
|
105
|
-
rabbitqueue.on('ready', () => {
|
|
106
|
-
this.logdebug('Connection is ready, will try making exchange')
|
|
107
|
-
// Now connection is ready will try to open exchange with config data.
|
|
108
|
-
rabbitqueue.exchange(exchangeName, { type: exchangeType, confirm, durable }, (connExchange) => {
|
|
109
|
-
this.logdebug(`connExchange with server ${connExchange} autoDelete : ${autoDelete}`)
|
|
110
|
-
|
|
111
|
-
//Exchange is now open, will try to open queue.
|
|
112
|
-
return rabbitqueue.queue(queueName, { autoDelete, durable }, (connQueue) => {
|
|
113
|
-
this.logdebug(`connQueue with server ${connQueue}`)
|
|
114
|
-
|
|
115
|
-
//Creating the Routing key to bind the queue and exchange.
|
|
116
|
-
const routing = `${queueName}Routing`
|
|
117
|
-
|
|
118
|
-
// Will try to bing queue and exchange which was created above.
|
|
119
|
-
connQueue.bind(connExchange, routing)
|
|
120
|
-
const key = exchangeName + queueName
|
|
121
|
-
|
|
122
|
-
//Save the variables for publising later.
|
|
123
|
-
if (!exports.exchangeMapping[key]) {
|
|
124
|
-
exports.exchangeMapping[key] = []
|
|
125
|
-
}
|
|
126
|
-
connExchange_ = connExchange
|
|
127
|
-
connQueue_ = connQueue
|
|
128
|
-
routing_ = routing
|
|
129
|
-
exports.exchangeMapping[key].push({
|
|
130
|
-
exchange: connExchange_,
|
|
131
|
-
queue: connQueue_,
|
|
132
|
-
routing: routing_,
|
|
133
|
-
queueName,
|
|
134
|
-
})
|
|
135
|
-
this.logdebug(
|
|
136
|
-
`exchange: ${exchangeName}, queue: ${queueName} exchange : ${connExchange_} queue : ${connQueue_}`,
|
|
137
|
-
)
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
})
|
|
141
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// queue/rabbitmq_amqplib
|
|
2
|
-
|
|
3
|
-
const amqp = require('amqplib/callback_api')
|
|
4
|
-
|
|
5
|
-
let channel
|
|
6
|
-
let queue
|
|
7
|
-
let deliveryMode
|
|
8
|
-
let priority
|
|
9
|
-
|
|
10
|
-
exports.register = function () {
|
|
11
|
-
this.init_amqp_connection()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.rabbitmq_queue = function (next, connection) {
|
|
15
|
-
if (!connection?.transaction) return next()
|
|
16
|
-
|
|
17
|
-
connection.transaction.message_stream.get_data((str) => {
|
|
18
|
-
const sendOptions = { deliveryMode }
|
|
19
|
-
if (priority != null) {
|
|
20
|
-
sendOptions.priority = priority
|
|
21
|
-
}
|
|
22
|
-
if (channel?.sendToQueue(queue, str, sendOptions)) {
|
|
23
|
-
return next(OK)
|
|
24
|
-
} else {
|
|
25
|
-
this.logerror('Failed to queue to rabbitmq')
|
|
26
|
-
return next()
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
exports.init_amqp_connection = function () {
|
|
32
|
-
const cfg = this.config.get('rabbitmq.ini').rabbitmq
|
|
33
|
-
|
|
34
|
-
const protocol = cfg.protocol || 'amqp'
|
|
35
|
-
const host = cfg.host || '127.0.0.1'
|
|
36
|
-
const port = cfg.port || '5672'
|
|
37
|
-
const vhost = cfg.vhost || ''
|
|
38
|
-
const user = cfg.user || 'guest'
|
|
39
|
-
const password = cfg.password || 'guest'
|
|
40
|
-
const exchangeName = cfg.exchangeName || 'emailMessages'
|
|
41
|
-
const exchangeType = cfg.exchangeType || 'direct'
|
|
42
|
-
const queueName = cfg.queueName || 'emails'
|
|
43
|
-
const durable = cfg.durable === 'true' || true
|
|
44
|
-
// var confirm = cfg.confirm === "true" || true;
|
|
45
|
-
const autoDelete = cfg.autoDelete === 'true' || false
|
|
46
|
-
deliveryMode = cfg.deliveryMode || 2
|
|
47
|
-
priority = cfg.priority
|
|
48
|
-
|
|
49
|
-
amqp.connect(
|
|
50
|
-
`${protocol}://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:${port}${vhost}`,
|
|
51
|
-
(err, conn) => {
|
|
52
|
-
if (err) {
|
|
53
|
-
this.logerror(`Connection to rabbitmq failed: ${err}`)
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
// TODO: if !confirm conn.createChannel...
|
|
57
|
-
conn.createConfirmChannel((err2, ch) => {
|
|
58
|
-
if (err2) {
|
|
59
|
-
this.logerror(`Error creating rabbitmq channel: ${err2}`)
|
|
60
|
-
return conn.close()
|
|
61
|
-
}
|
|
62
|
-
ch.assertExchange(
|
|
63
|
-
exchangeName,
|
|
64
|
-
exchangeType,
|
|
65
|
-
{
|
|
66
|
-
durable,
|
|
67
|
-
arguments: this.config.get('rabbitmq.ini').exchange_args,
|
|
68
|
-
},
|
|
69
|
-
(err3, ok) => {
|
|
70
|
-
if (err3) {
|
|
71
|
-
this.logerror(`Error asserting rabbitmq exchange: ${err3}`)
|
|
72
|
-
return conn.close()
|
|
73
|
-
}
|
|
74
|
-
ch.assertQueue(
|
|
75
|
-
queueName,
|
|
76
|
-
{
|
|
77
|
-
durable,
|
|
78
|
-
autoDelete,
|
|
79
|
-
arguments: this.config.get('rabbitmq.ini').queue_args,
|
|
80
|
-
},
|
|
81
|
-
(err4, ok2) => {
|
|
82
|
-
if (err4) {
|
|
83
|
-
this.logerror(`Error asserting rabbitmq queue: ${err4}`)
|
|
84
|
-
return conn.close()
|
|
85
|
-
}
|
|
86
|
-
queue = ok2.queue
|
|
87
|
-
channel = ch
|
|
88
|
-
this.register_hook('queue', 'rabbitmq_queue')
|
|
89
|
-
},
|
|
90
|
-
)
|
|
91
|
-
},
|
|
92
|
-
)
|
|
93
|
-
})
|
|
94
|
-
},
|
|
95
|
-
)
|
|
96
|
-
}
|
package/test/config/tls/ec.pem
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
-----BEGIN EC PARAMETERS-----
|
|
2
|
-
BggqhkjOPQMBBw==
|
|
3
|
-
-----END EC PARAMETERS-----
|
|
4
|
-
-----BEGIN EC PRIVATE KEY-----
|
|
5
|
-
MHcCAQEEIIDhiI5q6l7txfMJ6kIEYjK12EFcHLvDIkfWIwzdZBsloAoGCCqGSM49
|
|
6
|
-
AwEHoUQDQgAEZg2nHEFy9nquFPF3DQyQE28e/ytjXeb4nD/8U+L4KHKFtglaX3R4
|
|
7
|
-
uZ+5JcwfcDghpL4Z8h4ouUD/xqe957e2+g==
|
|
8
|
-
-----END EC PRIVATE KEY-----
|
|
9
|
-
-----BEGIN CERTIFICATE-----
|
|
10
|
-
MIICaTCCAg+gAwIBAgIUEDa9VX16wCdo97WvIk7jyEBz1wQwCgYIKoZIzj0EAwIw
|
|
11
|
-
gYkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT
|
|
12
|
-
ZWF0dGxlMRQwEgYDVQQKDAtIYXJha2EgTWFpbDEXMBUGA1UEAwwObWFpbC5oYXJh
|
|
13
|
-
a2EuaW8xJDAiBgkqhkiG9w0BCQEWFWhhcmFrYS5tYWlsQGdtYWlsLmNvbTAeFw0y
|
|
14
|
-
MTEwMTQwNjQxMTlaFw0yMjEwMTQwNjQxMTlaMIGJMQswCQYDVQQGEwJVUzETMBEG
|
|
15
|
-
A1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEUMBIGA1UECgwLSGFy
|
|
16
|
-
YWthIE1haWwxFzAVBgNVBAMMDm1haWwuaGFyYWthLmlvMSQwIgYJKoZIhvcNAQkB
|
|
17
|
-
FhVoYXJha2EubWFpbEBnbWFpbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
|
|
18
|
-
AARmDaccQXL2eq4U8XcNDJATbx7/K2Nd5vicP/xT4vgocoW2CVpfdHi5n7klzB9w
|
|
19
|
-
OCGkvhnyHii5QP/Gp73nt7b6o1MwUTAdBgNVHQ4EFgQU094ROMLHmLEspT4ZoCfX
|
|
20
|
-
Rz0mR/YwHwYDVR0jBBgwFoAU094ROMLHmLEspT4ZoCfXRz0mR/YwDwYDVR0TAQH/
|
|
21
|
-
BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAsmshzvMDjmYDHyGRrKdMmsnnESFd
|
|
22
|
-
GMtfRXYIv0AZe7ICIGD2Sta9LL0zZ44ARGXhh+sPjxd78I/+0FdIPsofr2I+
|
|
23
|
-
-----END CERTIFICATE-----
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDcg5h5TVO1gECK
|
|
3
|
-
yNCXbpJduNqJvhE6hyVb9q0WRR8zKHE7DnOog9JqOcrz4mv3TmszDZ2511mGxo/v
|
|
4
|
-
j2dAYakU7HxEuSqKX1CsjbDP3xa7IvVCaKQbcMImq7dzmenXkCdPivuglZmooZen
|
|
5
|
-
c18QZ6YkrunDeh/OcP8WAA+9yYXp82lmKPzKNkJETfGVXff0loXWR5SSjGXYvjqm
|
|
6
|
-
XK6IXqPcuNriUTmylLx2149O6RWJPaZ2YYxTOHTeV5OMeEHjLpAOShCfZi4VYvAe
|
|
7
|
-
GZSFq5UdMv5QD1k6BueS1Ruf6ChCLjfqkMcCAw8DOY8oxvzovgM/sgBcx3L00/pe
|
|
8
|
-
QeSegG+3AgMBAAECggEAW9qJEcYvH0SMHgNmOB375ARTK9s7S/jti/Aly0gBpgqr
|
|
9
|
-
l+D+NmyqokruikZ/mKVWrA546+eTSDu/yxcd+Eh16NxVKz9CRB9N+IKQ6xXPXyZB
|
|
10
|
-
qWbzLOb8SKVwpjuvl3ZZmZ2YER0fw4mEJWE+cRPrtg4SG7XsN88DwoNGC1U9beSL
|
|
11
|
-
vZ3lDuOMHNBNGx5k608i5HCV8Ty3Sz8ksvL9fPFwUpKAvRuG3lYgS+GxSrijH+KO
|
|
12
|
-
vIwXAu3E+7MIPXdbsg14HBRRHEfyQlRGV8rj3e8neDLFarB8fXDVqIsko6/D5qZZ
|
|
13
|
-
D/jXYW7pcafOGT0PTbHxUMrUxahhAjKKfPt3Y7JVcQKBgQDzIhmN7SbQvu2dl54X
|
|
14
|
-
XezrgKteDVd4q7VYVpiAjNEZA+kNdBcXC6k2T5WMNPesNwyFIoDLDFWUg4FMG/Mc
|
|
15
|
-
KA1eArBocGQ0gQvLlnlUxBy519e/AAj7jTspLi7gAwLqfTo0TGdTH/Hfq+1uCXys
|
|
16
|
-
dd3BKYnDKc4aDPTQCEkRzfPHDwKBgQDoLw7MZecGnNNrqArqsOaOO1uUKFysW6pi
|
|
17
|
-
2ZU7KKj1x6vKGIW88YmzNBPCj4LU8XlXbR1isaSs5TaWgc6N0aAEXwA6TN/8PXhq
|
|
18
|
-
6IXarR1WJIq2DEDtdBrj2AiaPoF8Y6hsebsQs+EpyLx8MCGLaucYJvqyK87ep000
|
|
19
|
-
mXQuyfgM2QKBgHCLy2qAaeRdTV8S7TKB3wcQ88LAyEnqqjJvO37eMHi076+zmnCn
|
|
20
|
-
jDfA1UgmyLNmdBw44YeceQ0bZsHVek8BV1a6RfDCfhAz4ELor9eGRInemVcn7ACN
|
|
21
|
-
2uHwJ/C4VCQ5vbSx3W6ELhHM40Z5i8XFddZRpRy7gFVcxAJ8o15jiMIPAoGAHiq3
|
|
22
|
-
DoGS8b4AjjVILdQMMKCvtmFEITTLv4orpIMU6NInlNt4zOLJFFqI0reYtRgmvuAz
|
|
23
|
-
eDZCgiBJ5mY5Mx3wX4EEY47Hb1uBQMqzUYU6kY2v5BVVfkSelcnk3D2Qz1uXb3il
|
|
24
|
-
gHcOo0IskyohwZ6DJhUyb2HXwAAWvOXPPaEKNIkCgYAqWhzYCAoxZ6f7i2I3J1JO
|
|
25
|
-
5OaMi4+9YR3ivTDcKVYp1ZOzANe0gsQlal/gf2fTjG35b9FyK3Lo5rp0QLKxv2vh
|
|
26
|
-
6dR+sk+58jJhk8H1kPNIVzvA4SAd51YoE0x7edi7+5vDMwlz57yz5rwMQvN1wUOO
|
|
27
|
-
5Ev9F9qrVJZFF4Ei+fRW9Q==
|
|
28
|
-
-----END PRIVATE KEY-----
|
|
29
|
-
-----BEGIN CERTIFICATE-----
|
|
30
|
-
MIIDXTCCAkWgAwIBAgIJAIloeq99SSuwMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
|
31
|
-
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
|
32
|
-
aWRnaXRzIFB0eSBMdGQwHhcNMTcwMTMxMDQyNTIwWhcNMjMwMTMwMDQyNTIwWjBF
|
|
33
|
-
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
|
34
|
-
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
35
|
-
CgKCAQEAyMYkzD7HnZ29d83Hi2cTOVRsNJX/oTwwq7SiZwm8cwt/bMj4pK2XFxHK
|
|
36
|
-
0UDHSTgERKLSTCZJRvvGnWyBGRfTkdYui605gxlcmUkvHY5ZJ658iLnFCyrKkTj6
|
|
37
|
-
hZOCtD2Y4P0WUItt4LsU+5smluZoJeeNfJG3os77LHb2G7j2U8UbKyH5uYRGecmt
|
|
38
|
-
cuFfIPUxny2Mom+3BySb1QDOcMO1JtI2IzbuRKUlWicIjhqGyYTm5ceZoGt18hSC
|
|
39
|
-
xilH2dT59rB2XKZ2gR1oA/Zj7EXCxzUvw48JuPZgbayuhRgDIPJVh26PDR5atYkq
|
|
40
|
-
/RUtMaeurPTL++BUrGYTObLw86h1FwIDAQABo1AwTjAdBgNVHQ4EFgQUsW4yJbIS
|
|
41
|
-
kLw2Q3V2a2vjWkzGo3owHwYDVR0jBBgwFoAUsW4yJbISkLw2Q3V2a2vjWkzGo3ow
|
|
42
|
-
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAjom2PQHtX0hCpMZovIoA
|
|
43
|
-
JHeGMffuoP2N1445SMkxvxfcawK4LP/eeTvHGsBukBsVqa206orqooYVd3UWtcSQ
|
|
44
|
-
rKfkwM0fQ1j7vCswJfCE3HIGtPyUTrtQHLAbu0vNeIlAH2v/wJZ+rhjIc3DrN8dt
|
|
45
|
-
u2dnErb4V/KM5f3vlyZQgLvwJisx/vzvTYD0GC0XteHwxkJ6mpnH3ORDVyLaBZA3
|
|
46
|
-
bFkuB7iwp4frwdvdcIDYVcuFBaLcu1zoJuSdEYNXo5d4Ji6hnSTyZsXz4jkGoH7n
|
|
47
|
-
5OLoHzF0lY9EpyLMdINWOyodxTEXjKUWggSUKsFRWkb8cTUjp+0lfvFiJ6gs3H+a
|
|
48
|
-
sQ==
|
|
49
|
-
-----END CERTIFICATE-----
|