emailengine-app 2.61.1 → 2.61.3

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 (136) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/data/google-crawlers.json +1 -1
  3. package/lib/account/account-state.js +248 -0
  4. package/lib/account.js +45 -193
  5. package/lib/api-routes/account-routes.js +1023 -0
  6. package/lib/api-routes/message-routes.js +1377 -0
  7. package/lib/consts.js +12 -2
  8. package/lib/email-client/base-client.js +282 -771
  9. package/lib/email-client/gmail/gmail-api.js +243 -0
  10. package/lib/email-client/gmail-client.js +145 -53
  11. package/lib/email-client/imap/mailbox.js +24 -698
  12. package/lib/email-client/imap/sync-operations.js +812 -0
  13. package/lib/email-client/imap-client.js +1 -1
  14. package/lib/email-client/message-builder.js +566 -0
  15. package/lib/email-client/notification-handler.js +314 -0
  16. package/lib/email-client/outlook/graph-api.js +326 -0
  17. package/lib/email-client/outlook-client.js +159 -113
  18. package/lib/email-client/smtp-pool-manager.js +196 -0
  19. package/lib/imapproxy/imap-server.js +3 -12
  20. package/lib/oauth/gmail.js +4 -4
  21. package/lib/oauth/mail-ru.js +30 -5
  22. package/lib/oauth/outlook.js +57 -3
  23. package/lib/oauth/pubsub/google.js +30 -11
  24. package/lib/oauth/scope-checker.js +202 -0
  25. package/lib/oauth2-apps.js +8 -4
  26. package/lib/redis-operations.js +484 -0
  27. package/lib/routes-ui.js +283 -2582
  28. package/lib/tools.js +4 -196
  29. package/lib/ui-routes/account-routes.js +1931 -0
  30. package/lib/ui-routes/admin-config-routes.js +1233 -0
  31. package/lib/ui-routes/admin-entities-routes.js +2367 -0
  32. package/lib/ui-routes/oauth-routes.js +992 -0
  33. package/lib/utils/network.js +237 -0
  34. package/package.json +10 -10
  35. package/sbom.json +1 -1
  36. package/static/js/app.js +5 -5
  37. package/static/licenses.html +79 -19
  38. package/translations/de.mo +0 -0
  39. package/translations/de.po +97 -86
  40. package/translations/en.mo +0 -0
  41. package/translations/en.po +80 -75
  42. package/translations/et.mo +0 -0
  43. package/translations/et.po +96 -86
  44. package/translations/fr.mo +0 -0
  45. package/translations/fr.po +97 -86
  46. package/translations/ja.mo +0 -0
  47. package/translations/ja.po +96 -86
  48. package/translations/messages.pot +105 -91
  49. package/translations/nl.mo +0 -0
  50. package/translations/nl.po +98 -86
  51. package/translations/pl.mo +0 -0
  52. package/translations/pl.po +96 -86
  53. package/views/account/security.hbs +4 -4
  54. package/views/accounts/account.hbs +13 -13
  55. package/views/accounts/register/imap-server.hbs +12 -12
  56. package/views/config/document-store/pre-processing/index.hbs +4 -2
  57. package/views/config/oauth/app.hbs +6 -7
  58. package/views/config/oauth/index.hbs +2 -2
  59. package/views/config/service.hbs +3 -4
  60. package/views/dashboard.hbs +5 -7
  61. package/views/error.hbs +22 -7
  62. package/views/gateways/gateway.hbs +2 -2
  63. package/views/partials/add_account_modal.hbs +7 -10
  64. package/views/partials/document_store_header.hbs +1 -1
  65. package/views/partials/editor_scope_info.hbs +0 -1
  66. package/views/partials/oauth_config_header.hbs +1 -1
  67. package/views/partials/side_menu.hbs +3 -3
  68. package/views/partials/webhook_form.hbs +2 -2
  69. package/views/templates/index.hbs +1 -1
  70. package/views/templates/template.hbs +8 -8
  71. package/views/tokens/index.hbs +6 -6
  72. package/views/tokens/new.hbs +1 -1
  73. package/views/webhooks/index.hbs +4 -4
  74. package/views/webhooks/webhook.hbs +7 -7
  75. package/workers/api.js +148 -2436
  76. package/workers/smtp.js +2 -1
  77. package/lib/imapproxy/imap-core/test/client.js +0 -46
  78. package/lib/imapproxy/imap-core/test/fixtures/append.eml +0 -1196
  79. package/lib/imapproxy/imap-core/test/fixtures/chunks.js +0 -44
  80. package/lib/imapproxy/imap-core/test/fixtures/fix1.eml +0 -6
  81. package/lib/imapproxy/imap-core/test/fixtures/fix2.eml +0 -599
  82. package/lib/imapproxy/imap-core/test/fixtures/fix3.eml +0 -32
  83. package/lib/imapproxy/imap-core/test/fixtures/fix4.eml +0 -6
  84. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.eml +0 -599
  85. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.js +0 -2740
  86. package/lib/imapproxy/imap-core/test/fixtures/mimetorture.json +0 -1411
  87. package/lib/imapproxy/imap-core/test/fixtures/mimetree.js +0 -85
  88. package/lib/imapproxy/imap-core/test/fixtures/nodemailer.eml +0 -582
  89. package/lib/imapproxy/imap-core/test/fixtures/ryan_finnie_mime_torture.eml +0 -599
  90. package/lib/imapproxy/imap-core/test/fixtures/simple.eml +0 -42
  91. package/lib/imapproxy/imap-core/test/fixtures/simple.json +0 -164
  92. package/lib/imapproxy/imap-core/test/imap-compile-stream-test.js +0 -671
  93. package/lib/imapproxy/imap-core/test/imap-compiler-test.js +0 -272
  94. package/lib/imapproxy/imap-core/test/imap-indexer-test.js +0 -236
  95. package/lib/imapproxy/imap-core/test/imap-parser-test.js +0 -922
  96. package/lib/imapproxy/imap-core/test/memory-notifier.js +0 -129
  97. package/lib/imapproxy/imap-core/test/prepare.sh +0 -74
  98. package/lib/imapproxy/imap-core/test/protocol-test.js +0 -1756
  99. package/lib/imapproxy/imap-core/test/search-test.js +0 -1356
  100. package/lib/imapproxy/imap-core/test/test-client.js +0 -152
  101. package/lib/imapproxy/imap-core/test/test-server.js +0 -623
  102. package/lib/imapproxy/imap-core/test/tools-test.js +0 -22
  103. package/test/api-test.js +0 -899
  104. package/test/autoreply-test.js +0 -327
  105. package/test/bounce-test.js +0 -151
  106. package/test/complaint-test.js +0 -256
  107. package/test/fixtures/autoreply/LICENSE +0 -27
  108. package/test/fixtures/autoreply/rfc3834-01.eml +0 -23
  109. package/test/fixtures/autoreply/rfc3834-02.eml +0 -24
  110. package/test/fixtures/autoreply/rfc3834-03.eml +0 -26
  111. package/test/fixtures/autoreply/rfc3834-04.eml +0 -48
  112. package/test/fixtures/autoreply/rfc3834-05.eml +0 -19
  113. package/test/fixtures/autoreply/rfc3834-06.eml +0 -59
  114. package/test/fixtures/bounces/163.eml +0 -2521
  115. package/test/fixtures/bounces/fastmail.eml +0 -242
  116. package/test/fixtures/bounces/gmail.eml +0 -252
  117. package/test/fixtures/bounces/hotmail.eml +0 -655
  118. package/test/fixtures/bounces/mailru.eml +0 -121
  119. package/test/fixtures/bounces/outlook.eml +0 -1107
  120. package/test/fixtures/bounces/postfix.eml +0 -101
  121. package/test/fixtures/bounces/rambler.eml +0 -116
  122. package/test/fixtures/bounces/workmail.eml +0 -142
  123. package/test/fixtures/bounces/yahoo.eml +0 -139
  124. package/test/fixtures/bounces/zoho.eml +0 -83
  125. package/test/fixtures/bounces/zonemta.eml +0 -100
  126. package/test/fixtures/complaints/LICENSE +0 -27
  127. package/test/fixtures/complaints/amazonses.eml +0 -72
  128. package/test/fixtures/complaints/dmarc.eml +0 -59
  129. package/test/fixtures/complaints/hotmail.eml +0 -49
  130. package/test/fixtures/complaints/optout.eml +0 -40
  131. package/test/fixtures/complaints/standard-arf.eml +0 -68
  132. package/test/fixtures/complaints/yahoo.eml +0 -68
  133. package/test/oauth2-apps-test.js +0 -301
  134. package/test/sendonly-test.js +0 -160
  135. package/test/test-config.js +0 -34
  136. package/test/webhooks-server.js +0 -39
@@ -1,671 +0,0 @@
1
- /*eslint no-unused-expressions: 0, prefer-arrow-callback: 0 */
2
-
3
- 'use strict';
4
-
5
- const chai = require('chai');
6
- const imapHandler = require('../lib/handler/imap-handler');
7
- const PassThrough = require('stream').PassThrough;
8
- const crypto = require('crypto');
9
- const expect = chai.expect;
10
- chai.config.includeStack = true;
11
-
12
- describe('IMAP Command Compile Stream', function () {
13
- describe('#compile', function () {
14
- it('should compile correctly', function (done) {
15
- let command =
16
- '* FETCH (ENVELOPE ("Mon, 2 Sep 2013 05:30:13 -0700 (PDT)" NIL ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "tr.ee")) NIL NIL NIL "<-4730417346358914070@unknownmsgid>") BODYSTRUCTURE (("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 105 (NIL NIL ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "pangalink.net")) NIL NIL "<test1>" NIL) ("TEXT" "PLAIN" NIL NIL NIL "7BIT" 12 0 NIL NIL NIL) 5 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 83 (NIL NIL ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "kreata.ee")) ((NIL NIL "andris" "pangalink.net")) NIL NIL "NIL" NIL) ("TEXT" "PLAIN" NIL NIL NIL "7BIT" 12 0 NIL NIL NIL) 4 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "utf-8") NIL NIL "QUOTED-PRINTABLE" 19 0 NIL NIL NIL) "MIXED" ("BOUNDARY" "----mailcomposer-?=_1-1328088797399") NIL NIL))',
17
- parsed = imapHandler.parser(command, {
18
- allowUntagged: true
19
- });
20
-
21
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
22
- expect(err).to.not.exist;
23
- expect(compiled.toString('binary')).to.equal(command);
24
- done();
25
- });
26
- });
27
- });
28
-
29
- describe('Types', function () {
30
- let parsed;
31
-
32
- beforeEach(function () {
33
- parsed = {
34
- tag: '*',
35
- command: 'CMD'
36
- };
37
- });
38
-
39
- describe('No attributes', function () {
40
- it('should compile correctly', function (done) {
41
- let command = '* CMD';
42
-
43
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
44
- expect(err).to.not.exist;
45
- expect(compiled.toString('binary')).to.equal(command);
46
- done();
47
- });
48
- });
49
- });
50
-
51
- describe('TEXT', function () {
52
- it('should compile correctly', function (done) {
53
- parsed.attributes = [
54
- {
55
- type: 'TEXT',
56
- value: 'Tere tere!'
57
- }
58
- ];
59
- let command = '* CMD Tere tere!';
60
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
61
- expect(err).to.not.exist;
62
- expect(compiled.toString('binary')).to.equal(command);
63
- done();
64
- });
65
- });
66
- });
67
-
68
- describe('SECTION', function () {
69
- it('should compile correctly', function (done) {
70
- parsed.attributes = [
71
- {
72
- type: 'SECTION',
73
- section: [
74
- {
75
- type: 'ATOM',
76
- value: 'ALERT'
77
- }
78
- ]
79
- }
80
- ];
81
- let command = '* CMD [ALERT]';
82
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
83
- expect(err).to.not.exist;
84
- expect(compiled.toString('binary')).to.equal(command);
85
- done();
86
- });
87
- });
88
- });
89
-
90
- describe('ATOM', function () {
91
- it('should compile correctly', function (done) {
92
- parsed.attributes = [
93
- {
94
- type: 'ATOM',
95
- value: 'ALERT'
96
- },
97
- {
98
- type: 'ATOM',
99
- value: '\\ALERT'
100
- },
101
- {
102
- type: 'ATOM',
103
- value: 'NO ALERT'
104
- }
105
- ];
106
- let command = '* CMD ALERT \\ALERT "NO ALERT"';
107
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
108
- expect(err).to.not.exist;
109
- expect(compiled.toString('binary')).to.equal(command);
110
- done();
111
- });
112
- });
113
- });
114
-
115
- describe('SEQUENCE', function () {
116
- it('should compile correctly', function (done) {
117
- parsed.attributes = [
118
- {
119
- type: 'SEQUENCE',
120
- value: '*:4,5,6'
121
- }
122
- ];
123
- let command = '* CMD *:4,5,6';
124
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
125
- expect(err).to.not.exist;
126
- expect(compiled.toString('binary')).to.equal(command);
127
- done();
128
- });
129
- });
130
- });
131
-
132
- describe('NIL', function () {
133
- it('should compile correctly', function (done) {
134
- parsed.attributes = [null, null];
135
-
136
- let command = '* CMD NIL NIL';
137
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
138
- expect(err).to.not.exist;
139
- expect(compiled.toString('binary')).to.equal(command);
140
- done();
141
- });
142
- });
143
- });
144
-
145
- describe('TEXT', function () {
146
- it('should compile correctly', function (done) {
147
- parsed.attributes = [
148
- // keep indentation
149
- {
150
- type: 'String',
151
- value: 'Tere tere!',
152
- sensitive: true
153
- },
154
- 'Vana kere'
155
- ];
156
-
157
- let command = '* CMD "Tere tere!" "Vana kere"';
158
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
159
- expect(err).to.not.exist;
160
- expect(compiled.toString('binary')).to.equal(command);
161
- done();
162
- });
163
- });
164
-
165
- it('should keep short strings', function (done) {
166
- parsed.attributes = [
167
- // keep indentation
168
- {
169
- type: 'String',
170
- value: 'Tere tere!'
171
- },
172
- 'Vana kere'
173
- ];
174
-
175
- let command = '* CMD "Tere tere!" "Vana kere"';
176
- resolveStream(imapHandler.compileStream(parsed, true), (err, compiled) => {
177
- expect(err).to.not.exist;
178
- expect(compiled.toString('binary')).to.equal(command);
179
- done();
180
- });
181
- });
182
-
183
- it('should hide strings', function (done) {
184
- parsed.attributes = [
185
- // keep indentation
186
- {
187
- type: 'String',
188
- value: 'Tere tere!',
189
- sensitive: true
190
- },
191
- 'Vana kere'
192
- ];
193
-
194
- let command = '* CMD "(* value hidden *)" "Vana kere"';
195
- resolveStream(imapHandler.compileStream(parsed, true), (err, compiled) => {
196
- expect(err).to.not.exist;
197
- expect(compiled.toString('binary')).to.equal(command);
198
- done();
199
- });
200
- });
201
-
202
- it('should hide long strings', function (done) {
203
- parsed.attributes = [
204
- // keep indentation
205
- {
206
- type: 'String',
207
- value: 'Tere tere! Tere tere! Tere tere! Tere tere! Tere tere!'
208
- },
209
- 'Vana kere'
210
- ];
211
-
212
- let command = '* CMD "(* 54B string *)" "Vana kere"';
213
- resolveStream(imapHandler.compileStream(parsed, true), (err, compiled) => {
214
- expect(err).to.not.exist;
215
- expect(compiled.toString('binary')).to.equal(command);
216
- done();
217
- });
218
- });
219
- });
220
-
221
- describe('No Command', function () {
222
- it('should compile correctly', function (done) {
223
- parsed = {
224
- tag: '*',
225
- attributes: [
226
- 1,
227
- {
228
- type: 'ATOM',
229
- value: 'EXPUNGE'
230
- }
231
- ]
232
- };
233
-
234
- let command = '* 1 EXPUNGE';
235
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
236
- expect(err).to.not.exist;
237
- expect(compiled.toString('binary')).to.equal(command);
238
- done();
239
- });
240
- });
241
- });
242
- describe('Literal', function () {
243
- it('should return as text', function (done) {
244
- let parsed = {
245
- tag: '*',
246
- command: 'CMD',
247
- attributes: [
248
- // keep indentation
249
- {
250
- type: 'LITERAL',
251
- value: 'Tere tere!'
252
- },
253
- 'Vana kere'
254
- ]
255
- };
256
-
257
- let command = '* CMD {10}\r\nTere tere! "Vana kere"';
258
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
259
- expect(err).to.not.exist;
260
- expect(compiled.toString('binary')).to.equal(command);
261
- done();
262
- });
263
- });
264
-
265
- it('should compile correctly without tag and command', function (done) {
266
- let parsed = {
267
- attributes: [
268
- {
269
- type: 'LITERAL',
270
- value: 'Tere tere!'
271
- },
272
- {
273
- type: 'LITERAL',
274
- value: 'Vana kere'
275
- }
276
- ]
277
- };
278
- let command = '{10}\r\nTere tere! {9}\r\nVana kere';
279
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
280
- expect(err).to.not.exist;
281
- expect(compiled.toString('binary')).to.equal(command);
282
- done();
283
- });
284
- });
285
-
286
- it('should return byte length', function (done) {
287
- let parsed = {
288
- tag: '*',
289
- command: 'CMD',
290
- attributes: [
291
- // keep indentation
292
- {
293
- type: 'LITERAL',
294
- value: 'Tere tere!'
295
- },
296
- 'Vana kere'
297
- ]
298
- };
299
-
300
- let command = '* CMD "(* 10B literal *)" "Vana kere"';
301
- resolveStream(imapHandler.compileStream(parsed, true), (err, compiled) => {
302
- expect(err).to.not.exist;
303
- expect(compiled.toString('binary')).to.equal(command);
304
- done();
305
- });
306
- });
307
-
308
- it('should mix with other values', function (done) {
309
- let s = new PassThrough();
310
- let str = 'abc'.repeat(100);
311
- let parsed = {
312
- attributes: [
313
- {
314
- type: 'ATOM',
315
- value: 'BODY'
316
- },
317
- {
318
- type: 'LITERAL',
319
- value: 'Tere tere!'
320
- },
321
- {
322
- type: 'ATOM',
323
- value: 'BODY'
324
- },
325
- {
326
- type: 'LITERAL',
327
- //value: str
328
- value: s,
329
- expectedLength: str.length
330
- },
331
- {
332
- type: 'ATOM',
333
- value: 'UID'
334
- },
335
- {
336
- type: 'ATOM',
337
- value: '12345'
338
- }
339
- ]
340
- };
341
- setImmediate(function () {
342
- s.end(str);
343
- });
344
- let command = 'BODY {10}\r\nTere tere! BODY {' + str.length + '}\r\n' + str + ' UID 12345';
345
- resolveStream(imapHandler.compileStream(parsed), (err, compiled) => {
346
- expect(err).to.not.exist;
347
- expect(compiled.toString('binary')).to.equal(command);
348
- done();
349
- });
350
- });
351
-
352
- it('should pipe literal streams', function (done) {
353
- let stream1 = new PassThrough();
354
- let stream2 = new PassThrough();
355
- let stream3 = new PassThrough();
356
- let parsed = {
357
- tag: '*',
358
- command: 'CMD',
359
- attributes: [
360
- // keep indentation
361
- {
362
- type: 'LITERAL',
363
- value: 'Tere tere!'
364
- },
365
- {
366
- type: 'LITERAL',
367
- expectedLength: 5,
368
- value: stream1
369
- },
370
- 'Vana kere',
371
- {
372
- type: 'LITERAL',
373
- expectedLength: 7,
374
- value: stream2
375
- },
376
- {
377
- type: 'LITERAL',
378
- value: 'Kuidas laheb?'
379
- },
380
- {
381
- type: 'LITERAL',
382
- expectedLength: 5,
383
- value: stream3
384
- }
385
- ]
386
- };
387
-
388
- let command = '* CMD {10}\r\nTere tere! {5}\r\ntest1 "Vana kere" {7}\r\ntest2 {13}\r\nKuidas laheb? {5}\r\ntest3';
389
- resolveStream(imapHandler.compileStream(parsed, false), (err, compiled) => {
390
- expect(err).to.not.exist;
391
- expect(compiled.toString('binary')).to.equal(command);
392
- done();
393
- });
394
-
395
- setTimeout(() => {
396
- stream2.end('test2');
397
- setTimeout(() => {
398
- stream1.end('test1');
399
- setTimeout(() => {
400
- stream3.end('test3');
401
- }, 100);
402
- }, 100);
403
- }, 100);
404
- });
405
-
406
- it('should pipe limited literal streams', function (done) {
407
- let stream1 = new PassThrough();
408
- let stream2 = new PassThrough();
409
- let stream3 = new PassThrough();
410
- let parsed = {
411
- tag: '*',
412
- command: 'CMD',
413
- attributes: [
414
- // keep indentation
415
- {
416
- type: 'LITERAL',
417
- value: 'Tere tere!'
418
- },
419
- {
420
- type: 'LITERAL',
421
- expectedLength: 5,
422
- value: stream1,
423
- startFrom: 2,
424
- maxLength: 2
425
- },
426
- 'Vana kere',
427
- {
428
- type: 'LITERAL',
429
- expectedLength: 7,
430
- value: stream2,
431
- startFrom: 2
432
- },
433
- {
434
- type: 'LITERAL',
435
- value: 'Kuidas laheb?'
436
- },
437
- {
438
- type: 'LITERAL',
439
- expectedLength: 7,
440
- value: stream3,
441
- startFrom: 2,
442
- maxLength: 2
443
- }
444
- ]
445
- };
446
-
447
- let command = '* CMD {10}\r\nTere tere! {2}\r\nst "Vana kere" {5}\r\nst2 {13}\r\nKuidas laheb? {2}\r\nst';
448
- resolveStream(imapHandler.compileStream(parsed, false), (err, compiled) => {
449
- expect(err).to.not.exist;
450
- expect(compiled.toString('binary')).to.equal(command);
451
- done();
452
- });
453
-
454
- setTimeout(() => {
455
- stream2.end('test2');
456
- setTimeout(() => {
457
- stream1.end('test1');
458
- setTimeout(() => {
459
- stream3.end('test3');
460
- }, 100);
461
- }, 100);
462
- }, 100);
463
- });
464
-
465
- it('should pipe errors for literal streams', function (done) {
466
- let stream1 = new PassThrough();
467
- let parsed = {
468
- tag: '*',
469
- command: 'CMD',
470
- attributes: [
471
- // keep indentation
472
- {
473
- type: 'LITERAL',
474
- value: 'Tere tere!'
475
- },
476
- {
477
- type: 'LITERAL',
478
- expectedLength: 5,
479
- value: stream1
480
- }
481
- ]
482
- };
483
-
484
- resolveStream(imapHandler.compileStream(parsed, false), err => {
485
- expect(err).to.exist;
486
- done();
487
- });
488
-
489
- setTimeout(() => {
490
- stream1.emit('error', new Error('Stream error'));
491
- }, 100);
492
- });
493
- });
494
- });
495
-
496
- describe('#LengthLimiter', function () {
497
- this.timeout(10000);
498
-
499
- it('should emit exact length', function (done) {
500
- let len = 1024;
501
- let limiter = new imapHandler.compileStream.LengthLimiter(len);
502
- let expected = 'X'.repeat(len);
503
-
504
- resolveStream(limiter, (err, value) => {
505
- value = value.toString();
506
- expect(err).to.not.exist;
507
- expect(value).to.equal(expected);
508
- done();
509
- });
510
-
511
- let emitted = 0;
512
- let emitter = () => {
513
- let str = 'X'.repeat(128);
514
- emitted += str.length;
515
- limiter.write(Buffer.from(str));
516
- if (emitted >= len) {
517
- limiter.end();
518
- } else {
519
- setTimeout(emitter, 100);
520
- }
521
- };
522
-
523
- setTimeout(emitter, 100);
524
- });
525
-
526
- it('should truncate output', function (done) {
527
- let len = 1024;
528
- let limiter = new imapHandler.compileStream.LengthLimiter(len - 100);
529
- let expected = 'X'.repeat(len - 100);
530
-
531
- resolveStream(limiter, (err, value) => {
532
- value = value.toString();
533
- expect(err).to.not.exist;
534
- expect(value).to.equal(expected);
535
- done();
536
- });
537
-
538
- let emitted = 0;
539
- let emitter = () => {
540
- let str = 'X'.repeat(128);
541
- emitted += str.length;
542
- limiter.write(Buffer.from(str));
543
- if (emitted >= len) {
544
- limiter.end();
545
- } else {
546
- setTimeout(emitter, 100);
547
- }
548
- };
549
-
550
- setTimeout(emitter, 100);
551
- });
552
-
553
- it('should skip output', function (done) {
554
- let len = 1024;
555
- let limiter = new imapHandler.compileStream.LengthLimiter(len - 100, false, 30);
556
- let expected = 'X'.repeat(len - 100 - 30);
557
-
558
- resolveStream(limiter, (err, value) => {
559
- value = value.toString();
560
- expect(err).to.not.exist;
561
- expect(value).to.equal(expected);
562
- done();
563
- });
564
-
565
- let emitted = 0;
566
- let emitter = () => {
567
- let str = 'X'.repeat(128);
568
- emitted += str.length;
569
- limiter.write(Buffer.from(str));
570
- if (emitted >= len) {
571
- limiter.end();
572
- } else {
573
- setTimeout(emitter, 100);
574
- }
575
- };
576
-
577
- setTimeout(emitter, 100);
578
- });
579
-
580
- it('should pad output', function (done) {
581
- let len = 1024;
582
- let limiter = new imapHandler.compileStream.LengthLimiter(len + 100);
583
- let expected = 'X'.repeat(len) + ' '.repeat(100);
584
-
585
- resolveStream(limiter, (err, value) => {
586
- value = value.toString();
587
- expect(err).to.not.exist;
588
- expect(value).to.equal(expected);
589
- done();
590
- });
591
-
592
- let emitted = 0;
593
- let emitter = () => {
594
- let str = 'X'.repeat(128);
595
- emitted += str.length;
596
- limiter.write(Buffer.from(str));
597
- if (emitted >= len) {
598
- limiter.end();
599
- } else {
600
- setTimeout(emitter, 100);
601
- }
602
- };
603
-
604
- setTimeout(emitter, 100);
605
- });
606
-
607
- it('should pipe to several streams', function (done) {
608
- let len = 1024;
609
- let start = 30;
610
- let margin = 200;
611
- let limiter = new imapHandler.compileStream.LengthLimiter(len - margin, false, start);
612
- let stream = new PassThrough();
613
- let input = crypto.randomBytes(len / 2).toString('hex');
614
- let expected1 = input.substr(start, len - margin - start);
615
- let expected2 = input.substr(len - margin);
616
-
617
- limiter.on('done', function (remainder) {
618
- stream.unpipe(limiter);
619
- if (remainder) {
620
- stream.unshift(remainder);
621
- }
622
- limiter.end();
623
- });
624
-
625
- resolveStream(limiter, (err, value) => {
626
- value = value.toString();
627
- expect(err).to.not.exist;
628
- expect(value).to.equal(expected1);
629
- resolveStream(stream, (err, value) => {
630
- value = value.toString();
631
- expect(err).to.not.exist;
632
- expect(value).to.equal(expected2);
633
- done();
634
- });
635
- });
636
-
637
- let emitted = 0;
638
- let emitter = () => {
639
- let str = input.substr(emitted, 128);
640
- emitted += str.length;
641
-
642
- stream.write(Buffer.from(str));
643
- if (emitted >= len) {
644
- stream.end();
645
- } else {
646
- setImmediate(emitter);
647
- }
648
- };
649
-
650
- stream.pipe(limiter);
651
- setImmediate(emitter);
652
- });
653
- });
654
- });
655
-
656
- function resolveStream(stream, callback) {
657
- let chunks = [];
658
- let chunklen = 0;
659
-
660
- stream.on('readable', () => {
661
- let chunk;
662
-
663
- while ((chunk = stream.read()) !== null) {
664
- chunks.push(chunk);
665
- chunklen += chunk.length;
666
- }
667
- });
668
-
669
- stream.on('error', err => callback(err));
670
- stream.on('end', () => callback(null, Buffer.concat(chunks, chunklen)));
671
- }