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.
Files changed (160) hide show
  1. package/.prettierignore +4 -0
  2. package/CONTRIBUTORS.md +5 -5
  3. package/Changes.md +62 -50
  4. package/Plugins.md +3 -1
  5. package/README.md +1 -1
  6. package/bin/haraka +475 -479
  7. package/config/outbound.ini +3 -0
  8. package/connection.js +1072 -1108
  9. package/docs/Connection.md +29 -30
  10. package/docs/CoreConfig.md +38 -39
  11. package/docs/CustomReturnCodes.md +0 -1
  12. package/docs/HAProxy.md +2 -2
  13. package/docs/Header.md +1 -1
  14. package/docs/Logging.md +29 -5
  15. package/docs/Outbound.md +93 -78
  16. package/docs/Plugins.md +103 -108
  17. package/docs/Transaction.md +49 -51
  18. package/docs/Tutorial.md +127 -143
  19. package/docs/deprecated/access.md +0 -1
  20. package/docs/deprecated/backscatterer.md +2 -3
  21. package/docs/deprecated/connect.rdns_access.md +18 -27
  22. package/docs/deprecated/data.headers.md +0 -1
  23. package/docs/deprecated/data.nomsgid.md +1 -2
  24. package/docs/deprecated/data.noreceived.md +1 -2
  25. package/docs/deprecated/data.rfc5322_header_checks.md +1 -2
  26. package/docs/deprecated/dkim_sign.md +13 -17
  27. package/docs/deprecated/dkim_verify.md +9 -17
  28. package/docs/deprecated/dnsbl.md +36 -38
  29. package/docs/deprecated/dnswl.md +41 -43
  30. package/docs/deprecated/lookup_rdns.strict.md +21 -34
  31. package/docs/deprecated/mail_from.access.md +17 -25
  32. package/docs/deprecated/mail_from.blocklist.md +9 -12
  33. package/docs/deprecated/mail_from.nobounces.md +1 -2
  34. package/docs/deprecated/rcpt_to.access.md +20 -27
  35. package/docs/deprecated/rcpt_to.blocklist.md +10 -13
  36. package/docs/deprecated/rcpt_to.routes.md +0 -1
  37. package/docs/deprecated/rdns.regexp.md +13 -15
  38. package/docs/plugins/aliases.md +89 -89
  39. package/docs/plugins/auth/auth_bridge.md +5 -7
  40. package/docs/plugins/auth/auth_ldap.md +11 -14
  41. package/docs/plugins/auth/auth_proxy.md +10 -12
  42. package/docs/plugins/auth/auth_vpopmaild.md +5 -6
  43. package/docs/plugins/auth/flat_file.md +4 -4
  44. package/docs/plugins/block_me.md +3 -3
  45. package/docs/plugins/data.signatures.md +1 -2
  46. package/docs/plugins/delay_deny.md +3 -4
  47. package/docs/plugins/max_unrecognized_commands.md +4 -4
  48. package/docs/plugins/prevent_credential_leaks.md +6 -6
  49. package/docs/plugins/process_title.md +18 -18
  50. package/docs/plugins/queue/deliver.md +2 -3
  51. package/docs/plugins/queue/discard.md +4 -4
  52. package/docs/plugins/queue/lmtp.md +1 -3
  53. package/docs/plugins/queue/qmail-queue.md +7 -9
  54. package/docs/plugins/queue/quarantine.md +16 -21
  55. package/docs/plugins/queue/rabbitmq.md +8 -11
  56. package/docs/plugins/queue/rabbitmq_amqplib.md +43 -39
  57. package/docs/plugins/queue/smtp_bridge.md +7 -10
  58. package/docs/plugins/queue/smtp_forward.md +42 -34
  59. package/docs/plugins/queue/smtp_proxy.md +30 -29
  60. package/docs/plugins/queue/test.md +1 -3
  61. package/docs/plugins/rcpt_to.in_host_list.md +6 -6
  62. package/docs/plugins/rcpt_to.max_count.md +1 -1
  63. package/docs/plugins/record_envelope_addresses.md +3 -3
  64. package/docs/plugins/reseed_rng.md +6 -6
  65. package/docs/plugins/status.md +9 -8
  66. package/docs/plugins/tarpit.md +7 -11
  67. package/docs/plugins/tls.md +12 -17
  68. package/docs/plugins/toobusy.md +4 -4
  69. package/docs/plugins/xclient.md +3 -3
  70. package/docs/tutorials/Migrating_from_v1_to_v2.md +19 -41
  71. package/docs/tutorials/SettingUpOutbound.md +6 -9
  72. package/endpoint.js +35 -38
  73. package/eslint.config.mjs +22 -19
  74. package/haraka.js +42 -47
  75. package/host_pool.js +75 -79
  76. package/http/html/404.html +45 -49
  77. package/http/html/index.html +39 -28
  78. package/http/package.json +2 -4
  79. package/line_socket.js +27 -28
  80. package/logger.js +182 -201
  81. package/outbound/client_pool.js +33 -33
  82. package/outbound/config.js +64 -59
  83. package/outbound/fsync_writestream.js +24 -25
  84. package/outbound/hmail.js +888 -835
  85. package/outbound/index.js +194 -187
  86. package/outbound/qfile.js +49 -52
  87. package/outbound/queue.js +197 -190
  88. package/outbound/timer_queue.js +41 -43
  89. package/outbound/tls.js +68 -61
  90. package/outbound/todo.js +11 -11
  91. package/package.json +32 -32
  92. package/plugins/.eslintrc.yaml +0 -1
  93. package/plugins/auth/auth_base.js +123 -127
  94. package/plugins/auth/auth_bridge.js +7 -7
  95. package/plugins/auth/auth_proxy.js +121 -126
  96. package/plugins/auth/auth_vpopmaild.js +84 -85
  97. package/plugins/auth/flat_file.js +18 -17
  98. package/plugins/block_me.js +31 -31
  99. package/plugins/data.signatures.js +13 -13
  100. package/plugins/delay_deny.js +65 -61
  101. package/plugins/prevent_credential_leaks.js +23 -23
  102. package/plugins/process_title.js +125 -128
  103. package/plugins/profile.js +5 -5
  104. package/plugins/queue/deliver.js +3 -3
  105. package/plugins/queue/discard.js +13 -14
  106. package/plugins/queue/lmtp.js +16 -17
  107. package/plugins/queue/qmail-queue.js +54 -55
  108. package/plugins/queue/quarantine.js +68 -70
  109. package/plugins/queue/rabbitmq.js +80 -87
  110. package/plugins/queue/rabbitmq_amqplib.js +75 -54
  111. package/plugins/queue/smtp_bridge.js +16 -16
  112. package/plugins/queue/smtp_forward.js +175 -179
  113. package/plugins/queue/smtp_proxy.js +69 -71
  114. package/plugins/queue/test.js +9 -9
  115. package/plugins/rcpt_to.host_list_base.js +30 -34
  116. package/plugins/rcpt_to.in_host_list.js +19 -19
  117. package/plugins/record_envelope_addresses.js +4 -4
  118. package/plugins/reseed_rng.js +4 -4
  119. package/plugins/status.js +90 -97
  120. package/plugins/tarpit.js +25 -14
  121. package/plugins/tls.js +68 -68
  122. package/plugins/toobusy.js +21 -23
  123. package/plugins/xclient.js +51 -53
  124. package/plugins.js +276 -293
  125. package/rfc1869.js +30 -35
  126. package/server.js +308 -299
  127. package/smtp_client.js +244 -228
  128. package/test/.eslintrc.yaml +0 -1
  129. package/test/connection.js +127 -134
  130. package/test/endpoint.js +53 -47
  131. package/test/fixtures/line_socket.js +12 -12
  132. package/test/fixtures/util_hmailitem.js +89 -85
  133. package/test/host_pool.js +90 -92
  134. package/test/installation/plugins/base_plugin.js +2 -2
  135. package/test/installation/plugins/folder_plugin/index.js +2 -3
  136. package/test/installation/plugins/inherits.js +3 -3
  137. package/test/installation/plugins/load_first.js +2 -3
  138. package/test/installation/plugins/plugin.js +1 -3
  139. package/test/installation/plugins/tls.js +2 -4
  140. package/test/logger.js +135 -116
  141. package/test/outbound/hmail.js +49 -35
  142. package/test/outbound/index.js +118 -101
  143. package/test/outbound/qfile.js +51 -53
  144. package/test/outbound_bounce_net_errors.js +84 -69
  145. package/test/outbound_bounce_rfc3464.js +235 -165
  146. package/test/plugins/auth/auth_base.js +420 -279
  147. package/test/plugins/auth/auth_vpopmaild.js +38 -39
  148. package/test/plugins/queue/smtp_forward.js +126 -104
  149. package/test/plugins/rcpt_to.host_list_base.js +85 -67
  150. package/test/plugins/rcpt_to.in_host_list.js +159 -112
  151. package/test/plugins/status.js +71 -64
  152. package/test/plugins/tls.js +37 -34
  153. package/test/plugins.js +97 -92
  154. package/test/rfc1869.js +19 -26
  155. package/test/server.js +293 -272
  156. package/test/smtp_client.js +180 -176
  157. package/test/tls_socket.js +62 -66
  158. package/test/transaction.js +159 -160
  159. package/tls_socket.js +331 -333
  160. package/transaction.js +129 -137
package/test/server.js CHANGED
@@ -1,107 +1,115 @@
1
1
  const assert = require('node:assert')
2
- const path = require('node:path');
2
+ const path = require('node:path')
3
3
 
4
- const endpoint = require('../endpoint');
4
+ const endpoint = require('../endpoint')
5
5
  const message = require('haraka-email-message')
6
6
 
7
7
  const _set_up = (done) => {
8
- this.config = require('haraka-config');
9
- this.server = require('../server');
10
- done();
8
+ this.config = require('haraka-config')
9
+ this.server = require('../server')
10
+ done()
11
11
  }
12
12
 
13
13
  const _setupServer = (ip_port, done) => {
14
- process.env.YES_REALLY_DO_DISCARD=1; // for queue/discard plugin
15
- process.env.HARAKA_TEST_DIR=path.resolve('test');
14
+ process.env.YES_REALLY_DO_DISCARD = 1 // for queue/discard plugin
15
+ process.env.HARAKA_TEST_DIR = path.resolve('test')
16
16
 
17
17
  // test sets the default path for plugin instances to the test dir
18
- const test_cfg_path=path.resolve('test');
18
+ const test_cfg_path = path.resolve('test')
19
19
 
20
- this.server = require('../server');
21
- this.config = require('haraka-config').module_config(test_cfg_path);
22
- this.server.logger.loglevel = 6; // INFO
20
+ this.server = require('../server')
21
+ this.config = require('haraka-config').module_config(test_cfg_path)
22
+ this.server.logger.loglevel = 6 // INFO
23
23
 
24
24
  // set the default path for the plugin loader
25
- this.server.config = this.config.module_config(test_cfg_path);
26
- this.server.plugins.config = this.config.module_config(test_cfg_path);
25
+ this.server.config = this.config.module_config(test_cfg_path)
26
+ this.server.plugins.config = this.config.module_config(test_cfg_path)
27
27
  // this.server.outbound.config = this.config.module_config(this_cfg_path);
28
28
 
29
- this.server.load_smtp_ini();
30
- this.server.cfg.main.listen = ip_port;
31
- this.server.cfg.main.smtps_port = 2465;
29
+ this.server.load_smtp_ini()
30
+ this.server.cfg.main.listen = ip_port
31
+ this.server.cfg.main.smtps_port = 2465
32
32
 
33
33
  this.server.load_default_tls_config(() => {
34
- this.server.createServer({});
34
+ this.server.createServer({})
35
35
  setTimeout(() => {
36
- done();
37
- }, 200);
36
+ done()
37
+ }, 200)
38
38
  })
39
39
  }
40
40
 
41
41
  const _tearDownServer = (done) => {
42
- delete process.env.YES_REALLY_DO_DISCARD;
43
- delete process.env.HARAKA_TEST_DIR;
44
- this.server.stopListeners();
45
- this.server.plugins.registered_hooks = {};
42
+ delete process.env.YES_REALLY_DO_DISCARD
43
+ delete process.env.HARAKA_TEST_DIR
44
+ this.server.stopListeners()
45
+ this.server.plugins.registered_hooks = {}
46
46
  setTimeout(() => {
47
- done();
48
- }, 200);
47
+ done()
48
+ }, 200)
49
49
  }
50
50
 
51
51
  describe('server', () => {
52
-
53
52
  describe('get_listen_addrs', () => {
54
53
  beforeEach(_set_up)
55
54
 
56
55
  it('IPv4 fully qualified', () => {
57
- const listeners = this.server.get_listen_addrs({listen: '127.0.0.1:25'});
58
- assert.deepEqual(['127.0.0.1:25'], listeners);
56
+ const listeners = this.server.get_listen_addrs({
57
+ listen: '127.0.0.1:25',
58
+ })
59
+ assert.deepEqual(['127.0.0.1:25'], listeners)
59
60
  })
60
61
 
61
62
  it('IPv4, default port', () => {
62
- const listeners = this.server.get_listen_addrs({listen: '127.0.0.1'});
63
- assert.deepEqual(['127.0.0.1:25'], listeners);
63
+ const listeners = this.server.get_listen_addrs({
64
+ listen: '127.0.0.1',
65
+ })
66
+ assert.deepEqual(['127.0.0.1:25'], listeners)
64
67
  })
65
68
 
66
69
  it('IPv4, custom port', () => {
67
- const listeners = this.server.get_listen_addrs({ listen: '127.0.0.1'}, 250);
68
- assert.deepEqual(['127.0.0.1:250'], listeners);
70
+ const listeners = this.server.get_listen_addrs({ listen: '127.0.0.1' }, 250)
71
+ assert.deepEqual(['127.0.0.1:250'], listeners)
69
72
  })
70
73
 
71
74
  it('IPv6 fully qualified', () => {
72
- const listeners = this.server.get_listen_addrs({listen: '[::1]:25'});
73
- assert.deepEqual(['[::1]:25'], listeners);
75
+ const listeners = this.server.get_listen_addrs({
76
+ listen: '[::1]:25',
77
+ })
78
+ assert.deepEqual(['[::1]:25'], listeners)
74
79
  })
75
80
 
76
81
  it('IPv6, default port', () => {
77
- const listeners = this.server.get_listen_addrs({listen: '[::1]'});
78
- assert.deepEqual(['[::1]:25'], listeners);
82
+ const listeners = this.server.get_listen_addrs({ listen: '[::1]' })
83
+ assert.deepEqual(['[::1]:25'], listeners)
79
84
  })
80
85
 
81
86
  it('IPv6, custom port', () => {
82
- const listeners = this.server.get_listen_addrs({listen: '[::1]'}, 250);
83
- assert.deepEqual(['[::1]:250'], listeners);
87
+ const listeners = this.server.get_listen_addrs({ listen: '[::1]' }, 250)
88
+ assert.deepEqual(['[::1]:250'], listeners)
84
89
  })
85
90
 
86
91
  it('IPv4 & IPv6 fully qualified', () => {
87
92
  const listeners = this.server.get_listen_addrs({
88
- listen: '127.0.0.1:25,[::1]:25'
89
- });
90
- assert.deepEqual(['127.0.0.1:25','[::1]:25'], listeners);
93
+ listen: '127.0.0.1:25,[::1]:25',
94
+ })
95
+ assert.deepEqual(['127.0.0.1:25', '[::1]:25'], listeners)
91
96
  })
92
97
 
93
98
  it('IPv4 & IPv6, default port', () => {
94
99
  const listeners = this.server.get_listen_addrs({
95
- listen: '127.0.0.1:25,[::1]'
96
- });
97
- assert.deepEqual(['127.0.0.1:25','[::1]:25'], listeners);
100
+ listen: '127.0.0.1:25,[::1]',
101
+ })
102
+ assert.deepEqual(['127.0.0.1:25', '[::1]:25'], listeners)
98
103
  })
99
104
 
100
105
  it('IPv4 & IPv6, custom port', () => {
101
- const listeners = this.server.get_listen_addrs({
102
- listen: '127.0.0.1,[::1]'
103
- }, 250);
104
- assert.deepEqual(['127.0.0.1:250','[::1]:250'], listeners);
106
+ const listeners = this.server.get_listen_addrs(
107
+ {
108
+ listen: '127.0.0.1,[::1]',
109
+ },
110
+ 250,
111
+ )
112
+ assert.deepEqual(['127.0.0.1:250', '[::1]:250'], listeners)
105
113
  })
106
114
  })
107
115
 
@@ -109,60 +117,60 @@ describe('server', () => {
109
117
  beforeEach(_set_up)
110
118
 
111
119
  it('saves settings to Server.cfg', () => {
112
- this.server.load_smtp_ini();
120
+ this.server.load_smtp_ini()
113
121
  // console.log(this.server.cfg);
114
- const c = this.server.cfg.main;
115
- assert.notEqual(c.daemonize, undefined);
116
- assert.notEqual(c.daemon_log_file, undefined);
117
- assert.notEqual(c.daemon_pid_file, undefined);
122
+ const c = this.server.cfg.main
123
+ assert.notEqual(c.daemonize, undefined)
124
+ assert.notEqual(c.daemon_log_file, undefined)
125
+ assert.notEqual(c.daemon_pid_file, undefined)
118
126
  })
119
127
  })
120
128
 
121
129
  describe('get_smtp_server', () => {
122
130
  beforeEach((done) => {
123
- this.config = require('haraka-config');
124
- this.config = this.config.module_config(path.resolve('test'));
131
+ this.config = require('haraka-config')
132
+ this.config = this.config.module_config(path.resolve('test'))
125
133
 
126
- this.server = require('../server');
127
- this.server.config = this.config;
128
- this.server.plugins.config = this.config;
134
+ this.server = require('../server')
135
+ this.server.config = this.config
136
+ this.server.plugins.config = this.config
129
137
 
130
138
  this.server.load_default_tls_config(() => {
131
139
  setTimeout(() => {
132
- done();
133
- }, 200);
134
- });
140
+ done()
141
+ }, 200)
142
+ })
135
143
  })
136
144
 
137
145
  it('gets a net server object', (done) => {
138
- this.server.get_smtp_server(endpoint('0.0.0.0:2501'), 10).then(server => {
146
+ this.server.get_smtp_server(endpoint('0.0.0.0:2501'), 10).then((server) => {
139
147
  if (!server) {
140
- console.error('unable to bind to 0.0.0.0:2501');
148
+ console.error('unable to bind to 0.0.0.0:2501')
141
149
  if (process.env.CI) return // can't bind to IP/port (fails on Travis)
142
150
  }
143
- assert.ok(server);
144
- assert.equal(server.has_tls, false);
151
+ assert.ok(server)
152
+ assert.equal(server.has_tls, false)
145
153
  server.getConnections((err, count) => {
146
- assert.equal(0, count);
154
+ assert.equal(0, count)
147
155
  done()
148
156
  })
149
157
  })
150
158
  })
151
159
 
152
160
  it('gets a TLS net server object', (done) => {
153
- this.server.cfg.main.smtps_port = 2502;
161
+ this.server.cfg.main.smtps_port = 2502
154
162
  this.server.get_smtp_server(endpoint('0.0.0.0:2502'), 10).then((server) => {
155
163
  if (!server) {
156
- console.error('unable to bind to 0.0.0.0:2502');
164
+ console.error('unable to bind to 0.0.0.0:2502')
157
165
  if (process.env.CI) return // can't bind to IP/port (fails on Travis)
158
166
  }
159
- assert.ok(server);
160
- assert.equal(server.has_tls, true);
167
+ assert.ok(server)
168
+ assert.equal(server.has_tls, true)
161
169
  server.getConnections((err, count) => {
162
- assert.equal(0, count);
170
+ assert.equal(0, count)
163
171
  done()
164
- });
165
- });
172
+ })
173
+ })
166
174
  })
167
175
  })
168
176
 
@@ -170,7 +178,7 @@ describe('server', () => {
170
178
  beforeEach(_set_up)
171
179
 
172
180
  it('gets a fs path', () => {
173
- assert.ok(this.server.get_http_docroot());
181
+ assert.ok(this.server.get_http_docroot())
174
182
  })
175
183
  })
176
184
 
@@ -182,53 +190,52 @@ describe('server', () => {
182
190
  afterEach(_tearDownServer)
183
191
 
184
192
  it('accepts SMTP message', () => {
185
-
186
- const server = { notes: { } };
193
+ const server = { notes: {} }
187
194
  const cfg = {
188
195
  connect_timeout: 2,
189
196
  }
190
197
 
191
- const smtp_client = require('../smtp_client');
192
-
193
- smtp_client.get_client(server, (client) => {
194
-
195
- client
196
- .on('greeting', command => {
197
- client.send_command('HELO', 'haraka.local');
198
- })
199
- .on('helo', () => {
200
- client.send_command('MAIL', 'FROM:<test@haraka.local>');
201
- })
202
- .on('mail', () => {
203
- client.send_command('RCPT', 'TO:<nobody-will-see-this@haraka.local>');
204
- })
205
- .on('rcpt', () => {
206
- client.send_command('DATA');
207
- })
208
- .on('data', () => {
209
- const message_stream = new message.stream(
210
- { main : { spool_after : 1024 } }, "theMessageId"
211
- );
212
-
213
- message_stream.on('end', () => {
214
- client.socket.write('.\r\n');
198
+ const smtp_client = require('../smtp_client')
199
+
200
+ smtp_client.get_client(
201
+ server,
202
+ (client) => {
203
+ client
204
+ .on('greeting', (command) => {
205
+ client.send_command('HELO', 'haraka.local')
215
206
  })
216
- message_stream.add_line('Header: test\r\n');
217
- message_stream.add_line('\r\n');
218
- message_stream.add_line('I am body text\r\n');
219
- message_stream.add_line_end();
220
-
221
- client.start_data(message_stream);
222
- })
223
- .on('dot', () => {
224
- assert.ok(1);
225
- client.release();
226
- })
227
- .on('bad_code', (code, msg) => {
228
- client.release();
229
- });
230
-
231
- }, { port: 2500, host: 'localhost', cfg });
207
+ .on('helo', () => {
208
+ client.send_command('MAIL', 'FROM:<test@haraka.local>')
209
+ })
210
+ .on('mail', () => {
211
+ client.send_command('RCPT', 'TO:<nobody-will-see-this@haraka.local>')
212
+ })
213
+ .on('rcpt', () => {
214
+ client.send_command('DATA')
215
+ })
216
+ .on('data', () => {
217
+ const message_stream = new message.stream({ main: { spool_after: 1024 } }, 'theMessageId')
218
+
219
+ message_stream.on('end', () => {
220
+ client.socket.write('.\r\n')
221
+ })
222
+ message_stream.add_line('Header: test\r\n')
223
+ message_stream.add_line('\r\n')
224
+ message_stream.add_line('I am body text\r\n')
225
+ message_stream.add_line_end()
226
+
227
+ client.start_data(message_stream)
228
+ })
229
+ .on('dot', () => {
230
+ assert.ok(1)
231
+ client.release()
232
+ })
233
+ .on('bad_code', (code, msg) => {
234
+ client.release()
235
+ })
236
+ },
237
+ { port: 2500, host: 'localhost', cfg },
238
+ )
232
239
  })
233
240
  })
234
241
 
@@ -240,153 +247,158 @@ describe('server', () => {
240
247
  afterEach(_tearDownServer)
241
248
 
242
249
  it('accepts SMTP message', (done) => {
243
-
244
- const nodemailer = require('nodemailer');
250
+ const nodemailer = require('nodemailer')
245
251
  const transporter = nodemailer.createTransport({
246
252
  host: '127.0.0.1',
247
253
  port: 2503,
248
254
  tls: {
249
255
  // do not fail on invalid certs
250
- rejectUnauthorized: false
251
- }
252
- });
253
- transporter.sendMail({
254
- from: '"Testalicious Matt" <harakamail@gmail.com>',
255
- to: 'nobody-will-see-this@haraka.local',
256
- envelope: {
257
- from: 'Haraka Test <test@haraka.local>',
258
- to: 'Discard Queue <discard@haraka.local>',
256
+ rejectUnauthorized: false,
259
257
  },
260
- subject: 'Hello ✔',
261
- text: 'Hello world ?',
262
- html: '<b>Hello world ?</b>',
263
- },
264
- (error, info) => {
265
- if (error){
266
- console.log(error);
267
- return;
268
- }
269
- assert.deepEqual(info.accepted, [ 'discard@haraka.local' ]);
270
- console.log(`Message sent: ${info.response}`);
271
- done()
272
258
  })
259
+ transporter.sendMail(
260
+ {
261
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
262
+ to: 'nobody-will-see-this@haraka.local',
263
+ envelope: {
264
+ from: 'Haraka Test <test@haraka.local>',
265
+ to: 'Discard Queue <discard@haraka.local>',
266
+ },
267
+ subject: 'Hello ✔',
268
+ text: 'Hello world ?',
269
+ html: '<b>Hello world ?</b>',
270
+ },
271
+ (error, info) => {
272
+ if (error) {
273
+ console.log(error)
274
+ return
275
+ }
276
+ assert.deepEqual(info.accepted, ['discard@haraka.local'])
277
+ console.log(`Message sent: ${info.response}`)
278
+ done()
279
+ },
280
+ )
273
281
  })
274
282
 
275
283
  it('accepts authenticated SMTP', (done) => {
276
-
277
- const nodemailer = require('nodemailer');
284
+ const nodemailer = require('nodemailer')
278
285
  const transporter = nodemailer.createTransport({
279
286
  host: '127.0.0.1',
280
287
  port: 2503,
281
288
  auth: {
282
289
  user: 'matt',
283
- pass: 'goodPass'
290
+ pass: 'goodPass',
284
291
  },
285
292
  requireTLS: true,
286
293
  tls: {
287
294
  // do not fail on invalid certs
288
- rejectUnauthorized: false
289
- }
295
+ rejectUnauthorized: false,
296
+ },
290
297
  })
291
298
 
292
- transporter.sendMail({
293
- from: '"Testalicious Matt" <harakamail@gmail.com>',
294
- to: 'nobody-will-see-this@haraka.local',
295
- envelope: {
296
- from: 'Haraka Test <test@haraka.local>',
297
- to: 'Discard Queue <discard@haraka.local>',
299
+ transporter.sendMail(
300
+ {
301
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
302
+ to: 'nobody-will-see-this@haraka.local',
303
+ envelope: {
304
+ from: 'Haraka Test <test@haraka.local>',
305
+ to: 'Discard Queue <discard@haraka.local>',
306
+ },
307
+ subject: 'Hello ✔',
308
+ text: 'Hello world ?',
309
+ html: '<b>Hello world ?</b>',
298
310
  },
299
- subject: 'Hello ✔',
300
- text: 'Hello world ?',
301
- html: '<b>Hello world ?</b>',
302
- },
303
- (error, info) => {
304
- if (error){
305
- console.log(error);
306
- return;
307
- }
308
- assert.deepEqual(info.accepted, [ 'discard@haraka.local' ]);
309
- console.log(`Message sent: ${info.response}`);
310
- done()
311
- })
311
+ (error, info) => {
312
+ if (error) {
313
+ console.log(error)
314
+ return
315
+ }
316
+ assert.deepEqual(info.accepted, ['discard@haraka.local'])
317
+ console.log(`Message sent: ${info.response}`)
318
+ done()
319
+ },
320
+ )
312
321
  })
313
322
 
314
323
  it('rejects invalid auth', (done) => {
315
-
316
- const nodemailer = require('nodemailer');
324
+ const nodemailer = require('nodemailer')
317
325
  const transporter = nodemailer.createTransport({
318
326
  host: '127.0.0.1',
319
327
  port: 2503,
320
328
  auth: {
321
329
  user: 'matt',
322
- pass: 'badPass'
330
+ pass: 'badPass',
323
331
  },
324
332
  tls: {
325
333
  // do not fail on invalid certs
326
- rejectUnauthorized: false
327
- }
334
+ rejectUnauthorized: false,
335
+ },
328
336
  })
329
337
 
330
- transporter.sendMail({
331
- from: '"Testalicious Matt" <harakamail@gmail.com>',
332
- to: 'nobody-will-see-this@haraka.local',
333
- envelope: {
334
- from: 'Haraka Test <test@haraka.local>',
335
- to: 'Discard Queue <discard@haraka.local>',
338
+ transporter.sendMail(
339
+ {
340
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
341
+ to: 'nobody-will-see-this@haraka.local',
342
+ envelope: {
343
+ from: 'Haraka Test <test@haraka.local>',
344
+ to: 'Discard Queue <discard@haraka.local>',
345
+ },
346
+ subject: 'Hello ✔',
347
+ text: 'Hello world ?',
348
+ html: '<b>Hello world ?</b>',
336
349
  },
337
- subject: 'Hello ✔',
338
- text: 'Hello world ?',
339
- html: '<b>Hello world ?</b>',
340
- },
341
- (error, info) => {
342
- if (error){
343
- assert.equal(error.code, 'EAUTH');
344
- // console.log(error);
345
- return done();
346
- }
347
- console.log(info.response);
348
- done()
349
- })
350
+ (error, info) => {
351
+ if (error) {
352
+ assert.equal(error.code, 'EAUTH')
353
+ // console.log(error);
354
+ return done()
355
+ }
356
+ console.log(info.response)
357
+ done()
358
+ },
359
+ )
350
360
  })
351
361
 
352
362
  it('DKIM validates signed message', (done) => {
353
-
354
- const nodemailer = require('nodemailer');
363
+ const nodemailer = require('nodemailer')
355
364
  const transporter = nodemailer.createTransport({
356
365
  host: '127.0.0.1',
357
366
  port: 2503,
358
367
  tls: {
359
368
  // do not fail on invalid certs
360
- rejectUnauthorized: false
361
- }
369
+ rejectUnauthorized: false,
370
+ },
362
371
  })
363
372
 
364
- transporter.sendMail({
365
- from: '"Testalicious Matt" <harakamail@gmail.com>',
366
- to: 'nobody-will-see-this@haraka.local',
367
- envelope: {
368
- from: 'Haraka Test <test@haraka.local>',
369
- to: 'Discard Queue <discard@haraka.local>',
373
+ transporter.sendMail(
374
+ {
375
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
376
+ to: 'nobody-will-see-this@haraka.local',
377
+ envelope: {
378
+ from: 'Haraka Test <test@haraka.local>',
379
+ to: 'Discard Queue <discard@haraka.local>',
380
+ },
381
+ subject: 'Hello ✔',
382
+ text: 'Hello world ?',
383
+ html: '<b>Hello world ?</b>',
384
+ dkim: {
385
+ domainName: 'test.simerson.com',
386
+ keySelector: 'harakatest2017',
387
+ privateKey:
388
+ '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAxqoUAnQ9GB3iNnkS7coj0Iggd0nyryW062tpK95NC5UXmmAwIpUMfkYdiHY2o2duWYGF0Bp237M/QXKhJYTXfsgkwP/bq9OGWtRZxHPHhbhdjbiI\nqObi6zvYcxrI77gpWDDvruhMeS9Hwa1R99pLUWd4PsuYTzbV/jwu2pz+XZXXXNEU\nVxzDAAj0yF7mwxHMLzQfR+hdhWcrgN0stUP0o7hm7hoOP8IWgcSW3JiQYavIKoI4\nm4+I9I1LzDJN2rHVnQvmjUrqqpG7X6SyFVFtuTWGaMqf1Cj/t8eSvU9VdgLFllS8\ntThqUZHq5S5hm8M8VzLuQLG9U0dtFolcFmJkbQIDAQABAoIBAB4fUbNhjpXmihM6\nXm1htfZ7fXi45Kw76me7vJGjPklgTNjidsn3kZJf7UBwtC4ok6nMos6ABMA8fH3e\n9KIst0QI8tG0ucke5INHKWlJKNqUrtK7RTVe9M84HsStLgRzBwnRObZqkJXbXmT2\nc7RCDCOGrcvPsQNpzB6lX3FUVpk3x24RXpQV1qSgH8yuHSPc1C6rssXwPAgnESfS\nK3MHRx2CLZvTTkq/YCsT+wS/O9RWPCVOYuWaa5DDDAIp3Yw1wYq9Upoh0BdIFC3U\nWm+5Cr3o9wxcvS6+W2RA6I51eymzvCU5ZakWt/bnUDb6/ByxsWOn5rL4WfPpCwE4\nnuC72v0CgYEA9imEq6a0GoaEsMoR7cxT7uXKimQH+Jaq3CGkuh0iN32F4FXhuUKz\nLYKSLCZzpb1MiDJv6BBchV6uSQ6ATo1cZ8WzYQISikk175bf0SPom591OZElvKA2\nSOrTrXtbl33YbWZEgyEcpTgelVi5ys9rj4eKkMvM0lwRmW6gctEFXRcCgYEAzpqc\nR/wqPjgPhpF1CZtdEwOZg4kkOig8CBcuQ7o/hDG7N69A9ZbeJO8eD+gKDrHRfkYr\nTH/UdkZGjilBk/lxnpIZpyBLxQ6UdhNPuwtxXKAvuSN+aQ0pdJn8tg03OSj2OzTK\nJ4hMsO/wt1xM8EDRobLZEosMadaYZUHzx8VU5RsCgYEAvFZbuXEcT0cocpLIUOaK\nOTf7VRLfvmSYaUAcZoEv0sDpExDiWPodWO6To8/vn5lL2tCsKiOKhkhAlIjRxkgF\nsSfj7I7HXKJS7/LBX6RXrem8qMTS2JTDs9pnBk5hb3DLjDg4pxNIdWiQjbeKvw8f\nvnr3m30yQqhKlte7Tt15exUCgYBzq7RbyR6Nfy2SFdYE7usJPjawohOaS/RwQyov\n2RK+nGlJH+GqnjD5VLbsCOm4mG3F2NtdFSSKo4XVCdwhUMMAGKQsIbTKOwN7qAw3\nmIx7Y2PUr76SakAPfDc0ZenJItnZBBE6WOE3Ht8Siaa5zFCRy2QlMZxdlTv1VRt7\neUuyiQKBgQDdXJO5+3h1HPxbYZcmNm/2CJUNw2ehU8vCiBXCcWPn7JukayHx+TXy\nyj0j/b1SvmKgjB+4JWluiqIU+QBjRjvb397QY1YoCEaGZd0zdFjTZwQksQ5AFst9\nCiD9OFXe/kkmIUQQra6aw1CoppyAfvAblp8uevLWb57xU3VUB3xeGg==\n-----END RSA PRIVATE KEY-----\n',
389
+ },
370
390
  },
371
- subject: 'Hello ✔',
372
- text: 'Hello world ?',
373
- html: '<b>Hello world ?</b>',
374
- dkim: {
375
- domainName: "test.simerson.com",
376
- keySelector: "harakatest2017",
377
- privateKey: '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAxqoUAnQ9GB3iNnkS7coj0Iggd0nyryW062tpK95NC5UXmmAwIpUMfkYdiHY2o2duWYGF0Bp237M/QXKhJYTXfsgkwP/bq9OGWtRZxHPHhbhdjbiI\nqObi6zvYcxrI77gpWDDvruhMeS9Hwa1R99pLUWd4PsuYTzbV/jwu2pz+XZXXXNEU\nVxzDAAj0yF7mwxHMLzQfR+hdhWcrgN0stUP0o7hm7hoOP8IWgcSW3JiQYavIKoI4\nm4+I9I1LzDJN2rHVnQvmjUrqqpG7X6SyFVFtuTWGaMqf1Cj/t8eSvU9VdgLFllS8\ntThqUZHq5S5hm8M8VzLuQLG9U0dtFolcFmJkbQIDAQABAoIBAB4fUbNhjpXmihM6\nXm1htfZ7fXi45Kw76me7vJGjPklgTNjidsn3kZJf7UBwtC4ok6nMos6ABMA8fH3e\n9KIst0QI8tG0ucke5INHKWlJKNqUrtK7RTVe9M84HsStLgRzBwnRObZqkJXbXmT2\nc7RCDCOGrcvPsQNpzB6lX3FUVpk3x24RXpQV1qSgH8yuHSPc1C6rssXwPAgnESfS\nK3MHRx2CLZvTTkq/YCsT+wS/O9RWPCVOYuWaa5DDDAIp3Yw1wYq9Upoh0BdIFC3U\nWm+5Cr3o9wxcvS6+W2RA6I51eymzvCU5ZakWt/bnUDb6/ByxsWOn5rL4WfPpCwE4\nnuC72v0CgYEA9imEq6a0GoaEsMoR7cxT7uXKimQH+Jaq3CGkuh0iN32F4FXhuUKz\nLYKSLCZzpb1MiDJv6BBchV6uSQ6ATo1cZ8WzYQISikk175bf0SPom591OZElvKA2\nSOrTrXtbl33YbWZEgyEcpTgelVi5ys9rj4eKkMvM0lwRmW6gctEFXRcCgYEAzpqc\nR/wqPjgPhpF1CZtdEwOZg4kkOig8CBcuQ7o/hDG7N69A9ZbeJO8eD+gKDrHRfkYr\nTH/UdkZGjilBk/lxnpIZpyBLxQ6UdhNPuwtxXKAvuSN+aQ0pdJn8tg03OSj2OzTK\nJ4hMsO/wt1xM8EDRobLZEosMadaYZUHzx8VU5RsCgYEAvFZbuXEcT0cocpLIUOaK\nOTf7VRLfvmSYaUAcZoEv0sDpExDiWPodWO6To8/vn5lL2tCsKiOKhkhAlIjRxkgF\nsSfj7I7HXKJS7/LBX6RXrem8qMTS2JTDs9pnBk5hb3DLjDg4pxNIdWiQjbeKvw8f\nvnr3m30yQqhKlte7Tt15exUCgYBzq7RbyR6Nfy2SFdYE7usJPjawohOaS/RwQyov\n2RK+nGlJH+GqnjD5VLbsCOm4mG3F2NtdFSSKo4XVCdwhUMMAGKQsIbTKOwN7qAw3\nmIx7Y2PUr76SakAPfDc0ZenJItnZBBE6WOE3Ht8Siaa5zFCRy2QlMZxdlTv1VRt7\neUuyiQKBgQDdXJO5+3h1HPxbYZcmNm/2CJUNw2ehU8vCiBXCcWPn7JukayHx+TXy\nyj0j/b1SvmKgjB+4JWluiqIU+QBjRjvb397QY1YoCEaGZd0zdFjTZwQksQ5AFst9\nCiD9OFXe/kkmIUQQra6aw1CoppyAfvAblp8uevLWb57xU3VUB3xeGg==\n-----END RSA PRIVATE KEY-----\n',
378
- }
379
- },
380
- (error, info) => {
381
- // console.log(info);
382
- if (error){
383
- console.log(error);
384
- return;
385
- }
386
- assert.deepEqual(info.accepted, [ 'discard@haraka.local' ]);
387
- console.log(`Message sent: ${info.response}`);
388
- done()
389
- })
391
+ (error, info) => {
392
+ // console.log(info);
393
+ if (error) {
394
+ console.log(error)
395
+ return
396
+ }
397
+ assert.deepEqual(info.accepted, ['discard@haraka.local'])
398
+ console.log(`Message sent: ${info.response}`)
399
+ done()
400
+ },
401
+ )
390
402
  })
391
403
  })
392
404
 
@@ -398,47 +410,52 @@ describe('server', () => {
398
410
  afterEach(_tearDownServer)
399
411
 
400
412
  it('rejects non-validated SMTPS connection', (done) => {
401
-
402
- const nodemailer = require('nodemailer');
413
+ const nodemailer = require('nodemailer')
403
414
  const transporter = nodemailer.createTransport({
404
415
  host: '127.0.0.1',
405
416
  port: 2465,
406
417
  secure: true,
407
418
  tls: {
408
419
  // do not fail on invalid certs
409
- rejectUnauthorized: false
410
- }
420
+ rejectUnauthorized: false,
421
+ },
411
422
  })
412
423
 
413
424
  // give the SMTPS listener a second to start listening
414
425
  setTimeout(() => {
415
- transporter.sendMail({
416
- from: '"Testalicious Matt" <harakamail@gmail.com>',
417
- to: 'nobody-will-see-this@haraka.local',
418
- envelope: {
419
- from: 'Haraka Test <test@haraka.local>',
420
- to: 'Discard Queue <discard@haraka.local>',
426
+ transporter.sendMail(
427
+ {
428
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
429
+ to: 'nobody-will-see-this@haraka.local',
430
+ envelope: {
431
+ from: 'Haraka Test <test@haraka.local>',
432
+ to: 'Discard Queue <discard@haraka.local>',
433
+ },
434
+ subject: 'Hello ✔',
435
+ text: 'Hello world ?',
436
+ html: '<b>Hello world ?</b>',
421
437
  },
422
- subject: 'Hello ✔',
423
- text: 'Hello world ?',
424
- html: '<b>Hello world ?</b>',
425
- },
426
- (error, info) => {
427
- if (error) {
428
- // console.log(error);
429
- if (error.message === 'socket hang up') { // node 6 & 8
430
- assert.equal(error.message, 'socket hang up');
431
- }
432
- else if (/alert certificate required/.test(error.message)) { // node 18
433
- assert.ok(/alert certificate required/.test(error.message))
438
+ (error, info) => {
439
+ if (error) {
440
+ // console.log(error);
441
+ if (error.message === 'socket hang up') {
442
+ // node 6 & 8
443
+ assert.equal(error.message, 'socket hang up')
444
+ } else if (/alert certificate required/.test(error.message)) {
445
+ // node 18
446
+ assert.ok(/alert certificate required/.test(error.message))
447
+ } else {
448
+ // node 10+
449
+ assert.equal(
450
+ error.message,
451
+ 'Client network socket disconnected before secure TLS connection was established',
452
+ )
453
+ }
434
454
  }
435
- else { // node 10+
436
- assert.equal(error.message, 'Client network socket disconnected before secure TLS connection was established');
437
- }
438
- }
439
- done()
440
- })
441
- }, 500);
455
+ done()
456
+ },
457
+ )
458
+ }, 500)
442
459
  })
443
460
  })
444
461
 
@@ -448,44 +465,48 @@ describe('server', () => {
448
465
  })
449
466
 
450
467
  it('rejects non-validated STARTTLS connection', (done) => {
451
-
452
- const nodemailer = require('nodemailer');
468
+ const nodemailer = require('nodemailer')
453
469
  const transporter = nodemailer.createTransport({
454
470
  host: '127.0.0.1',
455
471
  port: 2587,
456
472
  secure: false,
457
473
  tls: {
458
474
  // do not fail on invalid certs
459
- rejectUnauthorized: false
460
- }
461
- });
475
+ rejectUnauthorized: false,
476
+ },
477
+ })
462
478
 
463
479
  // give the SMTPS listener a half second to start listening
464
480
  setTimeout(() => {
465
- transporter.sendMail({
466
- from: '"Testalicious Matt" <harakamail@gmail.com>',
467
- to: 'nobody-will-see-this@haraka.local',
468
- envelope: {
469
- from: 'Haraka Test <test@haraka.local>',
470
- to: 'Discard Queue <discard@haraka.local>',
481
+ transporter.sendMail(
482
+ {
483
+ from: '"Testalicious Matt" <harakamail@gmail.com>',
484
+ to: 'nobody-will-see-this@haraka.local',
485
+ envelope: {
486
+ from: 'Haraka Test <test@haraka.local>',
487
+ to: 'Discard Queue <discard@haraka.local>',
488
+ },
489
+ subject: 'Hello ✔',
490
+ text: 'Hello world ?',
491
+ html: '<b>Hello world ?</b>',
471
492
  },
472
- subject: 'Hello ✔',
473
- text: 'Hello world ?',
474
- html: '<b>Hello world ?</b>',
475
- },
476
- (error, info) => {
477
- if (error) {
478
- // console.log(error);
479
- if (/alert certificate required/.test(error.message)) { // node 18
480
- assert.ok(/alert certificate required/.test(error.message))
481
- }
482
- else {
483
- assert.equal(error.message, 'Client network socket disconnected before secure TLS connection was established');
493
+ (error, info) => {
494
+ if (error) {
495
+ // console.log(error);
496
+ if (/alert certificate required/.test(error.message)) {
497
+ // node 18
498
+ assert.ok(/alert certificate required/.test(error.message))
499
+ } else {
500
+ assert.equal(
501
+ error.message,
502
+ 'Client network socket disconnected before secure TLS connection was established',
503
+ )
504
+ }
484
505
  }
485
- }
486
- done()
487
- })
488
- }, 500);
506
+ done()
507
+ },
508
+ )
509
+ }, 500)
489
510
  })
490
511
  })
491
512
  })