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
|
@@ -1,135 +1,133 @@
|
|
|
1
1
|
// quarantine
|
|
2
2
|
|
|
3
|
-
const fs
|
|
4
|
-
const path = require('node:path')
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
5
|
|
|
6
6
|
exports.register = function () {
|
|
7
|
+
this.load_quarantine_ini()
|
|
7
8
|
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
this.register_hook('queue', 'quarantine');
|
|
11
|
-
this.register_hook('queue_outbound', 'quarantine');
|
|
9
|
+
this.register_hook('queue', 'quarantine')
|
|
10
|
+
this.register_hook('queue_outbound', 'quarantine')
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
exports.hook_init_master = function (next, server) {
|
|
15
14
|
this.init_quarantine_dir(() => {
|
|
16
|
-
this.clean_tmp_directory(next)
|
|
17
|
-
})
|
|
15
|
+
this.clean_tmp_directory(next)
|
|
16
|
+
})
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
exports.load_quarantine_ini = function () {
|
|
21
20
|
this.cfg = this.config.get('quarantine.ini', () => {
|
|
22
|
-
this.load_quarantine_ini()
|
|
21
|
+
this.load_quarantine_ini()
|
|
23
22
|
})
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
const zeroPad = exports.zeroPad = (n, digits) => {
|
|
27
|
-
n = n.toString()
|
|
25
|
+
const zeroPad = (exports.zeroPad = (n, digits) => {
|
|
26
|
+
n = n.toString()
|
|
28
27
|
while (n.length < digits) {
|
|
29
|
-
n = `0${n}
|
|
28
|
+
n = `0${n}`
|
|
30
29
|
}
|
|
31
|
-
return n
|
|
32
|
-
}
|
|
30
|
+
return n
|
|
31
|
+
})
|
|
33
32
|
|
|
34
33
|
exports.clean_tmp_directory = function (next) {
|
|
35
|
-
const tmp_dir = path.join(this.get_base_dir(), 'tmp')
|
|
34
|
+
const tmp_dir = path.join(this.get_base_dir(), 'tmp')
|
|
36
35
|
|
|
37
36
|
if (fs.existsSync(tmp_dir)) {
|
|
38
|
-
const dirent = fs.readdirSync(tmp_dir)
|
|
39
|
-
this.loginfo(`Removing temporary files from: ${tmp_dir}`)
|
|
37
|
+
const dirent = fs.readdirSync(tmp_dir)
|
|
38
|
+
this.loginfo(`Removing temporary files from: ${tmp_dir}`)
|
|
40
39
|
for (const element of dirent) {
|
|
41
|
-
fs.unlinkSync(path.join(tmp_dir, element))
|
|
40
|
+
fs.unlinkSync(path.join(tmp_dir, element))
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
|
-
next()
|
|
43
|
+
next()
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
function wants_quarantine
|
|
46
|
+
function wants_quarantine(connection) {
|
|
48
47
|
const { notes, transaction } = connection ?? {}
|
|
49
48
|
|
|
50
|
-
if (notes.quarantine) return notes.quarantine
|
|
49
|
+
if (notes.quarantine) return notes.quarantine
|
|
51
50
|
|
|
52
|
-
if (transaction.notes.quarantine) return transaction.notes.quarantine
|
|
51
|
+
if (transaction.notes.quarantine) return transaction.notes.quarantine
|
|
53
52
|
|
|
54
|
-
return transaction.notes.get('queue.wants') === 'quarantine'
|
|
53
|
+
return transaction.notes.get('queue.wants') === 'quarantine'
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
exports.get_base_dir = function () {
|
|
58
|
-
if (this.cfg.main.quarantine_path) return this.cfg.main.quarantine_path
|
|
59
|
-
return '/var/spool/haraka/quarantine'
|
|
57
|
+
if (this.cfg.main.quarantine_path) return this.cfg.main.quarantine_path
|
|
58
|
+
return '/var/spool/haraka/quarantine'
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
exports.init_quarantine_dir = function (done) {
|
|
63
|
-
const tmp_dir = path.join(this.get_base_dir(), 'tmp')
|
|
64
|
-
fs.promises
|
|
65
|
-
.
|
|
66
|
-
.
|
|
67
|
-
.
|
|
62
|
+
const tmp_dir = path.join(this.get_base_dir(), 'tmp')
|
|
63
|
+
fs.promises
|
|
64
|
+
.mkdir(tmp_dir, { recursive: true })
|
|
65
|
+
.then((made) => this.loginfo(`created ${tmp_dir}`))
|
|
66
|
+
.catch((err) => this.logerror(`Unable to create ${tmp_dir}`))
|
|
67
|
+
.finally(done)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
exports.quarantine = function (next, connection) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (!quarantine) return next();
|
|
71
|
+
const quarantine = wants_quarantine(connection)
|
|
72
|
+
this.logdebug(`quarantine: ${quarantine}`)
|
|
73
|
+
if (!quarantine) return next()
|
|
75
74
|
|
|
76
75
|
// Calculate date in YYYYMMDD format
|
|
77
|
-
const d = new Date()
|
|
78
|
-
const yyyymmdd = d.getFullYear() + zeroPad(d.getMonth()+1, 2)
|
|
79
|
-
+ this.zeroPad(d.getDate(), 2);
|
|
76
|
+
const d = new Date()
|
|
77
|
+
const yyyymmdd = d.getFullYear() + zeroPad(d.getMonth() + 1, 2) + this.zeroPad(d.getDate(), 2)
|
|
80
78
|
|
|
81
|
-
let subdir = yyyymmdd
|
|
79
|
+
let subdir = yyyymmdd
|
|
82
80
|
// Allow either boolean or a sub-directory to be specified
|
|
83
81
|
|
|
84
82
|
if (typeof quarantine !== 'boolean' && quarantine !== 1) {
|
|
85
|
-
subdir = path.join(quarantine, yyyymmdd)
|
|
83
|
+
subdir = path.join(quarantine, yyyymmdd)
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
const txn = connection?.transaction
|
|
89
|
-
if (!txn) return next()
|
|
86
|
+
const txn = connection?.transaction
|
|
87
|
+
if (!txn) return next()
|
|
90
88
|
|
|
91
|
-
const base_dir = this.get_base_dir()
|
|
92
|
-
const msg_dir
|
|
93
|
-
const tmp_path = path.join(base_dir, 'tmp', txn.uuid)
|
|
94
|
-
const msg_path = path.join(msg_dir, txn.uuid)
|
|
89
|
+
const base_dir = this.get_base_dir()
|
|
90
|
+
const msg_dir = path.join(base_dir, subdir)
|
|
91
|
+
const tmp_path = path.join(base_dir, 'tmp', txn.uuid)
|
|
92
|
+
const msg_path = path.join(msg_dir, txn.uuid)
|
|
95
93
|
|
|
96
94
|
// Create all the directories recursively if they do not exist.
|
|
97
95
|
// Then write the file to a temporary directory first, once this is
|
|
98
96
|
// successful we hardlink the file to the final destination and then
|
|
99
97
|
// remove the temporary file to guarantee a complete file in the
|
|
100
98
|
// final destination.
|
|
101
|
-
fs.promises
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
fs.promises
|
|
100
|
+
.mkdir(msg_dir, { recursive: true })
|
|
101
|
+
.catch((err) => {
|
|
102
|
+
connection.logerror(this, `Error creating directory: ${msg_dir}`)
|
|
103
|
+
next()
|
|
105
104
|
})
|
|
106
|
-
.then(ok => {
|
|
107
|
-
const ws = fs.createWriteStream(tmp_path)
|
|
105
|
+
.then((ok) => {
|
|
106
|
+
const ws = fs.createWriteStream(tmp_path)
|
|
108
107
|
|
|
109
|
-
ws.on('error', err => {
|
|
110
|
-
connection.logerror(this, `Error writing quarantine file: ${err.message}`)
|
|
111
|
-
return next()
|
|
112
|
-
})
|
|
108
|
+
ws.on('error', (err) => {
|
|
109
|
+
connection.logerror(this, `Error writing quarantine file: ${err.message}`)
|
|
110
|
+
return next()
|
|
111
|
+
})
|
|
113
112
|
ws.on('close', () => {
|
|
114
|
-
fs.link(tmp_path, msg_path, err => {
|
|
113
|
+
fs.link(tmp_path, msg_path, (err) => {
|
|
115
114
|
if (err) {
|
|
116
|
-
connection.logerror(this, `Error writing quarantine file: ${err}`)
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
115
|
+
connection.logerror(this, `Error writing quarantine file: ${err}`)
|
|
116
|
+
} else {
|
|
119
117
|
// Add a note to where we stored the message
|
|
120
|
-
txn.notes.quarantined = msg_path
|
|
121
|
-
txn.results.add(this, { pass: msg_path, emit: true })
|
|
118
|
+
txn.notes.quarantined = msg_path
|
|
119
|
+
txn.results.add(this, { pass: msg_path, emit: true })
|
|
122
120
|
// Now delete the temporary file
|
|
123
|
-
fs.unlink(tmp_path, () => {})
|
|
121
|
+
fs.unlink(tmp_path, () => {})
|
|
124
122
|
}
|
|
125
123
|
// Using notes.quarantine_action to decide what to do after the message is quarantined.
|
|
126
124
|
// Format can be either action = [ code, msg ] or action = code
|
|
127
|
-
const action =
|
|
128
|
-
if (!action) return next()
|
|
129
|
-
if (Array.isArray(action)) return next(action[0], action[1])
|
|
130
|
-
return next(action)
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
txn.message_stream.pipe(ws, { line_endings: '\n' })
|
|
134
|
-
})
|
|
125
|
+
const action = connection.notes.quarantine_action || txn.notes.quarantine_action
|
|
126
|
+
if (!action) return next()
|
|
127
|
+
if (Array.isArray(action)) return next(action[0], action[1])
|
|
128
|
+
return next(action)
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
txn.message_stream.pipe(ws, { line_endings: '\n' })
|
|
132
|
+
})
|
|
135
133
|
}
|
|
@@ -1,53 +1,50 @@
|
|
|
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_
|
|
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
10
|
exports.exchangeMapping = {}
|
|
11
11
|
|
|
12
12
|
//This method registers the hook and try to initialize the connection to rabbitmq server for later use.
|
|
13
13
|
exports.register = function () {
|
|
14
|
-
this.logdebug(
|
|
15
|
-
this.init_rabbitmq_server()
|
|
16
|
-
this.logdebug(`Finished initiating : ${exports.exchangeMapping[exchangeName + queueName]}`)
|
|
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
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
//Actual magic of publishing message to rabbit when email comes happen here.
|
|
21
20
|
exports.hook_queue = function (next, connection) {
|
|
22
|
-
if (!connection?.transaction) return next()
|
|
21
|
+
if (!connection?.transaction) return next()
|
|
23
22
|
|
|
24
23
|
//Calling the get_data method and when it gets the data on callback, publish the message to queue with routing key.
|
|
25
|
-
connection.transaction.message_stream.get_data(buffere => {
|
|
24
|
+
connection.transaction.message_stream.get_data((buffere) => {
|
|
26
25
|
const exchangeData = exports.exchangeMapping[exchangeName + queueName]
|
|
27
|
-
this.logdebug(`Sending the data: ${
|
|
26
|
+
this.logdebug(`Sending the data: ${queueName} Routing : ${exchangeData} exchange :${connExchange_}`)
|
|
28
27
|
if (connExchange_ && routing_) {
|
|
29
28
|
//This is publish function of rabbitmq amqp library, currently direct queue is configured and routing is fixed.
|
|
30
29
|
//Needs to be changed.
|
|
31
|
-
connExchange_.publish(routing_, buffere,{deliveryMode}, error => {
|
|
30
|
+
connExchange_.publish(routing_, buffere, { deliveryMode }, (error) => {
|
|
32
31
|
if (error) {
|
|
33
32
|
//There was some error while sending the email to queue.
|
|
34
|
-
this.logdebug(
|
|
35
|
-
exports.init_rabbitmq_server()
|
|
36
|
-
next()
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
33
|
+
this.logdebug('queueFailure: #{JSON.stringify(error)}')
|
|
34
|
+
exports.init_rabbitmq_server()
|
|
35
|
+
next()
|
|
36
|
+
} else {
|
|
39
37
|
//Queueing was successful, send ok as reply
|
|
40
|
-
this.logdebug(
|
|
41
|
-
next(OK,
|
|
38
|
+
this.logdebug('queueSuccess')
|
|
39
|
+
next(OK, 'Successfully Queued! in rabbitmq')
|
|
42
40
|
}
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
41
|
+
})
|
|
42
|
+
} else {
|
|
46
43
|
//Seems like connExchange is not defined , lets create one for next call
|
|
47
|
-
exports.init_rabbitmq_server()
|
|
48
|
-
next()
|
|
44
|
+
exports.init_rabbitmq_server()
|
|
45
|
+
next()
|
|
49
46
|
}
|
|
50
|
-
})
|
|
47
|
+
})
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
//This initializes the connection to rabbitmq server, It reads values from rabbitmq.ini file in config directory.
|
|
@@ -55,52 +52,48 @@ exports.init_rabbitmq_server = function () {
|
|
|
55
52
|
// this is called during init of rabbitmq
|
|
56
53
|
|
|
57
54
|
//Read the config file rabbitmq
|
|
58
|
-
const config
|
|
55
|
+
const config = this.config.get('rabbitmq.ini')
|
|
59
56
|
//Just putting the defaults
|
|
60
|
-
const options = {}
|
|
61
|
-
let confirm = true
|
|
62
|
-
let durable = true
|
|
63
|
-
let autoDelete = false
|
|
64
|
-
let exchangeType = 'direct'
|
|
57
|
+
const options = {}
|
|
58
|
+
let confirm = true
|
|
59
|
+
let durable = true
|
|
60
|
+
let autoDelete = false
|
|
61
|
+
let exchangeType = 'direct'
|
|
65
62
|
|
|
66
63
|
//Getting the values from config file rabbitmq.ini
|
|
67
64
|
if (config.rabbitmq) {
|
|
68
|
-
options.host = config.rabbitmq.server_ip || '127.0.0.1'
|
|
69
|
-
options.port = config.rabbitmq.server_port || '5672'
|
|
70
|
-
options.login = config.rabbitmq.user || 'guest'
|
|
71
|
-
options.password = config.rabbitmq.password || 'guest'
|
|
72
|
-
exchangeName = config.rabbitmq.exchangeName || 'emailMessages'
|
|
73
|
-
exchangeType = config.rabbitmq.exchangeType || 'direct'
|
|
74
|
-
confirm = config.rabbitmq.confirm === 'true'|| true
|
|
75
|
-
durable = config.rabbitmq.durable === 'true'|| true
|
|
76
|
-
autoDelete = config.rabbitmq.autoDelete === 'true' || false
|
|
77
|
-
deliveryMode = config.rabbitmq.deliveryMode || 2
|
|
78
|
-
queueName = config.rabbitmq.queueName || 'emails'
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
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 {
|
|
81
77
|
//If config file is not available , lets get the default values
|
|
82
|
-
queueName = 'emails'
|
|
83
|
-
exchangeName = 'emailMessages'
|
|
84
|
-
deliveryMode = 2
|
|
85
|
-
durable = true
|
|
78
|
+
queueName = 'emails'
|
|
79
|
+
exchangeName = 'emailMessages'
|
|
80
|
+
deliveryMode = 2
|
|
81
|
+
durable = true
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
|
|
89
84
|
//Create connection to the rabbitmq server
|
|
90
|
-
this.logdebug(
|
|
91
|
-
rabbitqueue = amqp.createConnection(options)
|
|
92
|
-
|
|
85
|
+
this.logdebug('About to Create connection with server')
|
|
86
|
+
rabbitqueue = amqp.createConnection(options)
|
|
93
87
|
|
|
94
88
|
//Declaring listerner on error on connection.
|
|
95
|
-
rabbitqueue.on('error', error => {
|
|
96
|
-
this.logerror(`There was some error on the connection : ${error}`)
|
|
97
|
-
})
|
|
89
|
+
rabbitqueue.on('error', (error) => {
|
|
90
|
+
this.logerror(`There was some error on the connection : ${error}`)
|
|
91
|
+
})
|
|
98
92
|
|
|
99
93
|
//Declaring listerner on close on connection.
|
|
100
|
-
rabbitqueue.on('close', close => {
|
|
101
|
-
this.logdebug(` Connection is being closed : ${close}`)
|
|
102
|
-
})
|
|
103
|
-
|
|
94
|
+
rabbitqueue.on('close', (close) => {
|
|
95
|
+
this.logdebug(` Connection is being closed : ${close}`)
|
|
96
|
+
})
|
|
104
97
|
|
|
105
98
|
/* Declaring the function to perform when connection is established and ready, function involves like:
|
|
106
99
|
* 1. Creating or connecting to Exchange.
|
|
@@ -110,39 +103,39 @@ exports.init_rabbitmq_server = function () {
|
|
|
110
103
|
*/
|
|
111
104
|
|
|
112
105
|
rabbitqueue.on('ready', () => {
|
|
113
|
-
this.logdebug(
|
|
106
|
+
this.logdebug('Connection is ready, will try making exchange')
|
|
114
107
|
// Now connection is ready will try to open exchange with config data.
|
|
115
|
-
rabbitqueue.exchange(exchangeName, {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.logdebug(`connExchange with server ${connExchange} autoDelete : ${autoDelete}`);
|
|
108
|
+
rabbitqueue.exchange(exchangeName, { type: exchangeType, confirm, durable }, (connExchange) => {
|
|
109
|
+
this.logdebug(`connExchange with server ${connExchange} autoDelete : ${autoDelete}`)
|
|
119
110
|
|
|
120
111
|
//Exchange is now open, will try to open queue.
|
|
121
|
-
return rabbitqueue.queue(queueName,{autoDelete, durable }, connQueue => {
|
|
122
|
-
this.logdebug(`connQueue with server ${connQueue}`)
|
|
112
|
+
return rabbitqueue.queue(queueName, { autoDelete, durable }, (connQueue) => {
|
|
113
|
+
this.logdebug(`connQueue with server ${connQueue}`)
|
|
123
114
|
|
|
124
115
|
//Creating the Routing key to bind the queue and exchange.
|
|
125
|
-
const routing = `${queueName}Routing
|
|
116
|
+
const routing = `${queueName}Routing`
|
|
126
117
|
|
|
127
118
|
// Will try to bing queue and exchange which was created above.
|
|
128
|
-
connQueue.bind(connExchange, routing)
|
|
129
|
-
const key = exchangeName + queueName
|
|
119
|
+
connQueue.bind(connExchange, routing)
|
|
120
|
+
const key = exchangeName + queueName
|
|
130
121
|
|
|
131
122
|
//Save the variables for publising later.
|
|
132
123
|
if (!exports.exchangeMapping[key]) {
|
|
133
|
-
exports.exchangeMapping[key] = []
|
|
124
|
+
exports.exchangeMapping[key] = []
|
|
134
125
|
}
|
|
135
|
-
connExchange_ = connExchange
|
|
136
|
-
connQueue_ = connQueue
|
|
137
|
-
routing_ = routing
|
|
126
|
+
connExchange_ = connExchange
|
|
127
|
+
connQueue_ = connQueue
|
|
128
|
+
routing_ = routing
|
|
138
129
|
exports.exchangeMapping[key].push({
|
|
139
|
-
exchange
|
|
140
|
-
queue
|
|
141
|
-
routing
|
|
142
|
-
queueName
|
|
143
|
-
})
|
|
144
|
-
this.logdebug(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
+
})
|
|
148
141
|
}
|
|
@@ -1,75 +1,96 @@
|
|
|
1
1
|
// queue/rabbitmq_amqplib
|
|
2
2
|
|
|
3
|
-
const amqp = require(
|
|
3
|
+
const amqp = require('amqplib/callback_api')
|
|
4
4
|
|
|
5
|
-
let channel
|
|
6
|
-
let queue
|
|
7
|
-
let deliveryMode
|
|
5
|
+
let channel
|
|
6
|
+
let queue
|
|
7
|
+
let deliveryMode
|
|
8
|
+
let priority
|
|
8
9
|
|
|
9
10
|
exports.register = function () {
|
|
10
|
-
this.init_amqp_connection()
|
|
11
|
+
this.init_amqp_connection()
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
exports.rabbitmq_queue = function (next, connection) {
|
|
14
|
-
if (!connection?.transaction) return next()
|
|
15
|
+
if (!connection?.transaction) return next()
|
|
15
16
|
|
|
16
|
-
connection.transaction.message_stream.get_data(str => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
connection.transaction.message_stream.get_data((str) => {
|
|
18
|
+
const sendOptions = { deliveryMode }
|
|
19
|
+
if (priority != null) {
|
|
20
|
+
sendOptions.priority = priority
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
if (channel?.sendToQueue(queue, str, sendOptions)) {
|
|
23
|
+
return next(OK)
|
|
24
|
+
} else {
|
|
25
|
+
this.logerror('Failed to queue to rabbitmq')
|
|
26
|
+
return next()
|
|
23
27
|
}
|
|
24
|
-
})
|
|
28
|
+
})
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
exports.init_amqp_connection = function () {
|
|
28
|
-
const cfg = this.config.get(
|
|
32
|
+
const cfg = this.config.get('rabbitmq.ini').rabbitmq
|
|
29
33
|
|
|
30
|
-
const protocol = cfg.protocol ||
|
|
31
|
-
const host = cfg.host ||
|
|
32
|
-
const port = cfg.port ||
|
|
33
|
-
const vhost = cfg.vhost ||
|
|
34
|
-
const user = cfg.user ||
|
|
35
|
-
const password = cfg.password ||
|
|
36
|
-
const exchangeName = cfg.exchangeName ||
|
|
37
|
-
const exchangeType = cfg.exchangeType ||
|
|
38
|
-
const queueName = cfg.queueName ||
|
|
39
|
-
const durable = cfg.durable ===
|
|
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
|
|
40
44
|
// var confirm = cfg.confirm === "true" || true;
|
|
41
|
-
const autoDelete = cfg.autoDelete ===
|
|
42
|
-
deliveryMode = cfg.deliveryMode || 2
|
|
45
|
+
const autoDelete = cfg.autoDelete === 'true' || false
|
|
46
|
+
deliveryMode = cfg.deliveryMode || 2
|
|
47
|
+
priority = cfg.priority
|
|
43
48
|
|
|
44
|
-
amqp.connect(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
conn.createConfirmChannel((err2, ch) => {
|
|
51
|
-
if (err2) {
|
|
52
|
-
this.logerror(`Error creating rabbitmq channel: ${err2}`);
|
|
53
|
-
return conn.close();
|
|
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
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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()
|
|
59
61
|
}
|
|
60
|
-
ch.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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()
|
|
66
73
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
+
)
|
|
75
96
|
}
|
|
@@ -2,37 +2,37 @@
|
|
|
2
2
|
// Overrides the MX and sets the same AUTH user and password
|
|
3
3
|
|
|
4
4
|
exports.register = function () {
|
|
5
|
-
this.load_flat_ini()
|
|
5
|
+
this.load_flat_ini()
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
exports.load_flat_ini = function () {
|
|
9
9
|
this.cfg = this.config.get('smtp_bridge.ini', () => {
|
|
10
|
-
this.load_flat_ini()
|
|
11
|
-
})
|
|
10
|
+
this.load_flat_ini()
|
|
11
|
+
})
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
exports.hook_data_post = (next, connection) => {
|
|
15
|
-
const txn = connection?.transaction
|
|
16
|
-
if (!txn) return next()
|
|
15
|
+
const txn = connection?.transaction
|
|
16
|
+
if (!txn) return next()
|
|
17
17
|
|
|
18
18
|
// Copy auth notes to transaction notes so they're available in hmail.todo.notes
|
|
19
|
-
txn.notes.auth_user = connection.notes.auth_user
|
|
20
|
-
txn.notes.auth_passwd = connection.notes.auth_passwd
|
|
21
|
-
return next()
|
|
19
|
+
txn.notes.auth_user = connection.notes.auth_user
|
|
20
|
+
txn.notes.auth_passwd = connection.notes.auth_passwd
|
|
21
|
+
return next()
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
exports.hook_get_mx = function (next, hmail, domain) {
|
|
25
|
-
let priority = 10
|
|
25
|
+
let priority = 10
|
|
26
26
|
if (this.cfg.main.priority) {
|
|
27
|
-
priority = this.cfg.main.priority
|
|
27
|
+
priority = this.cfg.main.priority
|
|
28
28
|
}
|
|
29
|
-
let authType = null
|
|
29
|
+
let authType = null
|
|
30
30
|
if (this.cfg.main.auth_type) {
|
|
31
|
-
authType = this.cfg.main.auth_type
|
|
31
|
+
authType = this.cfg.main.auth_type
|
|
32
32
|
}
|
|
33
|
-
let port = null
|
|
33
|
+
let port = null
|
|
34
34
|
if (this.cfg.main.port) {
|
|
35
|
-
port = this.cfg.main.port
|
|
35
|
+
port = this.cfg.main.port
|
|
36
36
|
}
|
|
37
37
|
return next(OK, {
|
|
38
38
|
priority,
|
|
@@ -40,6 +40,6 @@ exports.hook_get_mx = function (next, hmail, domain) {
|
|
|
40
40
|
port,
|
|
41
41
|
auth_type: authType,
|
|
42
42
|
auth_user: hmail.todo.notes.auth_user,
|
|
43
|
-
auth_pass: hmail.todo.notes.auth_passwd
|
|
44
|
-
})
|
|
43
|
+
auth_pass: hmail.todo.notes.auth_passwd,
|
|
44
|
+
})
|
|
45
45
|
}
|