imapflow 2.3.0 → 2.4.1
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 +19 -0
- package/SECURITY.md +126 -55
- package/dist/cjs/commands/append.d.ts +1 -1
- package/dist/cjs/commands/append.js +15 -4
- package/dist/cjs/commands/compress.js +2 -2
- package/dist/cjs/commands/idle.js +2 -3
- package/dist/cjs/commands/status.js +2 -4
- package/dist/cjs/connection-deadline.d.ts +1 -1
- package/dist/cjs/connection-deadline.js +2 -4
- package/dist/cjs/download.js +22 -19
- package/dist/cjs/errors.d.ts +15 -0
- package/dist/cjs/errors.js +22 -0
- package/dist/cjs/handler/imap-compiler.d.ts +4 -4
- package/dist/cjs/handler/imap-compiler.js +18 -18
- package/dist/cjs/handler/imap-parser.js +28 -3
- package/dist/cjs/handler/imap-stream.js +9 -8
- package/dist/cjs/handler/limits.d.ts +1 -1
- package/dist/cjs/handler/limits.js +5 -7
- package/dist/cjs/handler/parser-instance.js +23 -38
- package/dist/cjs/handler/token-parser.d.ts +12 -0
- package/dist/cjs/handler/token-parser.js +44 -104
- package/dist/cjs/imap-flow.d.ts +4 -3
- package/dist/cjs/imap-flow.js +72 -72
- package/dist/cjs/package-info.d.ts +1 -1
- package/dist/cjs/package-info.js +1 -1
- package/dist/cjs/proxy-connection.js +2 -5
- package/dist/cjs/search-compiler.js +2 -3
- package/dist/cjs/tools.d.ts +2 -2
- package/dist/cjs/tools.js +8 -11
- package/dist/esm/commands/append.d.ts +1 -1
- package/dist/esm/commands/append.js +15 -4
- package/dist/esm/commands/compress.js +2 -2
- package/dist/esm/commands/idle.js +2 -3
- package/dist/esm/commands/status.js +2 -4
- package/dist/esm/connection-deadline.d.ts +1 -1
- package/dist/esm/connection-deadline.js +2 -4
- package/dist/esm/download.js +22 -19
- package/dist/esm/errors.d.ts +15 -0
- package/dist/esm/errors.js +21 -0
- package/dist/esm/handler/imap-compiler.d.ts +4 -4
- package/dist/esm/handler/imap-compiler.js +18 -18
- package/dist/esm/handler/imap-parser.js +28 -3
- package/dist/esm/handler/imap-stream.js +9 -8
- package/dist/esm/handler/limits.d.ts +1 -1
- package/dist/esm/handler/limits.js +5 -7
- package/dist/esm/handler/parser-instance.js +23 -38
- package/dist/esm/handler/token-parser.d.ts +12 -0
- package/dist/esm/handler/token-parser.js +44 -104
- package/dist/esm/imap-flow.d.ts +4 -3
- package/dist/esm/imap-flow.js +73 -73
- package/dist/esm/package-info.d.ts +1 -1
- package/dist/esm/package-info.js +1 -1
- package/dist/esm/proxy-connection.js +2 -5
- package/dist/esm/search-compiler.js +2 -3
- package/dist/esm/tools.d.ts +2 -2
- package/dist/esm/tools.js +9 -12
- package/package.json +6 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint new-cap: 0 */
|
|
2
2
|
import imapFormalSyntax from './imap-formal-syntax.js';
|
|
3
3
|
import { MAX_LITERAL_SIZE, ERROR_CONTEXT_LENGTH, boundedInput, normalizeLimit, createLiteralTooLargeError } from './limits.js';
|
|
4
|
+
import { createImapError } from '../errors.js';
|
|
4
5
|
const STATE_ATOM = 0x001;
|
|
5
6
|
const STATE_LITERAL = 0x002;
|
|
6
7
|
const STATE_NORMAL = 0x003;
|
|
@@ -42,6 +43,23 @@ export class TokenParser {
|
|
|
42
43
|
this.currentNode.type = 'TREE';
|
|
43
44
|
this.state = STATE_NORMAL;
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Builds a numbered parser error that carries a bounded copy of the input and the position
|
|
48
|
+
* (and character, when there is one) where parsing failed.
|
|
49
|
+
*
|
|
50
|
+
* @param message - The error message
|
|
51
|
+
* @param code - The numbered parser error code
|
|
52
|
+
* @param pos - Position of the failure in the original input
|
|
53
|
+
* @param chr - The offending character
|
|
54
|
+
* @returns The error to throw
|
|
55
|
+
*/
|
|
56
|
+
parserError(message, code, pos, chr) {
|
|
57
|
+
const parserContext = { ...boundedInput(this.str), pos };
|
|
58
|
+
if (chr !== undefined) {
|
|
59
|
+
parserContext.chr = chr;
|
|
60
|
+
}
|
|
61
|
+
return createImapError(message, code, { parserContext });
|
|
62
|
+
}
|
|
45
63
|
/**
|
|
46
64
|
* Processes the input string and returns the parsed attributes as a flat array of typed objects.
|
|
47
65
|
* Each attribute is an object with a `type` (e.g., "ATOM", "STRING", "LITERAL", "SEQUENCE")
|
|
@@ -65,10 +83,7 @@ export class TokenParser {
|
|
|
65
83
|
}
|
|
66
84
|
// If the node was never closed, throw it
|
|
67
85
|
if (!node.isClosed) {
|
|
68
|
-
|
|
69
|
-
error.code = 'ParserError9';
|
|
70
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + this.str.length - 1 };
|
|
71
|
-
throw error;
|
|
86
|
+
throw this.parserError(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E9]`, 'ParserError9', this.pos + this.str.length - 1);
|
|
72
87
|
}
|
|
73
88
|
let type = (node.type || '').toString().toUpperCase();
|
|
74
89
|
switch (type) {
|
|
@@ -139,11 +154,8 @@ export class TokenParser {
|
|
|
139
154
|
node.depth = 0;
|
|
140
155
|
}
|
|
141
156
|
if (node.depth > MAX_NODE_DEPTH) {
|
|
142
|
-
let error = new Error('Too much nesting in IMAP string');
|
|
143
|
-
error.code = 'MAX_IMAP_NESTING_REACHED';
|
|
144
157
|
// A bounded prefix only, the error travels whole into logs and rejections
|
|
145
|
-
|
|
146
|
-
throw error;
|
|
158
|
+
throw createImapError('Too much nesting in IMAP string', 'MAX_IMAP_NESTING_REACHED', { _imapStr: this.str.slice(0, ERROR_CONTEXT_LENGTH) });
|
|
147
159
|
}
|
|
148
160
|
if (typeof startPos === 'number') {
|
|
149
161
|
node.startPos = startPos;
|
|
@@ -219,10 +231,7 @@ export class TokenParser {
|
|
|
219
231
|
// error instead of reading a missing buffer or shifting every later literal by one
|
|
220
232
|
const takeLiteral = (literals) => {
|
|
221
233
|
if (!literals.length) {
|
|
222
|
-
|
|
223
|
-
error.code = 'ParserError35';
|
|
224
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
225
|
-
throw error;
|
|
234
|
+
throw this.parserError(`Literal without data at position ${this.pos + i} [E35]`, 'ParserError35', this.pos + i, chr);
|
|
226
235
|
}
|
|
227
236
|
return literals.shift();
|
|
228
237
|
};
|
|
@@ -234,10 +243,7 @@ export class TokenParser {
|
|
|
234
243
|
// used to fall through into the default branch
|
|
235
244
|
const startAtom = () => {
|
|
236
245
|
if (!imapFormalSyntax['ATOM-CHAR']().includes(chr) && chr !== '\\' && chr !== '%' && chr.charCodeAt(0) < 0x80) {
|
|
237
|
-
|
|
238
|
-
error.code = 'ParserError13';
|
|
239
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
240
|
-
throw error;
|
|
246
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`, 'ParserError13', this.pos + i, chr);
|
|
241
247
|
}
|
|
242
248
|
this.currentNode = this.createNode(this.currentNode, this.pos + i);
|
|
243
249
|
this.currentNode.type = 'ATOM';
|
|
@@ -265,10 +271,7 @@ export class TokenParser {
|
|
|
265
271
|
// ) closes a list
|
|
266
272
|
case ')':
|
|
267
273
|
if (this.currentNode.type !== 'LIST') {
|
|
268
|
-
|
|
269
|
-
error.code = 'ParserError10';
|
|
270
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
271
|
-
throw error;
|
|
274
|
+
throw this.parserError(`Unexpected list terminator ) at position ${this.pos + i} [E10]`, 'ParserError10', this.pos + i, chr);
|
|
272
275
|
}
|
|
273
276
|
this.currentNode.isClosed = true;
|
|
274
277
|
this.currentNode.endPos = this.pos + i;
|
|
@@ -278,10 +281,7 @@ export class TokenParser {
|
|
|
278
281
|
// ] closes section group
|
|
279
282
|
case ']':
|
|
280
283
|
if (this.currentNode.type !== 'SECTION') {
|
|
281
|
-
|
|
282
|
-
error.code = 'ParserError11';
|
|
283
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
284
|
-
throw error;
|
|
284
|
+
throw this.parserError(`Unexpected section terminator ] at position ${this.pos + i} [E11]`, 'ParserError11', this.pos + i, chr);
|
|
285
285
|
}
|
|
286
286
|
this.currentNode.isClosed = true;
|
|
287
287
|
this.currentNode.endPos = this.pos + i;
|
|
@@ -322,10 +322,7 @@ export class TokenParser {
|
|
|
322
322
|
startAtom();
|
|
323
323
|
break;
|
|
324
324
|
}
|
|
325
|
-
|
|
326
|
-
error.code = 'ParserError12';
|
|
327
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
328
|
-
throw error;
|
|
325
|
+
throw this.parserError(`Unexpected literal8 marker at position ${this.pos + i} [E12]`, 'ParserError12', this.pos + i, chr);
|
|
329
326
|
}
|
|
330
327
|
// Mark the next literal as literal8 type; consumed when '{' is encountered
|
|
331
328
|
this.expectedLiteralType = 'literal8';
|
|
@@ -485,16 +482,10 @@ export class TokenParser {
|
|
|
485
482
|
chr !== ']' &&
|
|
486
483
|
!(chr === '*' && this.currentNode.value === '\\') &&
|
|
487
484
|
(!this.parent || !this.parent.command || !['NO', 'BAD', 'OK'].includes(this.parent.command.toUpperCase()))) {
|
|
488
|
-
|
|
489
|
-
error.code = 'ParserError16';
|
|
490
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
491
|
-
throw error;
|
|
485
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E16: ${JSON.stringify(chr)}]`, 'ParserError16', this.pos + i, chr);
|
|
492
486
|
}
|
|
493
487
|
else if (this.currentNode.value === '\\*') {
|
|
494
|
-
|
|
495
|
-
error.code = 'ParserError17';
|
|
496
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
497
|
-
throw error;
|
|
488
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E17: ${JSON.stringify(chr)}]`, 'ParserError17', this.pos + i, chr);
|
|
498
489
|
}
|
|
499
490
|
appendToToken(chr);
|
|
500
491
|
break;
|
|
@@ -512,10 +503,7 @@ export class TokenParser {
|
|
|
512
503
|
if (chr === '\\') {
|
|
513
504
|
i++;
|
|
514
505
|
if (i >= len) {
|
|
515
|
-
|
|
516
|
-
error.code = 'ParserError18';
|
|
517
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i };
|
|
518
|
-
throw error;
|
|
506
|
+
throw this.parserError(`Unexpected end of input at position ${this.pos + i} [E18]`, 'ParserError18', this.pos + i);
|
|
519
507
|
}
|
|
520
508
|
chr = this.str.charAt(i);
|
|
521
509
|
}
|
|
@@ -524,10 +512,7 @@ export class TokenParser {
|
|
|
524
512
|
case STATE_PARTIAL:
|
|
525
513
|
if (chr === '>') {
|
|
526
514
|
if (tokenLast === '.') {
|
|
527
|
-
|
|
528
|
-
error.code = 'ParserError19';
|
|
529
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
530
|
-
throw error;
|
|
515
|
+
throw this.parserError(`Unexpected end of partial at position ${this.pos + i} [E19]`, 'ParserError19', this.pos + i, chr);
|
|
531
516
|
}
|
|
532
517
|
this.currentNode.endPos = this.pos + i;
|
|
533
518
|
this.currentNode.isClosed = true;
|
|
@@ -537,22 +522,13 @@ export class TokenParser {
|
|
|
537
522
|
break;
|
|
538
523
|
}
|
|
539
524
|
if (chr === '.' && (!tokenLength || tokenHasDot)) {
|
|
540
|
-
|
|
541
|
-
error.code = 'ParserError20';
|
|
542
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
543
|
-
throw error;
|
|
525
|
+
throw this.parserError(`Unexpected partial separator . at position ${this.pos + i} [E20]`, 'ParserError20', this.pos + i, chr);
|
|
544
526
|
}
|
|
545
527
|
if (!imapFormalSyntax.DIGIT().includes(chr) && chr !== '.') {
|
|
546
|
-
|
|
547
|
-
error.code = 'ParserError21';
|
|
548
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
549
|
-
throw error;
|
|
528
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`, 'ParserError21', this.pos + i, chr);
|
|
550
529
|
}
|
|
551
530
|
if (tokenLast === '0' && (tokenLength === 1 || tokenPrev === '.') && chr !== '.') {
|
|
552
|
-
|
|
553
|
-
error.code = 'ParserError22';
|
|
554
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
555
|
-
throw error;
|
|
531
|
+
throw this.parserError(`Invalid partial at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`, 'ParserError22', this.pos + i, chr);
|
|
556
532
|
}
|
|
557
533
|
appendToToken(chr);
|
|
558
534
|
break;
|
|
@@ -584,10 +560,7 @@ export class TokenParser {
|
|
|
584
560
|
}
|
|
585
561
|
if (chr === '}') {
|
|
586
562
|
if (!('literalLength' in this.currentNode)) {
|
|
587
|
-
|
|
588
|
-
error.code = 'ParserError23';
|
|
589
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
590
|
-
throw error;
|
|
563
|
+
throw this.parserError(`Unexpected literal prefix end char } at position ${this.pos + i} [E23]`, 'ParserError23', this.pos + i, chr);
|
|
591
564
|
}
|
|
592
565
|
if (this.str.charAt(i + 1) === '\n') {
|
|
593
566
|
i++;
|
|
@@ -596,10 +569,7 @@ export class TokenParser {
|
|
|
596
569
|
i += 2;
|
|
597
570
|
}
|
|
598
571
|
else {
|
|
599
|
-
|
|
600
|
-
error.code = 'ParserError24';
|
|
601
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
602
|
-
throw error;
|
|
572
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E24: ${JSON.stringify(chr)}]`, 'ParserError24', this.pos + i, chr);
|
|
603
573
|
}
|
|
604
574
|
this.currentNode.literalLength = Number(this.currentNode.literalLength);
|
|
605
575
|
if (!this.currentNode.literalLength) {
|
|
@@ -660,16 +630,10 @@ export class TokenParser {
|
|
|
660
630
|
break;
|
|
661
631
|
}
|
|
662
632
|
if (!imapFormalSyntax.DIGIT().includes(chr)) {
|
|
663
|
-
|
|
664
|
-
error.code = 'ParserError25';
|
|
665
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
666
|
-
throw error;
|
|
633
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E25: ${JSON.stringify(chr)}]`, 'ParserError25', this.pos + i, chr);
|
|
667
634
|
}
|
|
668
635
|
if (this.currentNode.literalLength === '0') {
|
|
669
|
-
|
|
670
|
-
error.code = 'ParserError26';
|
|
671
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
672
|
-
throw error;
|
|
636
|
+
throw this.parserError(`Invalid literal at position ${this.pos + i} [E26]`, 'ParserError26', this.pos + i, chr);
|
|
673
637
|
}
|
|
674
638
|
this.currentNode.literalLength = (this.currentNode.literalLength || '') + chr;
|
|
675
639
|
break;
|
|
@@ -684,16 +648,10 @@ export class TokenParser {
|
|
|
684
648
|
continueAsAtom();
|
|
685
649
|
break;
|
|
686
650
|
}
|
|
687
|
-
|
|
688
|
-
error.code = 'ParserError27';
|
|
689
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
690
|
-
throw error;
|
|
651
|
+
throw this.parserError(`Unexpected end of sequence at position ${this.pos + i} [E27: ${JSON.stringify(chr)}]`, 'ParserError27', this.pos + i, chr);
|
|
691
652
|
}
|
|
692
653
|
if (this.currentNode.value !== '*' && tokenLast === '*' && tokenPrev !== ':') {
|
|
693
|
-
|
|
694
|
-
error.code = 'ParserError28';
|
|
695
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
696
|
-
throw error;
|
|
654
|
+
throw this.parserError(`Unexpected end of sequence at position ${this.pos + i} [E28: ${JSON.stringify(chr)}]`, 'ParserError28', this.pos + i, chr);
|
|
697
655
|
}
|
|
698
656
|
this.currentNode.isClosed = true;
|
|
699
657
|
this.currentNode.endPos = this.pos + i - 1;
|
|
@@ -713,18 +671,12 @@ export class TokenParser {
|
|
|
713
671
|
continueAsAtom();
|
|
714
672
|
break;
|
|
715
673
|
}
|
|
716
|
-
|
|
717
|
-
error.code = 'ParserError29';
|
|
718
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
719
|
-
throw error;
|
|
674
|
+
throw this.parserError(`Unexpected range separator : at position ${this.pos + i} [E29]`, 'ParserError29', this.pos + i, chr);
|
|
720
675
|
}
|
|
721
676
|
}
|
|
722
677
|
else if (chr === '*') {
|
|
723
678
|
if (![',', ':'].includes(tokenLast)) {
|
|
724
|
-
|
|
725
|
-
error.code = 'ParserError30';
|
|
726
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
727
|
-
throw error;
|
|
679
|
+
throw this.parserError(`Unexpected range wildcard at position ${this.pos + i} [E30]`, 'ParserError30', this.pos + i, chr);
|
|
728
680
|
}
|
|
729
681
|
}
|
|
730
682
|
else if (chr === ',') {
|
|
@@ -733,16 +685,10 @@ export class TokenParser {
|
|
|
733
685
|
continueAsAtom();
|
|
734
686
|
break;
|
|
735
687
|
}
|
|
736
|
-
|
|
737
|
-
error.code = 'ParserError31';
|
|
738
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
739
|
-
throw error;
|
|
688
|
+
throw this.parserError(`Unexpected sequence separator , at position ${this.pos + i} [E31]`, 'ParserError31', this.pos + i, chr);
|
|
740
689
|
}
|
|
741
690
|
if (tokenLast === '*' && tokenPrev !== ':') {
|
|
742
|
-
|
|
743
|
-
error.code = 'ParserError32';
|
|
744
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
745
|
-
throw error;
|
|
691
|
+
throw this.parserError(`Unexpected sequence separator , at position ${this.pos + i} [E32]`, 'ParserError32', this.pos + i, chr);
|
|
746
692
|
}
|
|
747
693
|
}
|
|
748
694
|
else if (!RE_SINGLE_DIGIT.test(chr)) {
|
|
@@ -750,16 +696,10 @@ export class TokenParser {
|
|
|
750
696
|
continueAsAtom();
|
|
751
697
|
break;
|
|
752
698
|
}
|
|
753
|
-
|
|
754
|
-
error.code = 'ParserError33';
|
|
755
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
756
|
-
throw error;
|
|
699
|
+
throw this.parserError(`Unexpected char at position ${this.pos + i} [E33: ${JSON.stringify(chr)}]`, 'ParserError33', this.pos + i, chr);
|
|
757
700
|
}
|
|
758
701
|
if (RE_SINGLE_DIGIT.test(chr) && tokenLast === '*') {
|
|
759
|
-
|
|
760
|
-
error.code = 'ParserError34';
|
|
761
|
-
error.parserContext = { ...boundedInput(this.str), pos: this.pos + i, chr };
|
|
762
|
-
throw error;
|
|
702
|
+
throw this.parserError(`Unexpected number at position ${this.pos + i} [E34: ${JSON.stringify(chr)}]`, 'ParserError34', this.pos + i, chr);
|
|
763
703
|
}
|
|
764
704
|
appendToToken(chr);
|
|
765
705
|
break;
|
package/dist/esm/imap-flow.d.ts
CHANGED
|
@@ -426,7 +426,7 @@ export declare class ImapFlow extends EventEmitter {
|
|
|
426
426
|
* Appends a new message to a mailbox
|
|
427
427
|
*
|
|
428
428
|
* @param path Mailbox path to upload the message to (unicode string). If value is an array then it is joined using current delimiter symbols. Namespace prefix is added automatically if required.
|
|
429
|
-
* @param content RFC822 formatted email message
|
|
429
|
+
* @param content RFC822 formatted email message, as a Buffer, Uint8Array or string
|
|
430
430
|
* @param flags an array of flags to be set for the uploaded message
|
|
431
431
|
* @param idate internal date to be set for the message
|
|
432
432
|
* @returns info about uploaded message
|
|
@@ -434,7 +434,7 @@ export declare class ImapFlow extends EventEmitter {
|
|
|
434
434
|
* @example
|
|
435
435
|
* await client.append('INBOX', rawMessageBuffer, ['\\Seen'], new Date(2000, 1, 1));
|
|
436
436
|
*/
|
|
437
|
-
append(path: string | string[], content: string | Buffer, flags?: string[] | undefined, idate?: Date | string | undefined): Promise<AppendResponseObject | false>;
|
|
437
|
+
append(path: string | string[], content: string | Buffer | Uint8Array, flags?: string[] | undefined, idate?: Date | string | undefined): Promise<AppendResponseObject | false>;
|
|
438
438
|
/**
|
|
439
439
|
* Copies messages from current mailbox to destination mailbox
|
|
440
440
|
*
|
|
@@ -562,7 +562,8 @@ export declare class ImapFlow extends EventEmitter {
|
|
|
562
562
|
* // download body part nr '1.2' from latest message
|
|
563
563
|
* let download = await client.download('*', '1.2');
|
|
564
564
|
* if (download.content) {
|
|
565
|
-
* download.
|
|
565
|
+
* // pipeline() rejects when the download fails, a plain .pipe() would not report it
|
|
566
|
+
* await stream.promises.pipeline(download.content, fs.createWriteStream(download.meta.filename));
|
|
566
567
|
* }
|
|
567
568
|
*/
|
|
568
569
|
download(range: SequenceString, part?: string | undefined, options?: DownloadOptions | undefined): Promise<DownloadObject | DownloadNotFound>;
|