imapflow 2.2.6 → 2.2.8
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.
- package/CHANGELOG.md +24 -0
- package/dist/cjs/commands/append.js +10 -3
- package/dist/cjs/commands/authenticate.js +42 -22
- package/dist/cjs/commands/close.d.ts +12 -1
- package/dist/cjs/commands/close.js +4 -2
- package/dist/cjs/commands/delete.js +2 -1
- package/dist/cjs/commands/enable.js +6 -0
- package/dist/cjs/commands/esearch-parser.js +8 -2
- package/dist/cjs/commands/fetch.js +57 -14
- package/dist/cjs/commands/id.js +8 -1
- package/dist/cjs/commands/idle.js +15 -5
- package/dist/cjs/commands/list.js +10 -1
- package/dist/cjs/commands/login.js +5 -1
- package/dist/cjs/commands/logout.js +7 -0
- package/dist/cjs/commands/namespace.js +7 -3
- package/dist/cjs/commands/quota.js +3 -1
- package/dist/cjs/commands/rename.js +2 -1
- package/dist/cjs/commands/select.js +5 -0
- package/dist/cjs/commands/status.js +6 -1
- package/dist/cjs/commands/store.d.ts +1 -1
- package/dist/cjs/commands/store.js +8 -8
- package/dist/cjs/download.js +220 -95
- package/dist/cjs/handler/imap-compiler.js +19 -10
- package/dist/cjs/handler/limits.d.ts +11 -0
- package/dist/cjs/handler/limits.js +16 -1
- package/dist/cjs/handler/parser-instance.d.ts +10 -0
- package/dist/cjs/handler/parser-instance.js +25 -10
- package/dist/cjs/handler/token-parser.js +36 -28
- package/dist/cjs/imap-flow.d.ts +2 -2
- package/dist/cjs/imap-flow.js +256 -95
- package/dist/cjs/package-info.d.ts +1 -1
- package/dist/cjs/package-info.js +1 -1
- package/dist/cjs/proxy-connection.js +7 -7
- package/dist/cjs/search-compiler.js +33 -13
- package/dist/cjs/special-use.js +10 -5
- package/dist/cjs/tools.d.ts +14 -4
- package/dist/cjs/tools.js +69 -9
- package/dist/cjs/types.d.ts +19 -4
- package/dist/esm/commands/append.js +11 -4
- package/dist/esm/commands/authenticate.js +43 -23
- package/dist/esm/commands/close.d.ts +12 -1
- package/dist/esm/commands/close.js +5 -3
- package/dist/esm/commands/delete.js +2 -1
- package/dist/esm/commands/enable.js +6 -0
- package/dist/esm/commands/esearch-parser.js +8 -2
- package/dist/esm/commands/fetch.js +57 -14
- package/dist/esm/commands/id.js +9 -2
- package/dist/esm/commands/idle.js +16 -6
- package/dist/esm/commands/list.js +10 -1
- package/dist/esm/commands/login.js +6 -2
- package/dist/esm/commands/logout.js +7 -0
- package/dist/esm/commands/namespace.js +7 -3
- package/dist/esm/commands/quota.js +3 -1
- package/dist/esm/commands/rename.js +2 -1
- package/dist/esm/commands/select.js +5 -0
- package/dist/esm/commands/status.js +7 -2
- package/dist/esm/commands/store.d.ts +1 -1
- package/dist/esm/commands/store.js +9 -9
- package/dist/esm/download.js +220 -95
- package/dist/esm/handler/imap-compiler.js +19 -10
- package/dist/esm/handler/limits.d.ts +11 -0
- package/dist/esm/handler/limits.js +14 -0
- package/dist/esm/handler/parser-instance.d.ts +10 -0
- package/dist/esm/handler/parser-instance.js +25 -10
- package/dist/esm/handler/token-parser.js +37 -29
- package/dist/esm/imap-flow.d.ts +2 -2
- package/dist/esm/imap-flow.js +256 -95
- package/dist/esm/package-info.d.ts +1 -1
- package/dist/esm/package-info.js +1 -1
- package/dist/esm/proxy-connection.js +7 -7
- package/dist/esm/search-compiler.js +33 -13
- package/dist/esm/special-use.js +10 -5
- package/dist/esm/tools.d.ts +14 -4
- package/dist/esm/tools.js +68 -9
- package/dist/esm/types.d.ts +19 -4
- package/package.json +5 -3
|
@@ -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 = {
|
|
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
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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
|
}
|
package/dist/esm/imap-flow.d.ts
CHANGED
|
@@ -122,8 +122,8 @@ export declare class ImapFlow extends EventEmitter {
|
|
|
122
122
|
*/
|
|
123
123
|
usable: boolean;
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
125
|
+
* `true` once the connection is authenticated (by LOGIN, AUTHENTICATE or a PREAUTH greeting),
|
|
126
|
+
* `false` before that. The user name is in `options.auth.user`
|
|
127
127
|
*/
|
|
128
128
|
authenticated: string | boolean;
|
|
129
129
|
/**
|