imapflow 2.3.0 → 2.4.0

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 (56) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/commands/append.d.ts +1 -1
  3. package/dist/cjs/commands/append.js +15 -4
  4. package/dist/cjs/commands/compress.js +2 -2
  5. package/dist/cjs/commands/idle.js +2 -3
  6. package/dist/cjs/commands/status.js +2 -4
  7. package/dist/cjs/connection-deadline.d.ts +1 -1
  8. package/dist/cjs/connection-deadline.js +2 -4
  9. package/dist/cjs/download.js +22 -19
  10. package/dist/cjs/errors.d.ts +15 -0
  11. package/dist/cjs/errors.js +22 -0
  12. package/dist/cjs/handler/imap-compiler.d.ts +4 -4
  13. package/dist/cjs/handler/imap-compiler.js +18 -18
  14. package/dist/cjs/handler/imap-parser.js +28 -3
  15. package/dist/cjs/handler/imap-stream.js +9 -8
  16. package/dist/cjs/handler/limits.d.ts +1 -1
  17. package/dist/cjs/handler/limits.js +5 -7
  18. package/dist/cjs/handler/parser-instance.js +23 -38
  19. package/dist/cjs/handler/token-parser.d.ts +12 -0
  20. package/dist/cjs/handler/token-parser.js +44 -104
  21. package/dist/cjs/imap-flow.d.ts +4 -3
  22. package/dist/cjs/imap-flow.js +72 -72
  23. package/dist/cjs/package-info.d.ts +1 -1
  24. package/dist/cjs/package-info.js +1 -1
  25. package/dist/cjs/proxy-connection.js +2 -5
  26. package/dist/cjs/search-compiler.js +2 -3
  27. package/dist/cjs/tools.d.ts +2 -2
  28. package/dist/cjs/tools.js +8 -11
  29. package/dist/esm/commands/append.d.ts +1 -1
  30. package/dist/esm/commands/append.js +15 -4
  31. package/dist/esm/commands/compress.js +2 -2
  32. package/dist/esm/commands/idle.js +2 -3
  33. package/dist/esm/commands/status.js +2 -4
  34. package/dist/esm/connection-deadline.d.ts +1 -1
  35. package/dist/esm/connection-deadline.js +2 -4
  36. package/dist/esm/download.js +22 -19
  37. package/dist/esm/errors.d.ts +15 -0
  38. package/dist/esm/errors.js +21 -0
  39. package/dist/esm/handler/imap-compiler.d.ts +4 -4
  40. package/dist/esm/handler/imap-compiler.js +18 -18
  41. package/dist/esm/handler/imap-parser.js +28 -3
  42. package/dist/esm/handler/imap-stream.js +9 -8
  43. package/dist/esm/handler/limits.d.ts +1 -1
  44. package/dist/esm/handler/limits.js +5 -7
  45. package/dist/esm/handler/parser-instance.js +23 -38
  46. package/dist/esm/handler/token-parser.d.ts +12 -0
  47. package/dist/esm/handler/token-parser.js +44 -104
  48. package/dist/esm/imap-flow.d.ts +4 -3
  49. package/dist/esm/imap-flow.js +73 -73
  50. package/dist/esm/package-info.d.ts +1 -1
  51. package/dist/esm/package-info.js +1 -1
  52. package/dist/esm/proxy-connection.js +2 -5
  53. package/dist/esm/search-compiler.js +2 -3
  54. package/dist/esm/tools.d.ts +2 -2
  55. package/dist/esm/tools.js +9 -12
  56. package/package.json +3 -3
@@ -8,6 +8,7 @@ exports.ParserInstance = void 0;
8
8
  const imap_formal_syntax_js_1 = __importDefault(require("./imap-formal-syntax.js"));
9
9
  const token_parser_js_1 = require("./token-parser.js");
10
10
  const limits_js_1 = require("./limits.js");
11
+ const errors_js_1 = require("../errors.js");
11
12
  /**
12
13
  * Parses a single IMAP response line into its structural components: tag, command,
13
14
  * and attributes. Handles status responses (OK, NO, BAD, PREAUTH, BYE) with their
@@ -143,10 +144,7 @@ class ParserInstance {
143
144
  async getElement(syntax) {
144
145
  let match, element, errPos;
145
146
  if (/^\s/.test(this.remainder)) {
146
- let error = new Error(`Unexpected whitespace at position ${this.pos} [E1]`);
147
- error.code = 'ParserError1';
148
- error.parserContext = this.errorContext();
149
- throw error;
147
+ throw (0, errors_js_1.createImapError)(`Unexpected whitespace at position ${this.pos} [E1]`, 'ParserError1', { parserContext: this.errorContext() });
150
148
  }
151
149
  if ((match = this.remainder.match(/^\s*[^\s]+(?=\s|$)/))) {
152
150
  element = match[0];
@@ -156,29 +154,24 @@ class ParserInstance {
156
154
  // "Server Unavailable." instead of a proper IMAP tagged/untagged response.
157
155
  // We detect this specific pattern and convert it into a synthetic BAD response
158
156
  // so the rest of the parser can handle it gracefully.
159
- let error = new Error(`Server returned an error: ${this.input}`);
160
- error.code = 'ParserErrorExchange';
161
- error.parserContext = {
162
- ...this.errorContext(element),
163
- value: {
164
- tag: '*',
165
- command: 'BAD',
166
- attributes: [{ type: 'TEXT', value: this.input }]
157
+ throw (0, errors_js_1.createImapError)(`Server returned an error: ${this.input}`, 'ParserErrorExchange', {
158
+ parserContext: {
159
+ ...this.errorContext(element),
160
+ value: {
161
+ tag: '*',
162
+ command: 'BAD',
163
+ attributes: [{ type: 'TEXT', value: this.input }]
164
+ }
167
165
  }
168
- };
169
- throw error;
166
+ });
170
167
  }
171
- let error = new Error(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`);
172
- error.code = 'ParserError2';
173
- error.parserContext = this.errorContext(element);
174
- throw error;
168
+ throw (0, errors_js_1.createImapError)(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`, 'ParserError2', {
169
+ parserContext: this.errorContext(element)
170
+ });
175
171
  }
176
172
  }
177
173
  else {
178
- let error = new Error(`Unexpected end of input at position ${this.pos} [E3]`);
179
- error.code = 'ParserError3';
180
- error.parserContext = this.errorContext();
181
- throw error;
174
+ throw (0, errors_js_1.createImapError)(`Unexpected end of input at position ${this.pos} [E3]`, 'ParserError3', { parserContext: this.errorContext() });
182
175
  }
183
176
  this.pos += match[0].length;
184
177
  this.remainder = this.remainder.slice(match[0].length);
@@ -196,16 +189,12 @@ class ParserInstance {
196
189
  // special case, empty + response
197
190
  return;
198
191
  }
199
- let error = new Error(`Unexpected end of input at position ${this.pos} [E4]`);
200
- error.code = 'ParserError4';
201
- error.parserContext = this.errorContext();
202
- throw error;
192
+ throw (0, errors_js_1.createImapError)(`Unexpected end of input at position ${this.pos} [E4]`, 'ParserError4', { parserContext: this.errorContext() });
203
193
  }
204
194
  if (imap_formal_syntax_js_1.default.verify(this.remainder.charAt(0), imap_formal_syntax_js_1.default.SP()) >= 0) {
205
- let error = new Error(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`);
206
- error.code = 'ParserError5';
207
- error.parserContext = this.errorContext(this.remainder);
208
- throw error;
195
+ throw (0, errors_js_1.createImapError)(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`, 'ParserError5', {
196
+ parserContext: this.errorContext(this.remainder)
197
+ });
209
198
  }
210
199
  this.pos++;
211
200
  this.remainder = this.remainder.slice(1);
@@ -220,16 +209,12 @@ class ParserInstance {
220
209
  */
221
210
  async getAttributes() {
222
211
  if (!this.remainder.length) {
223
- let error = new Error(`Unexpected end of input at position ${this.pos} [E6]`);
224
- error.code = 'ParserError6';
225
- error.parserContext = this.errorContext();
226
- throw error;
212
+ throw (0, errors_js_1.createImapError)(`Unexpected end of input at position ${this.pos} [E6]`, 'ParserError6', { parserContext: this.errorContext() });
227
213
  }
228
214
  if (/^\s/.test(this.remainder)) {
229
- let error = new Error(`Unexpected whitespace at position ${this.pos} [E7]`);
230
- error.code = 'ParserError7';
231
- error.parserContext = this.errorContext(this.remainder);
232
- throw error;
215
+ throw (0, errors_js_1.createImapError)(`Unexpected whitespace at position ${this.pos} [E7]`, 'ParserError7', {
216
+ parserContext: this.errorContext(this.remainder)
217
+ });
233
218
  }
234
219
  const tokenParser = new token_parser_js_1.TokenParser(this, this.pos, this.remainder, this.options);
235
220
  return await tokenParser.getAttributes();
@@ -1,3 +1,4 @@
1
+ import { type ImapFlowError, type ParserErrorCode } from '../errors.js';
1
2
  import type { ImapAttributeList, ParserOptions } from './types.js';
2
3
  import type { ParserInstance } from './parser-instance.js';
3
4
  /**
@@ -58,6 +59,17 @@ export declare class TokenParser {
58
59
  * from the input, i.e. when no pre-parsed literal buffers were supplied. Defaults to 1GB.
59
60
  */
60
61
  constructor(parent: TokenParserParent | ParserInstance, startPos?: number | undefined, str?: string | null | undefined, options?: ParserOptions | undefined);
62
+ /**
63
+ * Builds a numbered parser error that carries a bounded copy of the input and the position
64
+ * (and character, when there is one) where parsing failed.
65
+ *
66
+ * @param message - The error message
67
+ * @param code - The numbered parser error code
68
+ * @param pos - Position of the failure in the original input
69
+ * @param chr - The offending character
70
+ * @returns The error to throw
71
+ */
72
+ parserError(message: string, code: ParserErrorCode, pos: number, chr?: string | undefined): ImapFlowError;
61
73
  /**
62
74
  * Processes the input string and returns the parsed attributes as a flat array of typed objects.
63
75
  * Each attribute is an object with a `type` (e.g., "ATOM", "STRING", "LITERAL", "SEQUENCE")
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.TokenParser = void 0;
8
8
  const imap_formal_syntax_js_1 = __importDefault(require("./imap-formal-syntax.js"));
9
9
  const limits_js_1 = require("./limits.js");
10
+ const errors_js_1 = require("../errors.js");
10
11
  const STATE_ATOM = 0x001;
11
12
  const STATE_LITERAL = 0x002;
12
13
  const STATE_NORMAL = 0x003;
@@ -48,6 +49,23 @@ class TokenParser {
48
49
  this.currentNode.type = 'TREE';
49
50
  this.state = STATE_NORMAL;
50
51
  }
52
+ /**
53
+ * Builds a numbered parser error that carries a bounded copy of the input and the position
54
+ * (and character, when there is one) where parsing failed.
55
+ *
56
+ * @param message - The error message
57
+ * @param code - The numbered parser error code
58
+ * @param pos - Position of the failure in the original input
59
+ * @param chr - The offending character
60
+ * @returns The error to throw
61
+ */
62
+ parserError(message, code, pos, chr) {
63
+ const parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos };
64
+ if (chr !== undefined) {
65
+ parserContext.chr = chr;
66
+ }
67
+ return (0, errors_js_1.createImapError)(message, code, { parserContext });
68
+ }
51
69
  /**
52
70
  * Processes the input string and returns the parsed attributes as a flat array of typed objects.
53
71
  * Each attribute is an object with a `type` (e.g., "ATOM", "STRING", "LITERAL", "SEQUENCE")
@@ -71,10 +89,7 @@ class TokenParser {
71
89
  }
72
90
  // If the node was never closed, throw it
73
91
  if (!node.isClosed) {
74
- let error = new Error(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E9]`);
75
- error.code = 'ParserError9';
76
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + this.str.length - 1 };
77
- throw error;
92
+ throw this.parserError(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E9]`, 'ParserError9', this.pos + this.str.length - 1);
78
93
  }
79
94
  let type = (node.type || '').toString().toUpperCase();
80
95
  switch (type) {
@@ -145,11 +160,8 @@ class TokenParser {
145
160
  node.depth = 0;
146
161
  }
147
162
  if (node.depth > MAX_NODE_DEPTH) {
148
- let error = new Error('Too much nesting in IMAP string');
149
- error.code = 'MAX_IMAP_NESTING_REACHED';
150
163
  // A bounded prefix only, the error travels whole into logs and rejections
151
- error._imapStr = this.str.slice(0, limits_js_1.ERROR_CONTEXT_LENGTH);
152
- throw error;
164
+ throw (0, errors_js_1.createImapError)('Too much nesting in IMAP string', 'MAX_IMAP_NESTING_REACHED', { _imapStr: this.str.slice(0, limits_js_1.ERROR_CONTEXT_LENGTH) });
153
165
  }
154
166
  if (typeof startPos === 'number') {
155
167
  node.startPos = startPos;
@@ -225,10 +237,7 @@ class TokenParser {
225
237
  // error instead of reading a missing buffer or shifting every later literal by one
226
238
  const takeLiteral = (literals) => {
227
239
  if (!literals.length) {
228
- let error = new Error(`Literal without data at position ${this.pos + i} [E35]`);
229
- error.code = 'ParserError35';
230
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
231
- throw error;
240
+ throw this.parserError(`Literal without data at position ${this.pos + i} [E35]`, 'ParserError35', this.pos + i, chr);
232
241
  }
233
242
  return literals.shift();
234
243
  };
@@ -240,10 +249,7 @@ class TokenParser {
240
249
  // used to fall through into the default branch
241
250
  const startAtom = () => {
242
251
  if (!imap_formal_syntax_js_1.default['ATOM-CHAR']().includes(chr) && chr !== '\\' && chr !== '%' && chr.charCodeAt(0) < 0x80) {
243
- let error = new Error(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`);
244
- error.code = 'ParserError13';
245
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
246
- throw error;
252
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`, 'ParserError13', this.pos + i, chr);
247
253
  }
248
254
  this.currentNode = this.createNode(this.currentNode, this.pos + i);
249
255
  this.currentNode.type = 'ATOM';
@@ -271,10 +277,7 @@ class TokenParser {
271
277
  // ) closes a list
272
278
  case ')':
273
279
  if (this.currentNode.type !== 'LIST') {
274
- let error = new Error(`Unexpected list terminator ) at position ${this.pos + i} [E10]`);
275
- error.code = 'ParserError10';
276
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
277
- throw error;
280
+ throw this.parserError(`Unexpected list terminator ) at position ${this.pos + i} [E10]`, 'ParserError10', this.pos + i, chr);
278
281
  }
279
282
  this.currentNode.isClosed = true;
280
283
  this.currentNode.endPos = this.pos + i;
@@ -284,10 +287,7 @@ class TokenParser {
284
287
  // ] closes section group
285
288
  case ']':
286
289
  if (this.currentNode.type !== 'SECTION') {
287
- let error = new Error(`Unexpected section terminator ] at position ${this.pos + i} [E11]`);
288
- error.code = 'ParserError11';
289
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
290
- throw error;
290
+ throw this.parserError(`Unexpected section terminator ] at position ${this.pos + i} [E11]`, 'ParserError11', this.pos + i, chr);
291
291
  }
292
292
  this.currentNode.isClosed = true;
293
293
  this.currentNode.endPos = this.pos + i;
@@ -328,10 +328,7 @@ class TokenParser {
328
328
  startAtom();
329
329
  break;
330
330
  }
331
- let error = new Error(`Unexpected literal8 marker at position ${this.pos + i} [E12]`);
332
- error.code = 'ParserError12';
333
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
334
- throw error;
331
+ throw this.parserError(`Unexpected literal8 marker at position ${this.pos + i} [E12]`, 'ParserError12', this.pos + i, chr);
335
332
  }
336
333
  // Mark the next literal as literal8 type; consumed when '{' is encountered
337
334
  this.expectedLiteralType = 'literal8';
@@ -491,16 +488,10 @@ class TokenParser {
491
488
  chr !== ']' &&
492
489
  !(chr === '*' && this.currentNode.value === '\\') &&
493
490
  (!this.parent || !this.parent.command || !['NO', 'BAD', 'OK'].includes(this.parent.command.toUpperCase()))) {
494
- let error = new Error(`Unexpected char at position ${this.pos + i} [E16: ${JSON.stringify(chr)}]`);
495
- error.code = 'ParserError16';
496
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
497
- throw error;
491
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E16: ${JSON.stringify(chr)}]`, 'ParserError16', this.pos + i, chr);
498
492
  }
499
493
  else if (this.currentNode.value === '\\*') {
500
- let error = new Error(`Unexpected char at position ${this.pos + i} [E17: ${JSON.stringify(chr)}]`);
501
- error.code = 'ParserError17';
502
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
503
- throw error;
494
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E17: ${JSON.stringify(chr)}]`, 'ParserError17', this.pos + i, chr);
504
495
  }
505
496
  appendToToken(chr);
506
497
  break;
@@ -518,10 +509,7 @@ class TokenParser {
518
509
  if (chr === '\\') {
519
510
  i++;
520
511
  if (i >= len) {
521
- let error = new Error(`Unexpected end of input at position ${this.pos + i} [E18]`);
522
- error.code = 'ParserError18';
523
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i };
524
- throw error;
512
+ throw this.parserError(`Unexpected end of input at position ${this.pos + i} [E18]`, 'ParserError18', this.pos + i);
525
513
  }
526
514
  chr = this.str.charAt(i);
527
515
  }
@@ -530,10 +518,7 @@ class TokenParser {
530
518
  case STATE_PARTIAL:
531
519
  if (chr === '>') {
532
520
  if (tokenLast === '.') {
533
- let error = new Error(`Unexpected end of partial at position ${this.pos + i} [E19]`);
534
- error.code = 'ParserError19';
535
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
536
- throw error;
521
+ throw this.parserError(`Unexpected end of partial at position ${this.pos + i} [E19]`, 'ParserError19', this.pos + i, chr);
537
522
  }
538
523
  this.currentNode.endPos = this.pos + i;
539
524
  this.currentNode.isClosed = true;
@@ -543,22 +528,13 @@ class TokenParser {
543
528
  break;
544
529
  }
545
530
  if (chr === '.' && (!tokenLength || tokenHasDot)) {
546
- let error = new Error(`Unexpected partial separator . at position ${this.pos + i} [E20]`);
547
- error.code = 'ParserError20';
548
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
549
- throw error;
531
+ throw this.parserError(`Unexpected partial separator . at position ${this.pos + i} [E20]`, 'ParserError20', this.pos + i, chr);
550
532
  }
551
533
  if (!imap_formal_syntax_js_1.default.DIGIT().includes(chr) && chr !== '.') {
552
- let error = new Error(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`);
553
- error.code = 'ParserError21';
554
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
555
- throw error;
534
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`, 'ParserError21', this.pos + i, chr);
556
535
  }
557
536
  if (tokenLast === '0' && (tokenLength === 1 || tokenPrev === '.') && chr !== '.') {
558
- let error = new Error(`Invalid partial at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`);
559
- error.code = 'ParserError22';
560
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
561
- throw error;
537
+ throw this.parserError(`Invalid partial at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`, 'ParserError22', this.pos + i, chr);
562
538
  }
563
539
  appendToToken(chr);
564
540
  break;
@@ -590,10 +566,7 @@ class TokenParser {
590
566
  }
591
567
  if (chr === '}') {
592
568
  if (!('literalLength' in this.currentNode)) {
593
- let error = new Error(`Unexpected literal prefix end char } at position ${this.pos + i} [E23]`);
594
- error.code = 'ParserError23';
595
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
596
- throw error;
569
+ throw this.parserError(`Unexpected literal prefix end char } at position ${this.pos + i} [E23]`, 'ParserError23', this.pos + i, chr);
597
570
  }
598
571
  if (this.str.charAt(i + 1) === '\n') {
599
572
  i++;
@@ -602,10 +575,7 @@ class TokenParser {
602
575
  i += 2;
603
576
  }
604
577
  else {
605
- let error = new Error(`Unexpected char at position ${this.pos + i} [E24: ${JSON.stringify(chr)}]`);
606
- error.code = 'ParserError24';
607
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
608
- throw error;
578
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E24: ${JSON.stringify(chr)}]`, 'ParserError24', this.pos + i, chr);
609
579
  }
610
580
  this.currentNode.literalLength = Number(this.currentNode.literalLength);
611
581
  if (!this.currentNode.literalLength) {
@@ -666,16 +636,10 @@ class TokenParser {
666
636
  break;
667
637
  }
668
638
  if (!imap_formal_syntax_js_1.default.DIGIT().includes(chr)) {
669
- let error = new Error(`Unexpected char at position ${this.pos + i} [E25: ${JSON.stringify(chr)}]`);
670
- error.code = 'ParserError25';
671
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
672
- throw error;
639
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E25: ${JSON.stringify(chr)}]`, 'ParserError25', this.pos + i, chr);
673
640
  }
674
641
  if (this.currentNode.literalLength === '0') {
675
- let error = new Error(`Invalid literal at position ${this.pos + i} [E26]`);
676
- error.code = 'ParserError26';
677
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
678
- throw error;
642
+ throw this.parserError(`Invalid literal at position ${this.pos + i} [E26]`, 'ParserError26', this.pos + i, chr);
679
643
  }
680
644
  this.currentNode.literalLength = (this.currentNode.literalLength || '') + chr;
681
645
  break;
@@ -690,16 +654,10 @@ class TokenParser {
690
654
  continueAsAtom();
691
655
  break;
692
656
  }
693
- let error = new Error(`Unexpected end of sequence at position ${this.pos + i} [E27: ${JSON.stringify(chr)}]`);
694
- error.code = 'ParserError27';
695
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
696
- throw error;
657
+ throw this.parserError(`Unexpected end of sequence at position ${this.pos + i} [E27: ${JSON.stringify(chr)}]`, 'ParserError27', this.pos + i, chr);
697
658
  }
698
659
  if (this.currentNode.value !== '*' && tokenLast === '*' && tokenPrev !== ':') {
699
- let error = new Error(`Unexpected end of sequence at position ${this.pos + i} [E28: ${JSON.stringify(chr)}]`);
700
- error.code = 'ParserError28';
701
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
702
- throw error;
660
+ throw this.parserError(`Unexpected end of sequence at position ${this.pos + i} [E28: ${JSON.stringify(chr)}]`, 'ParserError28', this.pos + i, chr);
703
661
  }
704
662
  this.currentNode.isClosed = true;
705
663
  this.currentNode.endPos = this.pos + i - 1;
@@ -719,18 +677,12 @@ class TokenParser {
719
677
  continueAsAtom();
720
678
  break;
721
679
  }
722
- let error = new Error(`Unexpected range separator : at position ${this.pos + i} [E29]`);
723
- error.code = 'ParserError29';
724
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
725
- throw error;
680
+ throw this.parserError(`Unexpected range separator : at position ${this.pos + i} [E29]`, 'ParserError29', this.pos + i, chr);
726
681
  }
727
682
  }
728
683
  else if (chr === '*') {
729
684
  if (![',', ':'].includes(tokenLast)) {
730
- let error = new Error(`Unexpected range wildcard at position ${this.pos + i} [E30]`);
731
- error.code = 'ParserError30';
732
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
733
- throw error;
685
+ throw this.parserError(`Unexpected range wildcard at position ${this.pos + i} [E30]`, 'ParserError30', this.pos + i, chr);
734
686
  }
735
687
  }
736
688
  else if (chr === ',') {
@@ -739,16 +691,10 @@ class TokenParser {
739
691
  continueAsAtom();
740
692
  break;
741
693
  }
742
- let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E31]`);
743
- error.code = 'ParserError31';
744
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
745
- throw error;
694
+ throw this.parserError(`Unexpected sequence separator , at position ${this.pos + i} [E31]`, 'ParserError31', this.pos + i, chr);
746
695
  }
747
696
  if (tokenLast === '*' && tokenPrev !== ':') {
748
- let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E32]`);
749
- error.code = 'ParserError32';
750
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
751
- throw error;
697
+ throw this.parserError(`Unexpected sequence separator , at position ${this.pos + i} [E32]`, 'ParserError32', this.pos + i, chr);
752
698
  }
753
699
  }
754
700
  else if (!RE_SINGLE_DIGIT.test(chr)) {
@@ -756,16 +702,10 @@ class TokenParser {
756
702
  continueAsAtom();
757
703
  break;
758
704
  }
759
- let error = new Error(`Unexpected char at position ${this.pos + i} [E33: ${JSON.stringify(chr)}]`);
760
- error.code = 'ParserError33';
761
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
762
- throw error;
705
+ throw this.parserError(`Unexpected char at position ${this.pos + i} [E33: ${JSON.stringify(chr)}]`, 'ParserError33', this.pos + i, chr);
763
706
  }
764
707
  if (RE_SINGLE_DIGIT.test(chr) && tokenLast === '*') {
765
- let error = new Error(`Unexpected number at position ${this.pos + i} [E34: ${JSON.stringify(chr)}]`);
766
- error.code = 'ParserError34';
767
- error.parserContext = { ...(0, limits_js_1.boundedInput)(this.str), pos: this.pos + i, chr };
768
- throw error;
708
+ throw this.parserError(`Unexpected number at position ${this.pos + i} [E34: ${JSON.stringify(chr)}]`, 'ParserError34', this.pos + i, chr);
769
709
  }
770
710
  appendToToken(chr);
771
711
  break;
@@ -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.content.pipe(fs.createWriteStream(download.meta.filename));
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>;