imapflow 2.5.8 → 2.6.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 (43) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +9 -0
  3. package/dist/cjs/commands/append.js +6 -3
  4. package/dist/cjs/commands/fetch.d.ts +2 -1
  5. package/dist/cjs/commands/fetch.js +8 -2
  6. package/dist/cjs/commands/idle.js +7 -0
  7. package/dist/cjs/commands/select.js +17 -6
  8. package/dist/cjs/commands/status.js +19 -5
  9. package/dist/cjs/download.js +3 -3
  10. package/dist/cjs/errors.d.ts +3 -1
  11. package/dist/cjs/errors.js +4 -1
  12. package/dist/cjs/handler/imap-parser.js +38 -6
  13. package/dist/cjs/handler/limits.d.ts +1 -0
  14. package/dist/cjs/handler/limits.js +8 -1
  15. package/dist/cjs/handler/token-parser.d.ts +8 -2
  16. package/dist/cjs/handler/token-parser.js +55 -16
  17. package/dist/cjs/handler/types.d.ts +5 -2
  18. package/dist/cjs/imap-flow.d.ts +38 -2
  19. package/dist/cjs/imap-flow.js +99 -15
  20. package/dist/cjs/package-info.d.ts +1 -1
  21. package/dist/cjs/package-info.js +1 -1
  22. package/dist/cjs/types.d.ts +51 -7
  23. package/dist/esm/commands/append.js +6 -3
  24. package/dist/esm/commands/fetch.d.ts +2 -1
  25. package/dist/esm/commands/fetch.js +8 -2
  26. package/dist/esm/commands/idle.js +7 -0
  27. package/dist/esm/commands/select.js +17 -6
  28. package/dist/esm/commands/status.js +19 -5
  29. package/dist/esm/download.js +3 -3
  30. package/dist/esm/errors.d.ts +3 -1
  31. package/dist/esm/errors.js +4 -1
  32. package/dist/esm/handler/imap-parser.js +38 -6
  33. package/dist/esm/handler/limits.d.ts +1 -0
  34. package/dist/esm/handler/limits.js +7 -0
  35. package/dist/esm/handler/token-parser.d.ts +8 -2
  36. package/dist/esm/handler/token-parser.js +56 -17
  37. package/dist/esm/handler/types.d.ts +5 -2
  38. package/dist/esm/imap-flow.d.ts +38 -2
  39. package/dist/esm/imap-flow.js +99 -15
  40. package/dist/esm/package-info.d.ts +1 -1
  41. package/dist/esm/package-info.js +1 -1
  42. package/dist/esm/types.d.ts +51 -7
  43. package/package.json +3 -3
@@ -168,6 +168,18 @@ export class ImapFlow extends EventEmitter {
168
168
  * Current module version as a static class property
169
169
  */
170
170
  static { this.version = packageInfo.version; }
171
+ /**
172
+ * The mailboxes a `verifyOnly` connection with `includeMailboxes` listed before it logged out,
173
+ * `undefined` otherwise
174
+ *
175
+ * @example
176
+ * let client = new ImapFlow({ ..., verifyOnly: true, includeMailboxes: true });
177
+ * await client.connect();
178
+ * console.log(client.mailboxList.map(mailbox => mailbox.path));
179
+ */
180
+ get mailboxList() {
181
+ return this._mailboxList;
182
+ }
171
183
  /**
172
184
  * Creates a client for one IMAP connection. Nothing is sent before `connect()` is called
173
185
  */
@@ -219,6 +231,7 @@ export class ImapFlow extends EventEmitter {
219
231
  this._throttleWaits = new Set();
220
232
  this._upgradeReject = null;
221
233
  this.isClosed = false;
234
+ this._errorReported = false;
222
235
  this.states = states;
223
236
  this.state = this.states.NOT_AUTHENTICATED;
224
237
  this.lockCounter = 0;
@@ -243,6 +256,9 @@ export class ImapFlow extends EventEmitter {
243
256
  this.mailbox = false;
244
257
  this.currentSelectCommand = false;
245
258
  this.idling = false;
259
+ this.context = this.options.context;
260
+ this.connectedAt = null;
261
+ this.lastClientWrite = null;
246
262
  this.emitLogs = !!this.options.emitLogs;
247
263
  this.lo = 0;
248
264
  this.untaggedHandlers = {};
@@ -288,6 +304,15 @@ export class ImapFlow extends EventEmitter {
288
304
  return;
289
305
  }
290
306
  err._connId = err._connId || this.id;
307
+ // One error per connection: emitError() closes the connection, and until the deferred
308
+ // close() runs a second socket, deflate or parser error may still arrive. Emitting it as
309
+ // well would reach a consumer that removed its listener after the first one, or one that
310
+ // only awaited connect(), as an unhandled 'error' that throws.
311
+ if (this._errorReported) {
312
+ this.log.debug({ msg: 'Suppressed error after the connection already reported one', err, cid: this.id });
313
+ this.closeAfter();
314
+ return;
315
+ }
291
316
  // During a STARTTLS handshake the upgrade owns the single error path (its settle()
292
317
  // helper). Route the error there so a streamer-originated failure is surfaced with its
293
318
  // real code (instead of a generic ClosedAfterConnect*) and cannot hang a verifyOnly
@@ -298,6 +323,7 @@ export class ImapFlow extends EventEmitter {
298
323
  this._upgradeReject = null;
299
324
  if (typeof reject === 'function') {
300
325
  // settle() clears the upgrade timer and flags, and closes the connection
326
+ this._errorReported = true;
301
327
  reject(err);
302
328
  return;
303
329
  }
@@ -312,10 +338,12 @@ export class ImapFlow extends EventEmitter {
312
338
  let reject = this.initialReject;
313
339
  this.initialResolve = false;
314
340
  this.initialReject = false;
341
+ this._errorReported = true;
315
342
  this.closeAfter();
316
343
  reject(err);
317
344
  return;
318
345
  }
346
+ this._errorReported = true;
319
347
  this.closeAfter();
320
348
  this.emit('error', err);
321
349
  }
@@ -369,6 +397,7 @@ export class ImapFlow extends EventEmitter {
369
397
  else {
370
398
  return false;
371
399
  }
400
+ this.lastClientWrite = Date.now();
372
401
  for (let data of frames) {
373
402
  if (this.logRaw) {
374
403
  // Client frames of an authentication exchange carry credentials: the LOGIN
@@ -827,9 +856,17 @@ export class ImapFlow extends EventEmitter {
827
856
  async handleResponse(data) {
828
857
  let parsed;
829
858
  try {
830
- parsed = await parser(data.payload, { literals: data.literals });
859
+ parsed = await parser(data.payload, { literals: data.literals, maxResponseTokens: this.options.maxResponseTokens });
831
860
  }
832
861
  catch (err) {
862
+ if (err.code === 'TooManyTokens') {
863
+ // A size limit, so as terminal as the ones ImapStream enforces: the server is
864
+ // flooding responses, and skipping the line would only invite the next one
865
+ this.log.error({ msg: 'Response exceeded the token limit', payloadBytes: data.payload.length, err, cid: this.id });
866
+ this.rejectCurrentRequest(err);
867
+ this.failProtocol(err);
868
+ return false;
869
+ }
833
870
  // can not make sense of this. The payload can be up to the configured line
834
871
  // cap (1GB by default), so log only a bounded prefix: a server looping
835
872
  // unparseable garbage would otherwise turn this error log into a disk filler.
@@ -1251,7 +1288,9 @@ export class ImapFlow extends EventEmitter {
1251
1288
  }
1252
1289
  });
1253
1290
  const socket = this.socket;
1254
- socket.once('error', this._socketError);
1291
+ // on(), not once(): with compression the deflate and writeSocket errors are forwarded
1292
+ // onto this socket, and a second one before close() must not find it without a listener
1293
+ socket.on('error', this._socketError);
1255
1294
  socket.once('close', this._socketClose);
1256
1295
  socket.once('end', this._socketEnd);
1257
1296
  socket.on('tlsClientError', this._socketError);
@@ -2230,6 +2269,7 @@ export class ImapFlow extends EventEmitter {
2230
2269
  }
2231
2270
  try {
2232
2271
  clearTimer(this.connectTimeout);
2272
+ this.connectedAt = Date.now();
2233
2273
  // ImapFlow now owns the socket; drop the proxy's early error handler
2234
2274
  // (its "before connection setup" message no longer applies).
2235
2275
  detachEarlyErrorHandler(socket);
@@ -2355,6 +2395,15 @@ export class ImapFlow extends EventEmitter {
2355
2395
  }
2356
2396
  return error;
2357
2397
  }
2398
+ // What a message command called without a selected mailbox rejects with: NoMailboxSelected,
2399
+ // or NoConnection once the connection is gone, as that is why the mailbox is missing then
2400
+ /** @internal */
2401
+ createNoMailboxError(command) {
2402
+ if (!this.usable) {
2403
+ return this.createNoConnectionError(this.byeReason, { rejectedFrom: 'noMailbox', command });
2404
+ }
2405
+ return createImapError('No mailbox is selected', 'NoMailboxSelected', { command });
2406
+ }
2358
2407
  /**
2359
2408
  * Closes TCP connection without notifying the server.
2360
2409
  *
@@ -2795,8 +2844,14 @@ export class ImapFlow extends EventEmitter {
2795
2844
  // LIST. This sets mailboxMissing on the error so the caller can distinguish
2796
2845
  // "doesn't exist" from other failures, for getMailboxLock() callers as well.
2797
2846
  try {
2798
- let folders = await this.run('LIST', '', normalizePath(this, path), { listOnly: true });
2799
- if (!folders || !folders.length) {
2847
+ let normalized = normalizePath(this, path);
2848
+ let folders = await this.run('LIST', '', normalized, { listOnly: true });
2849
+ // The path is the LIST pattern, so a % or * in a name also matches other
2850
+ // mailboxes, and an entry marked \NonExistent (RFC 5258) does not exist either
2851
+ let exists = Array.isArray(folders) &&
2852
+ folders.some(entry => comparePaths(this, entry.path, normalized) &&
2853
+ ![...(entry.flags || [])].some(flag => typeof flag === 'string' && flag.toUpperCase() === '\\NONEXISTENT'));
2854
+ if (!exists) {
2800
2855
  err.mailboxMissing = true;
2801
2856
  }
2802
2857
  }
@@ -2839,6 +2894,9 @@ export class ImapFlow extends EventEmitter {
2839
2894
  * otherwise IDLE is started by default on connection inactivity. NB! If `idle()` is called manually then it does not
2840
2895
  * return until IDLE is finished which means you would have to call some other command out of scope.
2841
2896
  *
2897
+ * Unlike auto-IDLE, a direct call does not wait for the connection to be free: a mailbox lock
2898
+ * holder may idle inside its own lock, and idle() can not tell it from another caller.
2899
+ *
2842
2900
  * @returns `false` if IDLE failed, `undefined` otherwise
2843
2901
  *
2844
2902
  * @example
@@ -3092,6 +3150,9 @@ export class ImapFlow extends EventEmitter {
3092
3150
  * @param query Fetch query
3093
3151
  * @param options Fetch options
3094
3152
  * @yields Message data object
3153
+ * @throws An error with the code `NoMailboxSelected` when no mailbox is selected (for example
3154
+ * after `mailboxClose()` or a failed `mailboxOpen()`), or `NoConnection` once the connection
3155
+ * is gone. Earlier releases yielded nothing in that case, as for an empty mailbox
3095
3156
  *
3096
3157
  * @example
3097
3158
  * let mailbox = await client.mailboxOpen('INBOX');
@@ -3105,8 +3166,8 @@ export class ImapFlow extends EventEmitter {
3105
3166
  async *fetch(range, query, options) {
3106
3167
  options = options || {};
3107
3168
  if (!this.mailbox) {
3108
- // no mailbox selected, nothing to do
3109
- return;
3169
+ // an empty result would look like an empty mailbox, for example right after close()
3170
+ throw this.createNoMailboxError('FETCH');
3110
3171
  }
3111
3172
  let resolved = await this.resolveRange(range, options);
3112
3173
  if (!resolved) {
@@ -3216,6 +3277,7 @@ export class ImapFlow extends EventEmitter {
3216
3277
  * @param query Fetch query
3217
3278
  * @param options Fetch options
3218
3279
  * @returns Array of Message data object
3280
+ * @throws An error with the code `NoMailboxSelected` when no mailbox is selected, see fetch()
3219
3281
  *
3220
3282
  * @example
3221
3283
  * let mailbox = await client.mailboxOpen('INBOX');
@@ -3239,7 +3301,9 @@ export class ImapFlow extends EventEmitter {
3239
3301
  * @param seq Single UID or sequence number of the message to fetch for
3240
3302
  * @param query Fetch query
3241
3303
  * @param options Fetch options
3242
- * @returns Message data object
3304
+ * @returns Message data object, `false` when the message was not found
3305
+ * @throws An error with the code `NoMailboxSelected` when no mailbox is selected, see fetch().
3306
+ * Earlier releases resolved `undefined` then
3243
3307
  *
3244
3308
  * @example
3245
3309
  * let mailbox = await client.mailboxOpen('INBOX');
@@ -3249,8 +3313,9 @@ export class ImapFlow extends EventEmitter {
3249
3313
  */
3250
3314
  async fetchOne(seq, query, options) {
3251
3315
  if (!this.mailbox) {
3252
- // no mailbox selected, nothing to do
3253
- return;
3316
+ // undefined used to be returned here, indistinguishable from a missing message for a
3317
+ // caller that only tests the result
3318
+ throw this.createNoMailboxError('FETCH');
3254
3319
  }
3255
3320
  if (seq === '*') {
3256
3321
  if (!this.mailbox.exists) {
@@ -3428,6 +3493,9 @@ export class ImapFlow extends EventEmitter {
3428
3493
  return;
3429
3494
  }
3430
3495
  this.processingLock = true;
3496
+ // The lock taken off the queue and not settled yet. A pass that throws out of its loop
3497
+ // rejects it, its caller would wait forever otherwise: it is in the queue no longer.
3498
+ let unsettled = null;
3431
3499
  try {
3432
3500
  // Process all locks in queue until empty
3433
3501
  let processedCount = 0;
@@ -3444,6 +3512,7 @@ export class ImapFlow extends EventEmitter {
3444
3512
  await new Promise(resolve => setImmediate(resolve));
3445
3513
  }
3446
3514
  const lock = this.locks.shift();
3515
+ unsettled = lock;
3447
3516
  const { resolve, reject, path, options, lockId } = lock;
3448
3517
  // From here on the grant/reject path owns the outcome; the acquire
3449
3518
  // timer must not race with resolution.
@@ -3509,6 +3578,7 @@ export class ImapFlow extends EventEmitter {
3509
3578
  };
3510
3579
  if (!this.usable || !this.socket || this.socket.destroyed) {
3511
3580
  this.log.trace({ msg: 'Failed to acquire mailbox lock', path, lockId, idling: this.idling });
3581
+ unsettled = null;
3512
3582
  reject(this.createNoConnectionError(false, { rejectedFrom: 'mailboxLock', path }));
3513
3583
  continue; // Process next lock in queue
3514
3584
  }
@@ -3521,6 +3591,7 @@ export class ImapFlow extends EventEmitter {
3521
3591
  this.currentLock = lock;
3522
3592
  armHeldTimer();
3523
3593
  this.autoidle();
3594
+ unsettled = null;
3524
3595
  resolve({ path, release });
3525
3596
  };
3526
3597
  if (this.mailbox && this.mailbox.path === path && !!this.mailbox.readOnly === !!options.readOnly) {
@@ -3563,23 +3634,35 @@ export class ImapFlow extends EventEmitter {
3563
3634
  ...(options.description && { description: options.description }),
3564
3635
  err
3565
3636
  });
3637
+ unsettled = null;
3566
3638
  reject(err);
3567
3639
  // Continue to next lock in queue
3568
3640
  }
3569
3641
  }
3570
3642
  }
3643
+ catch (err) {
3644
+ if (unsettled) {
3645
+ let lock = unsettled;
3646
+ unsettled = null;
3647
+ // granted but not handed out (the grant itself failed): nobody can release it
3648
+ if (this.currentLock === lock) {
3649
+ clearTimer(lock.heldWarnTimer);
3650
+ lock.heldWarnTimer = null;
3651
+ this.currentLock = false;
3652
+ }
3653
+ lock.reject(err);
3654
+ }
3655
+ throw err;
3656
+ }
3571
3657
  finally {
3572
3658
  this.processingLock = false;
3573
- // New locks may have been queued while we were processing (e.g.,
3574
- // a lock that failed immediately and the next getMailboxLock call
3575
- // arrived before we finished). Schedule another run if needed.
3576
- /* c8 ignore start */ // requires a lock to be enqueued during an in-flight processLocks pass; not reproducible deterministically
3659
+ // A pass that ended with locks queued and none held (it threw out of its loop) would
3660
+ // leave them waiting with nothing to start another pass. Schedule one.
3577
3661
  if (this.locks.length && !this.currentLock) {
3578
3662
  setImmediate(() => {
3579
3663
  this.processLocks().catch(err => this.log.error({ err, cid: this.id }));
3580
3664
  });
3581
3665
  }
3582
- /* c8 ignore stop */
3583
3666
  }
3584
3667
  }
3585
3668
  /**
@@ -3773,7 +3856,8 @@ export class ImapFlow extends EventEmitter {
3773
3856
  */
3774
3857
  /**
3775
3858
  * Error event. In most cases getting an error event also means that connection is closed
3776
- * and pending operations should return with a failure.
3859
+ * and pending operations should return with a failure. Emitted at most once per connection,
3860
+ * later errors while the connection is closing are only logged.
3777
3861
  *
3778
3862
  * @event ImapFlow#error
3779
3863
  * @example
@@ -1,3 +1,3 @@
1
1
  export declare const name = "imapflow";
2
- export declare const version = "2.5.8";
2
+ export declare const version = "2.6.0";
3
3
  export declare const homepage = "https://imapflow.com/";
@@ -1,4 +1,4 @@
1
1
  // Generated by scripts/build.js from package.json. Do not edit by hand.
2
2
  export const name = "imapflow";
3
- export const version = "2.5.8";
3
+ export const version = "2.6.0";
4
4
  export const homepage = "https://imapflow.com/";
@@ -76,8 +76,13 @@ export interface ImapFlowOptions {
76
76
  emitLogs?: boolean | undefined;
77
77
  /** If true, then logs out automatically after successful authentication */
78
78
  verifyOnly?: boolean | undefined;
79
- /** If true and verifyOnly is set, lists mailboxes */
79
+ /** If true and verifyOnly is set, lists mailboxes. The listing is in `client.mailboxList` once `connect()` resolved */
80
80
  includeMailboxes?: boolean | undefined;
81
+ /**
82
+ * Data of the application's own to keep with the client, such as the account the connection
83
+ * belongs to. ImapFlow never reads it, it is the initial value of `client.context`
84
+ */
85
+ context?: unknown;
81
86
  /**
82
87
  * Proxy URL. Supports HTTP CONNECT (http:, https:) and SOCKS (socks:, socks4:, socks4a:,
83
88
  * socks5:) proxies. IPv6 proxy endpoints are given in URL form, e.g. `socks5://[2001:db8::1]:1080`.
@@ -133,8 +138,9 @@ export interface ImapFlowOptions {
133
138
  * whatever is left of `maxResponseSize`, so lowering that also bounds line buffering.
134
139
  * Exceeding it is terminal: the connection fails with error code `LineTooLarge` and
135
140
  * no further input is parsed. The limit bounds the bytes of a line, not the memory its parse
136
- * takes, which is several times the line size for a line of many small tokens. A SEARCH
137
- * answer of plain numbers is read into an array of about the size of the line.
141
+ * takes, which is several times the line size for a line of many small tokens, see
142
+ * `maxResponseTokens`. A SEARCH answer of plain numbers is read into an array of about the
143
+ * size of the line.
138
144
  */
139
145
  maxLineLength?: number | undefined;
140
146
  /**
@@ -159,6 +165,16 @@ export interface ImapFlowOptions {
159
165
  * no further input is parsed.
160
166
  */
161
167
  maxResponseSize?: number | undefined;
168
+ /**
169
+ * Maximum number of tokens (atoms, strings, literals, lists and other parse tree nodes) in a
170
+ * single IMAP response. The byte limits bound what a server sends, this bounds what parsing it
171
+ * costs: each token takes around a hundred bytes of heap while the response is parsed, so a
172
+ * response of many small tokens costs about fifty times its size. Defaults to 1000000, far
173
+ * above any legitimate response (a SEARCH answer of plain numbers is not tokenized and does
174
+ * not count). Lower it in a memory-limited runtime. `Infinity` disables the limit. Exceeding it
175
+ * is terminal: the connection fails with error code `TooManyTokens`.
176
+ */
177
+ maxResponseTokens?: number | undefined;
162
178
  /**
163
179
  * Threshold in milliseconds for warning that a mailbox lock has been held
164
180
  * for a long time (diagnostic for forgotten release() calls). Defaults to
@@ -681,9 +697,12 @@ export type DownloadManyResult = {
681
697
  export interface AppendResponseObject {
682
698
  /** Full mailbox path where the message was uploaded to */
683
699
  destination: string;
684
- /** Mailbox UIDVALIDITY if server has UIDPLUS extension enabled */
700
+ /** Mailbox UIDVALIDITY if server has UIDPLUS extension enabled, only set together with the `uid` it reported */
685
701
  uidValidity?: bigint | undefined;
686
- /** UID of the uploaded message if server has UIDPLUS extension enabled */
702
+ /**
703
+ * UID of the uploaded message if server has UIDPLUS extension enabled. Without a usable APPENDUID,
704
+ * an append to the selected mailbox looks it up by sequence number instead, and `uidValidity` is not set
705
+ */
687
706
  uid?: number | undefined;
688
707
  /** Sequence number of the uploaded message if path is currently selected mailbox */
689
708
  seq?: number | undefined;
@@ -775,6 +794,22 @@ export interface ExistsEvent {
775
794
  /** Message count before this update */
776
795
  prevCount: number;
777
796
  }
797
+ /**
798
+ * Payload of the `highestModseq` event: the HIGHESTMODSEQ of the selected mailbox changed (RFC
799
+ * 7162), so flags or other message metadata changed on the server. Emitted when a poll on a
800
+ * server without IDLE (`missingIdleCommand` STATUS or SELECT) or a STATUS or re-SELECT of the
801
+ * open mailbox reports a new value, which is when the changes themselves are not delivered as
802
+ * `flags` events. A consumer resynchronizes with `fetch(range, { flags: true }, { changedSince:
803
+ * prevHighestModseq })`.
804
+ */
805
+ export interface HighestModseqEvent {
806
+ /** Mailbox path */
807
+ path: string;
808
+ /** The new HIGHESTMODSEQ value */
809
+ highestModseq: bigint;
810
+ /** The value before this update, undefined when none was known */
811
+ prevHighestModseq?: bigint | undefined;
812
+ }
778
813
  export interface FlagsEvent {
779
814
  /** Mailbox path */
780
815
  path: string;
@@ -874,7 +909,10 @@ export interface TlsInfo extends CipherNameAndProtocol {
874
909
  export interface ImapFlowEvents {
875
910
  /** Connection close event */
876
911
  close: [];
877
- /** Error event */
912
+ /**
913
+ * Error event. Emitted at most once per connection, the connection closes after it. An error
914
+ * while `connect()` is pending rejects `connect()` instead and is not emitted
915
+ */
878
916
  error: [error: Error];
879
917
  /** Message count in currently opened mailbox changed */
880
918
  exists: [data: ExistsEvent];
@@ -882,7 +920,13 @@ export interface ImapFlowEvents {
882
920
  expunge: [data: ExpungeEvent];
883
921
  /** Flags were updated for a message */
884
922
  flags: [data: FlagsEvent];
885
- /** Mailbox was opened */
923
+ /** The HIGHESTMODSEQ of the selected mailbox changed without the changes being reported, see {@link HighestModseqEvent} */
924
+ highestModseq: [data: HighestModseqEvent];
925
+ /**
926
+ * Mailbox was opened. Also emitted, after `mailboxClose` for the old mailbox object, when the
927
+ * open mailbox turned out to have a new UIDVALIDITY (a re-SELECT, or a STATUS poll on a server
928
+ * without IDLE, which then selects the mailbox again): every cached UID of it is invalid
929
+ */
886
930
  mailboxOpen: [mailbox: MailboxObject];
887
931
  /** Mailbox was closed, either explicitly or because the connection went away while a mailbox was still selected */
888
932
  mailboxClose: [mailbox: MailboxObject];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imapflow",
3
- "version": "2.5.8",
3
+ "version": "2.6.0",
4
4
  "description": "IMAP Client for Node",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/imap-flow.js",
@@ -93,8 +93,8 @@
93
93
  "tsx": "4.23.15",
94
94
  "types-node-legacy": "npm:@types/node@20.0.0",
95
95
  "typescript": "6.0.3",
96
- "typescript-eslint": "8.71.2",
97
- "wrangler": "4.151.2"
96
+ "typescript-eslint": "8.72.0",
97
+ "wrangler": "4.151.3"
98
98
  },
99
99
  "dependencies": {
100
100
  "@zone-eu/mailsplit": "5.4.27",