Haraka 3.0.2 → 3.0.4

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 (267) hide show
  1. package/.eslintrc.yaml +5 -9
  2. package/.prettierrc.yml +1 -0
  3. package/CONTRIBUTORS.md +11 -0
  4. package/Changes.md +1393 -1211
  5. package/Dockerfile +3 -3
  6. package/Plugins.md +119 -106
  7. package/README.md +7 -16
  8. package/TODO +1 -24
  9. package/bin/haraka +197 -298
  10. package/config/auth_flat_file.ini +2 -0
  11. package/config/auth_vpopmaild.ini +4 -2
  12. package/config/dhparams.pem +8 -0
  13. package/config/mail_from.is_resolvable.ini +4 -2
  14. package/config/me +1 -0
  15. package/config/outbound.ini +0 -2
  16. package/config/plugins +36 -35
  17. package/config/rabbitmq_amqplib.ini +8 -1
  18. package/config/smtp.ini +0 -1
  19. package/config/smtp.json +17 -0
  20. package/config/tls_cert.pem +23 -0
  21. package/config/tls_key.pem +28 -0
  22. package/connection.js +46 -73
  23. package/contrib/bsd-rc.d/haraka +3 -1
  24. package/contrib/plugin2npm.sh +6 -36
  25. package/docs/Connection.md +1 -1
  26. package/docs/CoreConfig.md +2 -2
  27. package/docs/Logging.md +7 -21
  28. package/docs/Outbound.md +104 -210
  29. package/docs/Plugins.md +47 -40
  30. package/docs/Transaction.md +59 -82
  31. package/docs/{plugins → deprecated}/connect.rdns_access.md +1 -1
  32. package/docs/{plugins → deprecated}/mail_from.access.md +1 -1
  33. package/docs/{plugins → deprecated}/rcpt_to.access.md +1 -1
  34. package/docs/plugins/auth/auth_vpopmaild.md +15 -19
  35. package/docs/plugins/auth/flat_file.md +23 -30
  36. package/docs/plugins/queue/rabbitmq_amqplib.md +7 -0
  37. package/docs/plugins/queue/smtp_forward.md +1 -1
  38. package/docs/plugins/queue/smtp_proxy.md +5 -10
  39. package/docs/plugins/relay.md +2 -2
  40. package/docs/plugins/tls.md +29 -9
  41. package/endpoint.js +16 -13
  42. package/haraka.js +10 -14
  43. package/host_pool.js +5 -5
  44. package/line_socket.js +3 -4
  45. package/logger.js +44 -28
  46. package/outbound/client_pool.js +27 -23
  47. package/outbound/config.js +4 -6
  48. package/outbound/fsync_writestream.js +1 -1
  49. package/outbound/hmail.js +180 -220
  50. package/outbound/index.js +86 -99
  51. package/outbound/qfile.js +1 -1
  52. package/outbound/queue.js +55 -43
  53. package/outbound/timer_queue.js +3 -2
  54. package/outbound/tls.js +19 -7
  55. package/package.json +66 -55
  56. package/plugins/.eslintrc.yaml +0 -6
  57. package/plugins/auth/auth_base.js +30 -12
  58. package/plugins/auth/auth_proxy.js +14 -12
  59. package/plugins/auth/auth_vpopmaild.js +30 -20
  60. package/plugins/auth/flat_file.js +17 -12
  61. package/plugins/block_me.js +1 -1
  62. package/plugins/data.signatures.js +2 -4
  63. package/plugins/early_talker.js +2 -1
  64. package/plugins/mail_from.is_resolvable.js +65 -135
  65. package/plugins/queue/deliver.js +4 -5
  66. package/plugins/queue/lmtp.js +11 -14
  67. package/plugins/queue/qmail-queue.js +2 -2
  68. package/plugins/queue/quarantine.js +2 -2
  69. package/plugins/queue/rabbitmq.js +16 -17
  70. package/plugins/queue/rabbitmq_amqplib.js +1 -1
  71. package/plugins/queue/smtp_forward.js +6 -6
  72. package/plugins/queue/smtp_proxy.js +10 -1
  73. package/plugins/queue/test.js +2 -2
  74. package/plugins/rcpt_to.host_list_base.js +5 -5
  75. package/plugins/rcpt_to.in_host_list.js +2 -2
  76. package/plugins/relay.js +6 -7
  77. package/plugins/reseed_rng.js +1 -1
  78. package/plugins/status.js +37 -33
  79. package/plugins/tls.js +2 -2
  80. package/plugins/xclient.js +3 -2
  81. package/plugins.js +51 -54
  82. package/run_tests +3 -30
  83. package/server.js +190 -190
  84. package/smtp_client.js +30 -23
  85. package/{tests → test}/config/plugins +0 -2
  86. package/{tests → test}/config/smtp.ini +1 -1
  87. package/test/config/tls/example.com/_.example.com.key +28 -0
  88. package/test/config/tls/example.com/example.com.crt +25 -0
  89. package/test/connection.js +302 -0
  90. package/test/endpoint.js +94 -0
  91. package/{tests → test}/fixtures/line_socket.js +1 -1
  92. package/{tests → test}/fixtures/util_hmailitem.js +19 -25
  93. package/{tests → test}/host_pool.js +42 -57
  94. package/test/logger.js +258 -0
  95. package/test/outbound/hmail.js +141 -0
  96. package/test/outbound/index.js +220 -0
  97. package/test/outbound/qfile.js +126 -0
  98. package/test/outbound_bounce_net_errors.js +142 -0
  99. package/{tests → test}/outbound_bounce_rfc3464.js +110 -122
  100. package/test/plugins/auth/auth_base.js +484 -0
  101. package/test/plugins/auth/auth_vpopmaild.js +83 -0
  102. package/test/plugins/early_talker.js +104 -0
  103. package/test/plugins/mail_from.is_resolvable.js +35 -0
  104. package/test/plugins/queue/smtp_forward.js +206 -0
  105. package/test/plugins/rcpt_to.host_list_base.js +122 -0
  106. package/test/plugins/rcpt_to.in_host_list.js +193 -0
  107. package/test/plugins/relay.js +303 -0
  108. package/test/plugins/status.js +130 -0
  109. package/test/plugins/tls.js +70 -0
  110. package/test/plugins.js +228 -0
  111. package/{tests → test}/queue/multibyte +0 -0
  112. package/{tests → test}/queue/plain +0 -0
  113. package/test/rfc1869.js +73 -0
  114. package/test/server.js +491 -0
  115. package/test/smtp_client.js +299 -0
  116. package/test/tls_socket.js +273 -0
  117. package/test/transaction.js +270 -0
  118. package/tls_socket.js +202 -252
  119. package/transaction.js +9 -24
  120. package/CONTRIBUTING.md +0 -1
  121. package/bin/dkimverify +0 -40
  122. package/config/access.domains +0 -13
  123. package/config/attachment.ctype.regex +0 -2
  124. package/config/attachment.filename.regex +0 -1
  125. package/config/avg.ini +0 -5
  126. package/config/bounce.ini +0 -15
  127. package/config/data.headers.ini +0 -61
  128. package/config/dkim/dkim_key_gen.sh +0 -78
  129. package/config/dkim_sign.ini +0 -4
  130. package/config/dkim_verify.ini +0 -7
  131. package/config/dnsbl.ini +0 -23
  132. package/config/greylist.ini +0 -43
  133. package/config/helo.checks.ini +0 -52
  134. package/config/lookup_rdns.strict.ini +0 -12
  135. package/config/lookup_rdns.strict.timeout +0 -1
  136. package/config/lookup_rdns.strict.whitelist +0 -1
  137. package/config/lookup_rdns.strict.whitelist_regex +0 -5
  138. package/config/messagesniffer.ini +0 -18
  139. package/config/rcpt_to.blocklist +0 -1
  140. package/config/rdns.allow_regexps +0 -0
  141. package/config/rdns.deny_regexps +0 -0
  142. package/config/spamassassin.ini +0 -56
  143. package/config.js +0 -6
  144. package/dkim.js +0 -614
  145. package/docs/plugins/avg.md +0 -35
  146. package/docs/plugins/bounce.md +0 -69
  147. package/docs/plugins/clamd.md +0 -147
  148. package/docs/plugins/esets.md +0 -8
  149. package/docs/plugins/greylist.md +0 -90
  150. package/docs/plugins/helo.checks.md +0 -135
  151. package/docs/plugins/messagesniffer.md +0 -163
  152. package/docs/plugins/relay_acl.md +0 -29
  153. package/docs/plugins/relay_all.md +0 -15
  154. package/docs/plugins/relay_force_routing.md +0 -33
  155. package/docs/plugins/spamassassin.md +0 -180
  156. package/outbound/mx_lookup.js +0 -70
  157. package/plugins/auth/auth_ldap.js +0 -3
  158. package/plugins/avg.js +0 -162
  159. package/plugins/backscatterer.js +0 -25
  160. package/plugins/bounce.js +0 -381
  161. package/plugins/clamd.js +0 -381
  162. package/plugins/data.headers.js +0 -4
  163. package/plugins/data.uribl.js +0 -4
  164. package/plugins/dkim_sign.js +0 -395
  165. package/plugins/dkim_verify.js +0 -62
  166. package/plugins/dns_list_base.js +0 -221
  167. package/plugins/dnsbl.js +0 -146
  168. package/plugins/dnswl.js +0 -58
  169. package/plugins/esets.js +0 -71
  170. package/plugins/graph.js +0 -5
  171. package/plugins/greylist.js +0 -645
  172. package/plugins/helo.checks.js +0 -533
  173. package/plugins/messagesniffer.js +0 -381
  174. package/plugins/rcpt_to.ldap.js +0 -3
  175. package/plugins/rcpt_to.max_count.js +0 -24
  176. package/plugins/relay_all.js +0 -13
  177. package/plugins/spamassassin.js +0 -384
  178. package/tests/config/dkim/example.com/dns +0 -29
  179. package/tests/config/dkim/example.com/private +0 -6
  180. package/tests/config/dkim/example.com/public +0 -4
  181. package/tests/config/dkim/example.com/selector +0 -1
  182. package/tests/config/dkim.private.key +0 -6
  183. package/tests/config/dkim_sign.ini +0 -4
  184. package/tests/config/helo.checks.ini +0 -52
  185. package/tests/connection.js +0 -327
  186. package/tests/endpoint.js +0 -128
  187. package/tests/fixtures/vm_harness.js +0 -59
  188. package/tests/logger.js +0 -327
  189. package/tests/outbound/hmail.js +0 -112
  190. package/tests/outbound/index.js +0 -324
  191. package/tests/outbound/qfile.js +0 -67
  192. package/tests/outbound_bounce_net_errors.js +0 -173
  193. package/tests/plugins/auth/auth_base.js +0 -463
  194. package/tests/plugins/auth/auth_vpopmaild.js +0 -91
  195. package/tests/plugins/bounce.js +0 -307
  196. package/tests/plugins/clamd.js +0 -224
  197. package/tests/plugins/deprecated/relay_acl.js +0 -140
  198. package/tests/plugins/deprecated/relay_all.js +0 -59
  199. package/tests/plugins/dkim_sign.js +0 -315
  200. package/tests/plugins/dkim_signer.js +0 -108
  201. package/tests/plugins/dns_list_base.js +0 -259
  202. package/tests/plugins/dnsbl.js +0 -101
  203. package/tests/plugins/early_talker.js +0 -115
  204. package/tests/plugins/greylist.js +0 -58
  205. package/tests/plugins/helo.checks.js +0 -525
  206. package/tests/plugins/mail_from.is_resolvable.js +0 -116
  207. package/tests/plugins/queue/smtp_forward.js +0 -221
  208. package/tests/plugins/rcpt_to.host_list_base.js +0 -132
  209. package/tests/plugins/rcpt_to.in_host_list.js +0 -218
  210. package/tests/plugins/relay.js +0 -339
  211. package/tests/plugins/spamassassin.js +0 -171
  212. package/tests/plugins/status.js +0 -138
  213. package/tests/plugins/tls.js +0 -84
  214. package/tests/plugins.js +0 -247
  215. package/tests/rfc1869.js +0 -61
  216. package/tests/server.js +0 -510
  217. package/tests/smtp_client/auth.js +0 -105
  218. package/tests/smtp_client/basic.js +0 -101
  219. package/tests/smtp_client.js +0 -80
  220. package/tests/tls_socket.js +0 -333
  221. package/tests/transaction.js +0 -284
  222. /package/docs/{plugins → deprecated}/dkim_sign.md +0 -0
  223. /package/docs/{plugins → deprecated}/dkim_verify.md +0 -0
  224. /package/docs/{plugins → deprecated}/dnsbl.md +0 -0
  225. /package/docs/{plugins → deprecated}/dnswl.md +0 -0
  226. /package/docs/{plugins → deprecated}/rcpt_to.routes.md +0 -0
  227. /package/{tests → test}/.eslintrc.yaml +0 -0
  228. /package/{tests → test}/config/auth_flat_file.ini +0 -0
  229. /package/{tests → test}/config/dhparams.pem +0 -0
  230. /package/{tests → test}/config/host_list +0 -0
  231. /package/{tests → test}/config/outbound_tls_cert.pem +0 -0
  232. /package/{tests → test}/config/outbound_tls_key.pem +0 -0
  233. /package/{tests → test}/config/smtp_forward.ini +0 -0
  234. /package/{tests → test}/config/tls/ec.pem +0 -0
  235. /package/{tests → test}/config/tls/haraka.local.pem +0 -0
  236. /package/{tests → test}/config/tls/mismatched.pem +0 -0
  237. /package/{tests → test}/config/tls.ini +0 -0
  238. /package/{tests → test}/config/tls_cert.pem +0 -0
  239. /package/{tests → test}/config/tls_key.pem +0 -0
  240. /package/{tests → test}/fixtures/todo_qfile.txt +0 -0
  241. /package/{tests → test}/installation/config/test-plugin-flat +0 -0
  242. /package/{tests → test}/installation/config/test-plugin.ini +0 -0
  243. /package/{tests → test}/installation/config/tls.ini +0 -0
  244. /package/{tests → test}/installation/node_modules/load_first/index.js +0 -0
  245. /package/{tests → test}/installation/node_modules/load_first/package.json +0 -0
  246. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin-flat +0 -0
  247. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin.ini +0 -0
  248. /package/{tests → test}/installation/node_modules/test-plugin/package.json +0 -0
  249. /package/{tests → test}/installation/node_modules/test-plugin/test-plugin.js +0 -0
  250. /package/{tests → test}/installation/plugins/base_plugin.js +0 -0
  251. /package/{tests → test}/installation/plugins/folder_plugin/index.js +0 -0
  252. /package/{tests → test}/installation/plugins/folder_plugin/package.json +0 -0
  253. /package/{tests → test}/installation/plugins/inherits.js +0 -0
  254. /package/{tests → test}/installation/plugins/load_first.js +0 -0
  255. /package/{tests → test}/installation/plugins/plugin.js +0 -0
  256. /package/{tests → test}/installation/plugins/tls.js +0 -0
  257. /package/{tests → test}/loud/config/dhparams.pem +0 -0
  258. /package/{tests → test}/loud/config/tls/goobered.pem +0 -0
  259. /package/{tests → test}/loud/config/tls.ini +0 -0
  260. /package/{tests → test}/mail_specimen/base64-root-part.txt +0 -0
  261. /package/{tests → test}/mail_specimen/varied-fold-lengths-preserve-data.txt +0 -0
  262. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
  263. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
  264. /package/{tests → test}/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
  265. /package/{tests → test}/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
  266. /package/{tests → test}/queue/zero-length +0 -0
  267. /package/{tests → test}/test-queue/delete-me +0 -0
@@ -0,0 +1,270 @@
1
+ const assert = require('node:assert')
2
+ const fs = require('node:fs');
3
+ const path = require('node:path');
4
+
5
+ const config = require('haraka-config')
6
+ const transaction = require('../transaction');
7
+
8
+ const _set_up = (done) => {
9
+ this.transaction = transaction.createTransaction(undefined, config.get('smtp.ini'));
10
+ done()
11
+ }
12
+
13
+ describe('transaction', () => {
14
+ beforeEach(_set_up)
15
+
16
+ it('add_body_filter', (done) => {
17
+
18
+ this.transaction.add_body_filter('text/plain', (ct, enc, buf) => {
19
+ // The functionality of these filter functions is tested in
20
+ // haraka-email-message. This just assures the plumbing is in place.
21
+
22
+ assert.ok(ct.indexOf('text/plain') === 0, "correct body part");
23
+ assert.ok(/utf-?8/i.test(enc), "correct encoding");
24
+ assert.equal(buf.toString().trim(), "Text part", "correct body contents");
25
+ });
26
+
27
+ [
28
+ "Content-Type: multipart/alternative; boundary=abcd\n",
29
+ "\n",
30
+ "--abcd\n",
31
+ "Content-Type: text/plain\n",
32
+ "\n",
33
+ "Text part\n",
34
+ "--abcd\n",
35
+ "Content-Type: text/html\n",
36
+ "\n",
37
+ "<p>HTML part</p>\n",
38
+ "--abcd--\n",
39
+ ].forEach(line => {
40
+ this.transaction.add_data(line);
41
+ });
42
+ this.transaction.end_data(() => {
43
+ done();
44
+ });
45
+ })
46
+
47
+ it('regression: attachment_hooks before set_banner/add_body_filter', (done) => {
48
+
49
+ this.transaction.attachment_hooks(() => {});
50
+ this.transaction.set_banner('banner');
51
+ this.transaction.add_body_filter('', () => {
52
+ assert.ok(true, "body filter called");
53
+ });
54
+ [
55
+ "Content-Type: text/plain\n",
56
+ "\n",
57
+ "Some text\n",
58
+ ].forEach(line => {
59
+ this.transaction.add_data(line);
60
+ });
61
+
62
+ this.transaction.end_data(() => {
63
+ this.transaction.message_stream.get_data(body => {
64
+ assert.ok(/banner$/.test(body.toString().trim()), "banner applied");
65
+ done();
66
+ })
67
+ })
68
+ })
69
+
70
+ it('correct output encoding when content in non-utf8 #2176', (done) => {
71
+
72
+ // Czech panagram "Příliš žluťoučký kůň úpěl ďábelské ódy." in ISO-8859-2 encoding
73
+ const message = [0x50, 0xF8, 0xED, 0x6C, 0x69, 0xB9, 0x20, 0xBE, 0x6C, 0x75, 0xBB, 0x6F, 0x76, 0xE8, 0x6B, 0xFD, 0x20, 0x6B, 0xF9, 0xF2, 0xFA, 0xEC, 0x6C, 0x20, 0xEF, 0xE2, 0x62, 0x65, 0x6C, 0x73, 0x6b, 0xE9, 0x20, 0xF3, 0x64, 0x79, 0x2E];
74
+ const payload = [
75
+ Buffer.from("Content-Type: text/plain; charset=iso-8859-2; format=flowed\n"),
76
+ "\n",
77
+ Buffer.from([...message, 0x0A]), // Add \n
78
+ ];
79
+
80
+
81
+ this.transaction.parse_body = true;
82
+ this.transaction.attachment_hooks(function () {});
83
+
84
+ for (const line of payload) {
85
+ this.transaction.add_data(line);
86
+ }
87
+ this.transaction.end_data(() => {
88
+ this.transaction.message_stream.get_data(function (body) {
89
+ assert.ok(body.includes(Buffer.from(message)), "message not damaged");
90
+ done();
91
+ });
92
+ });
93
+ })
94
+
95
+ it('no munging of bytes if not parsing body', (done) => {
96
+
97
+ // Czech panagram "Příliš žluťoučký kůň úpěl ďábelské ódy.\n" in ISO-8859-2 encoding
98
+ const message = Buffer.from([0x50, 0xF8, 0xED, 0x6C, 0x69, 0xB9, 0x20, 0xBE, 0x6C, 0x75, 0xBB, 0x6F, 0x76, 0xE8, 0x6B, 0xFD, 0x20, 0x6B, 0xF9, 0xF2, 0xFA, 0xEC, 0x6C, 0x20, 0xEF, 0xE2, 0x62, 0x65, 0x6C, 0x73, 0x6b, 0xE9, 0x20, 0xF3, 0x64, 0x79, 0x2E, 0x0A]);
99
+ const payload = [
100
+ "Content-Type: text/plain; charset=iso-8859-2; format=flowed\n",
101
+ "\n",
102
+ message
103
+ ];
104
+
105
+ payload.forEach(line => {
106
+ this.transaction.add_data(line);
107
+ });
108
+ this.transaction.end_data(() => {
109
+ this.transaction.message_stream.get_data(body => {
110
+ assert.ok(body.includes(message), "message not damaged");
111
+ done();
112
+ });
113
+ });
114
+ })
115
+
116
+ it('bannering with nested mime structure', (done) => {
117
+
118
+ this.transaction.set_banner('TEXT_BANNER', 'HTML_BANNER');
119
+ [
120
+ 'Content-Type: multipart/mixed; boundary="TOP_LEVEL"',
121
+ '',
122
+ '--TOP_LEVEL',
123
+ 'Content-Type: multipart/alternative; boundary="INNER_LEVEL"',
124
+ '',
125
+ '--INNER_LEVEL',
126
+ 'Content-Type: text/plain; charset=us-ascii',
127
+ '',
128
+ 'Hello, this is a text part',
129
+ '--INNER_LEVEL',
130
+ 'Content-Type: text/html; charset=us-ascii',
131
+ '',
132
+ '<p>This is an html part</p>',
133
+ '--INNER_LEVEL--',
134
+ '--TOP_LEVEL--',
135
+ ].forEach(line => {
136
+ this.transaction.add_data(`${line}\r\n`);
137
+ });
138
+ this.transaction.end_data(() => {
139
+ this.transaction.message_stream.get_data(body => {
140
+ assert.ok(/Hello, this is a text part/.test(body.toString()),
141
+ "text content comes through in final message");
142
+ assert.ok(/This is an html part/.test(body.toString()),
143
+ "html content comes through in final message");
144
+ assert.ok(/TEXT_BANNER/.test(body.toString()),
145
+ "text banner comes through in final message");
146
+ assert.ok(/HTML_BANNER/.test(body.toString()),
147
+ "html banner comes through in final message");
148
+ done();
149
+ });
150
+ });
151
+ })
152
+
153
+ describe('base64_handling', () => {
154
+ beforeEach(_set_up)
155
+
156
+ it('varied-base64-fold-lengths-preserve-data', (done) => {
157
+
158
+ const parsed_attachments = {};
159
+ this.transaction.parse_body = true;
160
+ //accumulate attachment buffers.
161
+ this.transaction.attachment_hooks((ct, filename, body, stream) => {
162
+ let attachment = Buffer.alloc(0);
163
+ stream.on('data', data => {
164
+ attachment = Buffer.concat([attachment, data]);
165
+ });
166
+ stream.on('end', () => {
167
+ parsed_attachments[filename] = attachment;
168
+ });
169
+ });
170
+
171
+ const specimen_path = path.join(__dirname, 'mail_specimen', 'varied-fold-lengths-preserve-data.txt');
172
+ write_file_data_to_transaction(this.transaction, specimen_path);
173
+
174
+ assert.equal(this.transaction.body.children.length, 6);
175
+
176
+ let first_attachment = null;
177
+ for (const i in parsed_attachments) {
178
+ const current_attachment = parsed_attachments[i];
179
+ first_attachment = first_attachment || current_attachment;
180
+ // All buffers from data that was encoded with varied line lengths should
181
+ // still have the same final data.
182
+ assert.equal(true, first_attachment.equals(current_attachment),
183
+ `The buffer data for '${i}' doesn't appear to be equal to the other attachments, and is likely corrupted.`);
184
+ }
185
+ done();
186
+ })
187
+
188
+ it('base64-root-html-decodes-correct-number-of-bytes', (done) => {
189
+
190
+ this.transaction.parse_body = true;
191
+ const specimen_path = path.join(__dirname, 'mail_specimen', 'base64-root-part.txt');
192
+ write_file_data_to_transaction(this.transaction, specimen_path);
193
+
194
+ assert.equal(this.transaction.body.bodytext.length, 425);
195
+ done();
196
+ })
197
+ })
198
+
199
+ // Test is to ensure boundary marker just after the headers, is in-tact
200
+ // Issue: "User1990" <--abcd
201
+ // Expected: --abcd
202
+ describe('boundarymarkercorrupt_test', () => {
203
+ beforeEach(_set_up)
204
+
205
+ // populate the same email data in transaction (self.transaction.add_data()) and
206
+ // in raw buffer, then compare
207
+ it('fix mime boundary corruption issue', (done) => {
208
+ const self = this;
209
+ let buffer = '';
210
+ self.transaction.add_data("Content-Type: multipart/alternative; boundary=abcd\r\n");
211
+ buffer += "Content-Type: multipart/alternative; boundary=abcd\r\n";
212
+ self.transaction.add_data('To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n');
213
+ buffer += 'To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n';
214
+ // make sure we add headers so that it exceeds 64k bytes to expose this issue
215
+ for (let i=0;i<725;i++){
216
+ self.transaction.add_data(` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`);
217
+ buffer += ` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`
218
+ }
219
+ self.transaction.add_data(' "Final User_firstname_middlename_lastname" <final_user_firstname_middlename_lastname@test.com>\r\n');
220
+ buffer += ' "Final User_firstname_middlename_lastname" <final_user_firstname_middlename_lastname@test.com>\r\n';
221
+ self.transaction.add_data('Message-ID: <Boundary_Marker_Test>\r\n');
222
+ buffer += 'Message-ID: <Boundary_Marker_Test>\r\n';
223
+ self.transaction.add_data('MIME-Version: 1.0\r\n');
224
+ buffer += 'MIME-Version: 1.0\r\n';
225
+ self.transaction.add_data('Date: Wed, 1 Jun 2022 16:44:39 +0530 (IST)\r\n');
226
+ buffer += 'Date: Wed, 1 Jun 2022 16:44:39 +0530 (IST)\r\n';
227
+ self.transaction.add_data('\r\n');
228
+ buffer += '\r\n';
229
+ self.transaction.add_data("--abcd\r\n");
230
+ buffer += "--abcd\r\n";
231
+
232
+ [
233
+ "Content-Type: text/plain\r\n",
234
+ "\r\n",
235
+ "Text part\r\n",
236
+ "--abcd\r\n",
237
+ "Content-Type: text/html\r\n",
238
+ "\r\n",
239
+ "<p>HTML part</p>\r\n",
240
+ "--abcd--\r\n",
241
+ ].forEach(line => {
242
+ self.transaction.add_data(line);
243
+ buffer += line;
244
+ });
245
+
246
+ this.transaction.end_data(function () {
247
+ self.transaction.message_stream.get_data(function (body) {
248
+ assert.ok(body.includes(buffer), "message is damaged");
249
+ done();
250
+ })
251
+ })
252
+ })
253
+ })
254
+ })
255
+
256
+ function write_file_data_to_transaction (test_transaction, filename) {
257
+ const specimen = fs.readFileSync(filename, 'utf8');
258
+ const matcher = /[^\n]*([\n]|$)/g;
259
+
260
+ let line;
261
+ do {
262
+ line = matcher.exec(specimen);
263
+ if (line[0] == '') {
264
+ break;
265
+ }
266
+ test_transaction.add_data(line[0]);
267
+ } while (line[0] != '');
268
+
269
+ test_transaction.end_data();
270
+ }