imapflow 2.2.6 → 2.2.7

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 (72) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/commands/append.js +10 -3
  3. package/dist/cjs/commands/authenticate.js +27 -18
  4. package/dist/cjs/commands/close.d.ts +12 -1
  5. package/dist/cjs/commands/close.js +4 -2
  6. package/dist/cjs/commands/delete.js +2 -1
  7. package/dist/cjs/commands/esearch-parser.js +8 -2
  8. package/dist/cjs/commands/fetch.js +35 -9
  9. package/dist/cjs/commands/id.js +8 -1
  10. package/dist/cjs/commands/idle.js +15 -5
  11. package/dist/cjs/commands/list.js +10 -1
  12. package/dist/cjs/commands/login.js +5 -1
  13. package/dist/cjs/commands/logout.js +7 -0
  14. package/dist/cjs/commands/namespace.js +7 -3
  15. package/dist/cjs/commands/quota.js +3 -1
  16. package/dist/cjs/commands/rename.js +2 -1
  17. package/dist/cjs/commands/select.js +5 -0
  18. package/dist/cjs/commands/status.js +6 -1
  19. package/dist/cjs/commands/store.d.ts +1 -1
  20. package/dist/cjs/commands/store.js +1 -2
  21. package/dist/cjs/download.js +82 -91
  22. package/dist/cjs/handler/imap-compiler.js +19 -10
  23. package/dist/cjs/handler/limits.d.ts +11 -0
  24. package/dist/cjs/handler/limits.js +16 -1
  25. package/dist/cjs/handler/parser-instance.d.ts +10 -0
  26. package/dist/cjs/handler/parser-instance.js +25 -10
  27. package/dist/cjs/handler/token-parser.js +36 -28
  28. package/dist/cjs/imap-flow.js +235 -89
  29. package/dist/cjs/package-info.d.ts +1 -1
  30. package/dist/cjs/package-info.js +1 -1
  31. package/dist/cjs/proxy-connection.js +7 -7
  32. package/dist/cjs/search-compiler.js +30 -13
  33. package/dist/cjs/special-use.js +10 -5
  34. package/dist/cjs/tools.d.ts +10 -1
  35. package/dist/cjs/tools.js +30 -3
  36. package/dist/cjs/types.d.ts +19 -4
  37. package/dist/esm/commands/append.js +11 -4
  38. package/dist/esm/commands/authenticate.js +28 -19
  39. package/dist/esm/commands/close.d.ts +12 -1
  40. package/dist/esm/commands/close.js +5 -3
  41. package/dist/esm/commands/delete.js +2 -1
  42. package/dist/esm/commands/esearch-parser.js +8 -2
  43. package/dist/esm/commands/fetch.js +35 -9
  44. package/dist/esm/commands/id.js +9 -2
  45. package/dist/esm/commands/idle.js +16 -6
  46. package/dist/esm/commands/list.js +10 -1
  47. package/dist/esm/commands/login.js +6 -2
  48. package/dist/esm/commands/logout.js +7 -0
  49. package/dist/esm/commands/namespace.js +7 -3
  50. package/dist/esm/commands/quota.js +3 -1
  51. package/dist/esm/commands/rename.js +2 -1
  52. package/dist/esm/commands/select.js +5 -0
  53. package/dist/esm/commands/status.js +7 -2
  54. package/dist/esm/commands/store.d.ts +1 -1
  55. package/dist/esm/commands/store.js +1 -2
  56. package/dist/esm/download.js +82 -91
  57. package/dist/esm/handler/imap-compiler.js +19 -10
  58. package/dist/esm/handler/limits.d.ts +11 -0
  59. package/dist/esm/handler/limits.js +14 -0
  60. package/dist/esm/handler/parser-instance.d.ts +10 -0
  61. package/dist/esm/handler/parser-instance.js +25 -10
  62. package/dist/esm/handler/token-parser.js +37 -29
  63. package/dist/esm/imap-flow.js +235 -89
  64. package/dist/esm/package-info.d.ts +1 -1
  65. package/dist/esm/package-info.js +1 -1
  66. package/dist/esm/proxy-connection.js +7 -7
  67. package/dist/esm/search-compiler.js +30 -13
  68. package/dist/esm/special-use.js +10 -5
  69. package/dist/esm/tools.d.ts +10 -1
  70. package/dist/esm/tools.js +29 -3
  71. package/dist/esm/types.d.ts +19 -4
  72. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  /* eslint new-cap: 0 */
2
2
  import imapFormalSyntax from './imap-formal-syntax.js';
3
- import { MAX_LITERAL_SIZE, normalizeLimit, createLiteralTooLargeError } from './limits.js';
3
+ import { MAX_LITERAL_SIZE, ERROR_CONTEXT_LENGTH, boundedInput, normalizeLimit, createLiteralTooLargeError } from './limits.js';
4
4
  const STATE_ATOM = 0x001;
5
5
  const STATE_LITERAL = 0x002;
6
6
  const STATE_NORMAL = 0x003;
@@ -67,7 +67,7 @@ export class TokenParser {
67
67
  if (!node.isClosed) {
68
68
  let error = new Error(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E9]`);
69
69
  error.code = 'ParserError9';
70
- error.parserContext = { input: this.str, pos: this.pos + this.str.length - 1 };
70
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + this.str.length - 1 };
71
71
  throw error;
72
72
  }
73
73
  let type = (node.type || '').toString().toUpperCase();
@@ -141,7 +141,8 @@ export class TokenParser {
141
141
  if (node.depth > MAX_NODE_DEPTH) {
142
142
  let error = new Error('Too much nesting in IMAP string');
143
143
  error.code = 'MAX_IMAP_NESTING_REACHED';
144
- error._imapStr = this.str;
144
+ // A bounded prefix only, the error travels whole into logs and rejections
145
+ error._imapStr = this.str.slice(0, ERROR_CONTEXT_LENGTH);
145
146
  throw error;
146
147
  }
147
148
  if (typeof startPos === 'number') {
@@ -220,7 +221,7 @@ export class TokenParser {
220
221
  if (!literals.length) {
221
222
  let error = new Error(`Literal without data at position ${this.pos + i} [E35]`);
222
223
  error.code = 'ParserError35';
223
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
224
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
224
225
  throw error;
225
226
  }
226
227
  return literals.shift();
@@ -235,7 +236,7 @@ export class TokenParser {
235
236
  if (!imapFormalSyntax['ATOM-CHAR']().includes(chr) && chr !== '\\' && chr !== '%' && chr.charCodeAt(0) < 0x80) {
236
237
  let error = new Error(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`);
237
238
  error.code = 'ParserError13';
238
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
239
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
239
240
  throw error;
240
241
  }
241
242
  this.currentNode = this.createNode(this.currentNode, this.pos + i);
@@ -266,7 +267,7 @@ export class TokenParser {
266
267
  if (this.currentNode.type !== 'LIST') {
267
268
  let error = new Error(`Unexpected list terminator ) at position ${this.pos + i} [E10]`);
268
269
  error.code = 'ParserError10';
269
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
270
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
270
271
  throw error;
271
272
  }
272
273
  this.currentNode.isClosed = true;
@@ -279,7 +280,7 @@ export class TokenParser {
279
280
  if (this.currentNode.type !== 'SECTION') {
280
281
  let error = new Error(`Unexpected section terminator ] at position ${this.pos + i} [E11]`);
281
282
  error.code = 'ParserError11';
282
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
283
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
283
284
  throw error;
284
285
  }
285
286
  this.currentNode.isClosed = true;
@@ -323,7 +324,7 @@ export class TokenParser {
323
324
  }
324
325
  let error = new Error(`Unexpected literal8 marker at position ${this.pos + i} [E12]`);
325
326
  error.code = 'ParserError12';
326
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
327
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
327
328
  throw error;
328
329
  }
329
330
  // Mark the next literal as literal8 type; consumed when '{' is encountered
@@ -483,16 +484,16 @@ export class TokenParser {
483
484
  chr.charCodeAt(0) < 0x80 && // allow 8bit (presumably unicode) bytes
484
485
  chr !== ']' &&
485
486
  !(chr === '*' && this.currentNode.value === '\\') &&
486
- (!this.parent || !this.parent.command || !['NO', 'BAD', 'OK'].includes(this.parent.command))) {
487
+ (!this.parent || !this.parent.command || !['NO', 'BAD', 'OK'].includes(this.parent.command.toUpperCase()))) {
487
488
  let error = new Error(`Unexpected char at position ${this.pos + i} [E16: ${JSON.stringify(chr)}]`);
488
489
  error.code = 'ParserError16';
489
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
490
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
490
491
  throw error;
491
492
  }
492
493
  else if (this.currentNode.value === '\\*') {
493
494
  let error = new Error(`Unexpected char at position ${this.pos + i} [E17: ${JSON.stringify(chr)}]`);
494
495
  error.code = 'ParserError17';
495
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
496
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
496
497
  throw error;
497
498
  }
498
499
  appendToToken(chr);
@@ -513,7 +514,7 @@ export class TokenParser {
513
514
  if (i >= len) {
514
515
  let error = new Error(`Unexpected end of input at position ${this.pos + i} [E18]`);
515
516
  error.code = 'ParserError18';
516
- error.parserContext = { input: this.str, pos: this.pos + i };
517
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i };
517
518
  throw error;
518
519
  }
519
520
  chr = this.str.charAt(i);
@@ -525,7 +526,7 @@ export class TokenParser {
525
526
  if (tokenLast === '.') {
526
527
  let error = new Error(`Unexpected end of partial at position ${this.pos + i} [E19]`);
527
528
  error.code = 'ParserError19';
528
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
529
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
529
530
  throw error;
530
531
  }
531
532
  this.currentNode.endPos = this.pos + i;
@@ -538,19 +539,19 @@ export class TokenParser {
538
539
  if (chr === '.' && (!tokenLength || tokenHasDot)) {
539
540
  let error = new Error(`Unexpected partial separator . at position ${this.pos + i} [E20]`);
540
541
  error.code = 'ParserError20';
541
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
542
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
542
543
  throw error;
543
544
  }
544
545
  if (!imapFormalSyntax.DIGIT().includes(chr) && chr !== '.') {
545
546
  let error = new Error(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`);
546
547
  error.code = 'ParserError21';
547
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
548
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
548
549
  throw error;
549
550
  }
550
551
  if (tokenLast === '0' && (tokenLength === 1 || tokenPrev === '.') && chr !== '.') {
551
552
  let error = new Error(`Invalid partial at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`);
552
553
  error.code = 'ParserError22';
553
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
554
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
554
555
  throw error;
555
556
  }
556
557
  appendToToken(chr);
@@ -585,7 +586,7 @@ export class TokenParser {
585
586
  if (!('literalLength' in this.currentNode)) {
586
587
  let error = new Error(`Unexpected literal prefix end char } at position ${this.pos + i} [E23]`);
587
588
  error.code = 'ParserError23';
588
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
589
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
589
590
  throw error;
590
591
  }
591
592
  if (this.str.charAt(i + 1) === '\n') {
@@ -597,7 +598,7 @@ export class TokenParser {
597
598
  else {
598
599
  let error = new Error(`Unexpected char at position ${this.pos + i} [E24: ${JSON.stringify(chr)}]`);
599
600
  error.code = 'ParserError24';
600
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
601
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
601
602
  throw error;
602
603
  }
603
604
  this.currentNode.literalLength = Number(this.currentNode.literalLength);
@@ -647,7 +648,7 @@ export class TokenParser {
647
648
  if (literalLength > this.maxLiteralSize || literalLength > available) {
648
649
  let overMax = literalLength > this.maxLiteralSize;
649
650
  let error = createLiteralTooLargeError(literalLength, overMax ? this.maxLiteralSize : available, overMax ? null : `the ${available} bytes available in the input`);
650
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
651
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
651
652
  throw error;
652
653
  }
653
654
  this.currentNode.started = true;
@@ -661,13 +662,13 @@ export class TokenParser {
661
662
  if (!imapFormalSyntax.DIGIT().includes(chr)) {
662
663
  let error = new Error(`Unexpected char at position ${this.pos + i} [E25: ${JSON.stringify(chr)}]`);
663
664
  error.code = 'ParserError25';
664
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
665
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
665
666
  throw error;
666
667
  }
667
668
  if (this.currentNode.literalLength === '0') {
668
669
  let error = new Error(`Invalid literal at position ${this.pos + i} [E26]`);
669
670
  error.code = 'ParserError26';
670
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
671
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
671
672
  throw error;
672
673
  }
673
674
  this.currentNode.literalLength = (this.currentNode.literalLength || '') + chr;
@@ -685,13 +686,13 @@ export class TokenParser {
685
686
  }
686
687
  let error = new Error(`Unexpected end of sequence at position ${this.pos + i} [E27: ${JSON.stringify(chr)}]`);
687
688
  error.code = 'ParserError27';
688
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
689
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
689
690
  throw error;
690
691
  }
691
692
  if (this.currentNode.value !== '*' && tokenLast === '*' && tokenPrev !== ':') {
692
693
  let error = new Error(`Unexpected end of sequence at position ${this.pos + i} [E28: ${JSON.stringify(chr)}]`);
693
694
  error.code = 'ParserError28';
694
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
695
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
695
696
  throw error;
696
697
  }
697
698
  this.currentNode.isClosed = true;
@@ -714,7 +715,7 @@ export class TokenParser {
714
715
  }
715
716
  let error = new Error(`Unexpected range separator : at position ${this.pos + i} [E29]`);
716
717
  error.code = 'ParserError29';
717
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
718
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
718
719
  throw error;
719
720
  }
720
721
  }
@@ -722,7 +723,7 @@ export class TokenParser {
722
723
  if (![',', ':'].includes(tokenLast)) {
723
724
  let error = new Error(`Unexpected range wildcard at position ${this.pos + i} [E30]`);
724
725
  error.code = 'ParserError30';
725
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
726
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
726
727
  throw error;
727
728
  }
728
729
  }
@@ -734,13 +735,13 @@ export class TokenParser {
734
735
  }
735
736
  let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E31]`);
736
737
  error.code = 'ParserError31';
737
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
738
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
738
739
  throw error;
739
740
  }
740
741
  if (tokenLast === '*' && tokenPrev !== ':') {
741
742
  let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E32]`);
742
743
  error.code = 'ParserError32';
743
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
744
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
744
745
  throw error;
745
746
  }
746
747
  }
@@ -751,13 +752,13 @@ export class TokenParser {
751
752
  }
752
753
  let error = new Error(`Unexpected char at position ${this.pos + i} [E33: ${JSON.stringify(chr)}]`);
753
754
  error.code = 'ParserError33';
754
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
755
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
755
756
  throw error;
756
757
  }
757
758
  if (RE_SINGLE_DIGIT.test(chr) && tokenLast === '*') {
758
759
  let error = new Error(`Unexpected number at position ${this.pos + i} [E34: ${JSON.stringify(chr)}]`);
759
760
  error.code = 'ParserError34';
760
- error.parserContext = { input: this.str, pos: this.pos + i, chr };
761
+ error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
761
762
  throw error;
762
763
  }
763
764
  appendToToken(chr);
@@ -769,5 +770,12 @@ export class TokenParser {
769
770
  if (this.state === STATE_SEQUENCE && (tokenLast === ':' || tokenLast === ',') && !tokenHasStar) {
770
771
  this.currentNode.type = 'ATOM';
771
772
  }
773
+ // A star-led sequence set ("*:4") is only closed by a space or a closing delimiter, so one
774
+ // that ends the input is closed here, under the same rules a space applies to it. A bare "*"
775
+ // is left to getAttributes(), which reads it as an atom
776
+ if (this.state === STATE_SEQUENCE && !this.currentNode.isClosed && (RE_SINGLE_DIGIT.test(tokenLast) || (tokenLast === '*' && tokenPrev === ':'))) {
777
+ this.currentNode.isClosed = true;
778
+ this.currentNode.endPos = this.pos + this.str.length - 1;
779
+ }
772
780
  }
773
781
  }