Haraka 3.1.0 → 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 +69 -50
  4. package/Plugins.md +3 -1
  5. package/README.md +1 -1
  6. package/bin/haraka +475 -478
  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 +34 -27
  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 +38 -33
  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
@@ -1,12 +1,12 @@
1
1
  const assert = require('node:assert')
2
- const fs = require('node:fs');
3
- const path = require('node:path');
2
+ const fs = require('node:fs')
3
+ const path = require('node:path')
4
4
 
5
5
  const config = require('haraka-config')
6
- const transaction = require('../transaction');
6
+ const transaction = require('../transaction')
7
7
 
8
8
  const _set_up = (done) => {
9
- this.transaction = transaction.createTransaction(undefined, config.get('smtp.ini'));
9
+ this.transaction = transaction.createTransaction(undefined, config.get('smtp.ini'))
10
10
  done()
11
11
  }
12
12
 
@@ -14,109 +14,102 @@ describe('transaction', () => {
14
14
  beforeEach(_set_up)
15
15
 
16
16
  it('add_body_filter', (done) => {
17
-
18
17
  this.transaction.add_body_filter('text/plain', (ct, enc, buf) => {
19
18
  // The functionality of these filter functions is tested in
20
19
  // haraka-email-message. This just assures the plumbing is in place.
21
20
 
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
- });
21
+ assert.ok(ct.indexOf('text/plain') === 0, 'correct body part')
22
+ assert.ok(/utf-?8/i.test(enc), 'correct encoding')
23
+ assert.equal(buf.toString().trim(), 'Text part', 'correct body contents')
24
+ })
25
+ ;[
26
+ 'Content-Type: multipart/alternative; boundary=abcd\n',
27
+ '\n',
28
+ '--abcd\n',
29
+ 'Content-Type: text/plain\n',
30
+ '\n',
31
+ 'Text part\n',
32
+ '--abcd\n',
33
+ 'Content-Type: text/html\n',
34
+ '\n',
35
+ '<p>HTML part</p>\n',
36
+ '--abcd--\n',
37
+ ].forEach((line) => {
38
+ this.transaction.add_data(line)
39
+ })
42
40
  this.transaction.end_data(() => {
43
- done();
44
- });
41
+ done()
42
+ })
45
43
  })
46
44
 
47
45
  it('regression: attachment_hooks before set_banner/add_body_filter', (done) => {
48
-
49
- this.transaction.attachment_hooks(() => {});
50
- this.transaction.set_banner('banner');
46
+ this.transaction.attachment_hooks(() => {})
47
+ this.transaction.set_banner('banner')
51
48
  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
- });
49
+ assert.ok(true, 'body filter called')
50
+ })
51
+ ;['Content-Type: text/plain\n', '\n', 'Some text\n'].forEach((line) => {
52
+ this.transaction.add_data(line)
53
+ })
61
54
 
62
55
  this.transaction.end_data(() => {
63
- this.transaction.message_stream.get_data(body => {
64
- assert.ok(/banner$/.test(body.toString().trim()), "banner applied");
65
- done();
56
+ this.transaction.message_stream.get_data((body) => {
57
+ assert.ok(/banner$/.test(body.toString().trim()), 'banner applied')
58
+ done()
66
59
  })
67
60
  })
68
61
  })
69
62
 
70
63
  it('correct output encoding when content in non-utf8 #2176', (done) => {
71
-
72
64
  // 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];
65
+ const message = [
66
+ 0x50, 0xf8, 0xed, 0x6c, 0x69, 0xb9, 0x20, 0xbe, 0x6c, 0x75, 0xbb, 0x6f, 0x76, 0xe8, 0x6b, 0xfd, 0x20, 0x6b,
67
+ 0xf9, 0xf2, 0xfa, 0xec, 0x6c, 0x20, 0xef, 0xe2, 0x62, 0x65, 0x6c, 0x73, 0x6b, 0xe9, 0x20, 0xf3, 0x64, 0x79,
68
+ 0x2e,
69
+ ]
74
70
  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
-
71
+ Buffer.from('Content-Type: text/plain; charset=iso-8859-2; format=flowed\n'),
72
+ '\n',
73
+ Buffer.from([...message, 0x0a]), // Add \n
74
+ ]
80
75
 
81
- this.transaction.parse_body = true;
82
- this.transaction.attachment_hooks(function () {});
76
+ this.transaction.parse_body = true
77
+ this.transaction.attachment_hooks(function () {})
83
78
 
84
79
  for (const line of payload) {
85
- this.transaction.add_data(line);
80
+ this.transaction.add_data(line)
86
81
  }
87
82
  this.transaction.end_data(() => {
88
83
  this.transaction.message_stream.get_data(function (body) {
89
- assert.ok(body.includes(Buffer.from(message)), "message not damaged");
90
- done();
91
- });
92
- });
84
+ assert.ok(body.includes(Buffer.from(message)), 'message not damaged')
85
+ done()
86
+ })
87
+ })
93
88
  })
94
89
 
95
90
  it('no munging of bytes if not parsing body', (done) => {
96
-
97
91
  // 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
- });
92
+ const message = Buffer.from([
93
+ 0x50, 0xf8, 0xed, 0x6c, 0x69, 0xb9, 0x20, 0xbe, 0x6c, 0x75, 0xbb, 0x6f, 0x76, 0xe8, 0x6b, 0xfd, 0x20, 0x6b,
94
+ 0xf9, 0xf2, 0xfa, 0xec, 0x6c, 0x20, 0xef, 0xe2, 0x62, 0x65, 0x6c, 0x73, 0x6b, 0xe9, 0x20, 0xf3, 0x64, 0x79,
95
+ 0x2e, 0x0a,
96
+ ])
97
+ const payload = ['Content-Type: text/plain; charset=iso-8859-2; format=flowed\n', '\n', message]
98
+
99
+ payload.forEach((line) => {
100
+ this.transaction.add_data(line)
101
+ })
108
102
  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
- });
103
+ this.transaction.message_stream.get_data((body) => {
104
+ assert.ok(body.includes(message), 'message not damaged')
105
+ done()
106
+ })
107
+ })
114
108
  })
115
109
 
116
110
  it('bannering with nested mime structure', (done) => {
117
-
118
- this.transaction.set_banner('TEXT_BANNER', 'HTML_BANNER');
119
- [
111
+ this.transaction.set_banner('TEXT_BANNER', 'HTML_BANNER')
112
+ ;[
120
113
  'Content-Type: multipart/mixed; boundary="TOP_LEVEL"',
121
114
  '',
122
115
  '--TOP_LEVEL',
@@ -132,67 +125,67 @@ describe('transaction', () => {
132
125
  '<p>This is an html part</p>',
133
126
  '--INNER_LEVEL--',
134
127
  '--TOP_LEVEL--',
135
- ].forEach(line => {
136
- this.transaction.add_data(`${line}\r\n`);
137
- });
128
+ ].forEach((line) => {
129
+ this.transaction.add_data(`${line}\r\n`)
130
+ })
138
131
  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
- });
132
+ this.transaction.message_stream.get_data((body) => {
133
+ assert.ok(
134
+ /Hello, this is a text part/.test(body.toString()),
135
+ 'text content comes through in final message',
136
+ )
137
+ assert.ok(/This is an html part/.test(body.toString()), 'html content comes through in final message')
138
+ assert.ok(/TEXT_BANNER/.test(body.toString()), 'text banner comes through in final message')
139
+ assert.ok(/HTML_BANNER/.test(body.toString()), 'html banner comes through in final message')
140
+ done()
141
+ })
142
+ })
151
143
  })
152
144
 
153
145
  describe('base64_handling', () => {
154
146
  beforeEach(_set_up)
155
147
 
156
148
  it('varied-base64-fold-lengths-preserve-data', (done) => {
157
-
158
- const parsed_attachments = {};
159
- this.transaction.parse_body = true;
149
+ const parsed_attachments = {}
150
+ this.transaction.parse_body = true
160
151
  //accumulate attachment buffers.
161
152
  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
- });
153
+ let attachment = Buffer.alloc(0)
154
+ stream.on('data', (data) => {
155
+ attachment = Buffer.concat([attachment, data])
156
+ })
166
157
  stream.on('end', () => {
167
- parsed_attachments[filename] = attachment;
168
- });
169
- });
158
+ parsed_attachments[filename] = attachment
159
+ })
160
+ })
170
161
 
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);
162
+ const specimen_path = path.join(__dirname, 'mail_specimen', 'varied-fold-lengths-preserve-data.txt')
163
+ write_file_data_to_transaction(this.transaction, specimen_path)
173
164
 
174
- assert.equal(this.transaction.body.children.length, 6);
165
+ assert.equal(this.transaction.body.children.length, 6)
175
166
 
176
- let first_attachment = null;
167
+ let first_attachment = null
177
168
  for (const i in parsed_attachments) {
178
- const current_attachment = parsed_attachments[i];
179
- first_attachment = first_attachment || current_attachment;
169
+ const current_attachment = parsed_attachments[i]
170
+ first_attachment = first_attachment || current_attachment
180
171
  // All buffers from data that was encoded with varied line lengths should
181
172
  // 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.`);
173
+ assert.equal(
174
+ true,
175
+ first_attachment.equals(current_attachment),
176
+ `The buffer data for '${i}' doesn't appear to be equal to the other attachments, and is likely corrupted.`,
177
+ )
184
178
  }
185
- done();
179
+ done()
186
180
  })
187
181
 
188
182
  it('base64-root-html-decodes-correct-number-of-bytes', (done) => {
183
+ this.transaction.parse_body = true
184
+ const specimen_path = path.join(__dirname, 'mail_specimen', 'base64-root-part.txt')
185
+ write_file_data_to_transaction(this.transaction, specimen_path)
189
186
 
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();
187
+ assert.equal(this.transaction.body.bodytext.length, 425)
188
+ done()
196
189
  })
197
190
  })
198
191
 
@@ -205,66 +198,72 @@ describe('transaction', () => {
205
198
  // populate the same email data in transaction (self.transaction.add_data()) and
206
199
  // in raw buffer, then compare
207
200
  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';
201
+ const self = this
202
+ let buffer = ''
203
+ self.transaction.add_data('Content-Type: multipart/alternative; boundary=abcd\r\n')
204
+ buffer += 'Content-Type: multipart/alternative; boundary=abcd\r\n'
205
+ self.transaction.add_data(
206
+ 'To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n',
207
+ )
208
+ buffer += 'To: "User1_firstname_middlename_lastname" <user1_firstname_middlename_lastname@test.com>,\r\n'
214
209
  // 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`);
210
+ for (let i = 0; i < 725; i++) {
211
+ self.transaction.add_data(
212
+ ` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`,
213
+ )
217
214
  buffer += ` "User${i}_firstname_middlename_lastname" <user${i}_firstname_middlename_lastname@test.com>,\r\n`
218
215
  }
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
- });
216
+ self.transaction.add_data(
217
+ ' "Final User_firstname_middlename_lastname" <final_user_firstname_middlename_lastname@test.com>\r\n',
218
+ )
219
+ buffer +=
220
+ ' "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
+ 'Content-Type: text/plain\r\n',
233
+ '\r\n',
234
+ 'Text part\r\n',
235
+ '--abcd\r\n',
236
+ 'Content-Type: text/html\r\n',
237
+ '\r\n',
238
+ '<p>HTML part</p>\r\n',
239
+ '--abcd--\r\n',
240
+ ].forEach((line) => {
241
+ self.transaction.add_data(line)
242
+ buffer += line
243
+ })
245
244
 
246
245
  this.transaction.end_data(function () {
247
246
  self.transaction.message_stream.get_data(function (body) {
248
- assert.ok(body.includes(buffer), "message is damaged");
249
- done();
247
+ assert.ok(body.includes(buffer), 'message is damaged')
248
+ done()
250
249
  })
251
250
  })
252
251
  })
253
252
  })
254
253
  })
255
254
 
256
- function write_file_data_to_transaction (test_transaction, filename) {
257
- const specimen = fs.readFileSync(filename, 'utf8');
258
- const matcher = /[^\n]*([\n]|$)/g;
255
+ function write_file_data_to_transaction(test_transaction, filename) {
256
+ const specimen = fs.readFileSync(filename, 'utf8')
257
+ const matcher = /[^\n]*([\n]|$)/g
259
258
 
260
- let line;
259
+ let line
261
260
  do {
262
- line = matcher.exec(specimen);
261
+ line = matcher.exec(specimen)
263
262
  if (line[0] == '') {
264
- break;
263
+ break
265
264
  }
266
- test_transaction.add_data(line[0]);
267
- } while (line[0] != '');
265
+ test_transaction.add_data(line[0])
266
+ } while (line[0] != '')
268
267
 
269
- test_transaction.end_data();
268
+ test_transaction.end_data()
270
269
  }