@bobfrankston/iflow 1.0.43 → 1.0.44
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/imaplib/imap-native.js +30 -18
- package/imaplib/imap-protocol.js +2 -2
- package/package.json +1 -1
package/imaplib/imap-native.js
CHANGED
|
@@ -141,15 +141,9 @@ export class NativeImapClient {
|
|
|
141
141
|
this.capabilities.add(c.toUpperCase());
|
|
142
142
|
}
|
|
143
143
|
async logout() {
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
if (this._connected) {
|
|
148
|
-
const tag = proto.nextTag();
|
|
149
|
-
this.transport.write(proto.logoutCommand(tag)).catch(() => { });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
catch { /* ignore */ }
|
|
144
|
+
// Force-close the transport immediately. The LOGOUT command is a courtesy —
|
|
145
|
+
// the server cleans up the session when the socket closes.
|
|
146
|
+
// Sending LOGOUT and waiting caused hangs and connection leaks.
|
|
153
147
|
this.pendingCommand = null;
|
|
154
148
|
this.transport.close();
|
|
155
149
|
this._connected = false;
|
|
@@ -471,15 +465,23 @@ export class NativeImapClient {
|
|
|
471
465
|
}
|
|
472
466
|
processBuffer() {
|
|
473
467
|
while (true) {
|
|
474
|
-
// Check for literal {size}\r\n
|
|
468
|
+
// Check for literal {size}\r\n — reading exact byte count of literal data
|
|
475
469
|
if (this.pendingCommand?.literalBytes != null) {
|
|
476
470
|
if (this.buffer.length >= this.pendingCommand.literalBytes) {
|
|
477
471
|
const literal = this.buffer.substring(0, this.pendingCommand.literalBytes);
|
|
478
472
|
this.buffer = this.buffer.substring(this.pendingCommand.literalBytes);
|
|
479
473
|
this.pendingCommand.literalBuffer = (this.pendingCommand.literalBuffer || "") + literal;
|
|
480
474
|
this.pendingCommand.literalBytes = undefined;
|
|
475
|
+
if (this.verbose)
|
|
476
|
+
console.log(` [imap] literal consumed, ${literal.length} bytes, buffer remaining: ${this.buffer.length}`);
|
|
477
|
+
// After consuming literal, check if the NEXT part has another literal
|
|
478
|
+
// (e.g., BODY[HEADER] {500}\r\n<data>BODY[] {2000}\r\n<data>)\r\n)
|
|
479
|
+
// Continue to process the next line/literal from the buffer
|
|
481
480
|
continue;
|
|
482
481
|
}
|
|
482
|
+
if (this.verbose && this.pendingCommand.literalBytes > 0) {
|
|
483
|
+
console.log(` [imap] waiting for literal: need ${this.pendingCommand.literalBytes}, have ${this.buffer.length}`);
|
|
484
|
+
}
|
|
483
485
|
break; // Wait for more data
|
|
484
486
|
}
|
|
485
487
|
const lineEnd = this.buffer.indexOf("\r\n");
|
|
@@ -487,24 +489,34 @@ export class NativeImapClient {
|
|
|
487
489
|
break;
|
|
488
490
|
const line = this.buffer.substring(0, lineEnd + 2);
|
|
489
491
|
this.buffer = this.buffer.substring(lineEnd + 2);
|
|
490
|
-
// Check for literal announcement {size}
|
|
492
|
+
// Check for literal announcement {size}\r\n at end of line
|
|
491
493
|
const literalMatch = line.match(/\{(\d+)\}\r\n$/);
|
|
492
494
|
if (literalMatch && this.pendingCommand) {
|
|
493
|
-
|
|
494
|
-
// Store the line prefix before
|
|
495
|
-
const linePrefix = line.substring(0,
|
|
496
|
-
this.pendingCommand.literalBuffer
|
|
495
|
+
const size = parseInt(literalMatch[1]);
|
|
496
|
+
// Store the line prefix before {size} — will be prepended after literal is consumed
|
|
497
|
+
const linePrefix = line.substring(0, literalMatch.index);
|
|
498
|
+
if (this.pendingCommand.literalBuffer) {
|
|
499
|
+
// Already have buffered data from a previous literal — append this prefix
|
|
500
|
+
this.pendingCommand.literalBuffer += linePrefix;
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
this.pendingCommand.literalBuffer = linePrefix;
|
|
504
|
+
}
|
|
505
|
+
this.pendingCommand.literalBytes = size;
|
|
506
|
+
if (this.verbose)
|
|
507
|
+
console.log(` [imap] literal announced: ${size} bytes, prefix: ${linePrefix.length} chars`);
|
|
497
508
|
continue;
|
|
498
509
|
}
|
|
499
|
-
// If we have buffered literal data, prepend it
|
|
510
|
+
// If we have buffered literal data, prepend it to this line (the closing part after the literal)
|
|
500
511
|
let fullLine = line;
|
|
501
512
|
if (this.pendingCommand?.literalBuffer) {
|
|
502
513
|
fullLine = this.pendingCommand.literalBuffer + line;
|
|
503
514
|
this.pendingCommand.literalBuffer = undefined;
|
|
504
515
|
}
|
|
505
516
|
const resp = proto.parseResponseLine(fullLine);
|
|
506
|
-
if (this.verbose
|
|
507
|
-
|
|
517
|
+
if (this.verbose) {
|
|
518
|
+
const display = resp.raw.length > 200 ? resp.raw.substring(0, 200) + `... (${resp.raw.length} bytes)` : resp.raw;
|
|
519
|
+
console.log(` [imap] < [tag=${resp.tag} type=${resp.type}] ${display}`);
|
|
508
520
|
}
|
|
509
521
|
// Server greeting — resolve readGreeting() promise
|
|
510
522
|
if (this.greetingResolve && resp.tag === "*" && (resp.type === "OK" || resp.type === "PREAUTH")) {
|
package/imaplib/imap-protocol.js
CHANGED
|
@@ -116,8 +116,8 @@ export function parseResponseLine(line) {
|
|
|
116
116
|
// Untagged response
|
|
117
117
|
if (trimmed.startsWith("* ")) {
|
|
118
118
|
const rest = trimmed.substring(2);
|
|
119
|
-
// Check for numeric response (e.g., "* 5 EXISTS")
|
|
120
|
-
const numMatch = rest.match(/^(\d+)\s+(\S+)
|
|
119
|
+
// Check for numeric response (e.g., "* 5 EXISTS", "* 131441 FETCH (...)")
|
|
120
|
+
const numMatch = rest.match(/^(\d+)\s+(\S+)/);
|
|
121
121
|
if (numMatch) {
|
|
122
122
|
return { tag: "*", type: numMatch[2].toUpperCase(), text: rest, raw: trimmed };
|
|
123
123
|
}
|