@marlinjai/email-mcp 1.2.2 → 1.2.4
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/README.md +7 -0
- package/dist/index.js +62 -17
- package/dist/index.js.map +2 -2
- package/dist/setup/wizard.js +62 -17
- package/dist/setup/wizard.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,6 +202,13 @@ pnpm test:watch
|
|
|
202
202
|
pnpm test:integration
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
## Support
|
|
206
|
+
|
|
207
|
+
If this project is useful to you, consider supporting its development:
|
|
208
|
+
|
|
209
|
+
- [GitHub Sponsors](https://github.com/sponsors/marlinjai)
|
|
210
|
+
- [Buy Me a Coffee](https://buymeacoffee.com/marlinjai)
|
|
211
|
+
|
|
205
212
|
## License
|
|
206
213
|
|
|
207
214
|
MIT
|
package/dist/index.js
CHANGED
|
@@ -8387,6 +8387,10 @@ var init_adapter3 = __esm({
|
|
|
8387
8387
|
} catch {
|
|
8388
8388
|
folder = requestedFolder;
|
|
8389
8389
|
}
|
|
8390
|
+
try {
|
|
8391
|
+
await this.client.noop();
|
|
8392
|
+
} catch {
|
|
8393
|
+
}
|
|
8390
8394
|
let lock;
|
|
8391
8395
|
try {
|
|
8392
8396
|
lock = await this.client.getMailboxLock(folder);
|
|
@@ -8394,8 +8398,15 @@ var init_adapter3 = __esm({
|
|
|
8394
8398
|
throw formatImapError(error48, `Failed to open folder "${folder}"`);
|
|
8395
8399
|
}
|
|
8396
8400
|
try {
|
|
8401
|
+
let realMessageCount = -1;
|
|
8402
|
+
try {
|
|
8403
|
+
const status = await this.client.status(folder, { messages: true });
|
|
8404
|
+
realMessageCount = status.messages ?? -1;
|
|
8405
|
+
} catch {
|
|
8406
|
+
}
|
|
8397
8407
|
const mailboxExists = this.client.mailbox?.exists ?? -1;
|
|
8398
|
-
|
|
8408
|
+
const effectiveCount = Math.max(realMessageCount, mailboxExists);
|
|
8409
|
+
if (effectiveCount === 0) {
|
|
8399
8410
|
return [];
|
|
8400
8411
|
}
|
|
8401
8412
|
const criteria = this.buildSearchCriteria(query);
|
|
@@ -8408,7 +8419,9 @@ var init_adapter3 = __esm({
|
|
|
8408
8419
|
);
|
|
8409
8420
|
allUids = Array.isArray(searchResult) ? searchResult : [];
|
|
8410
8421
|
} catch (searchError) {
|
|
8411
|
-
|
|
8422
|
+
const errorMsg = String(searchError?.responseText || searchError?.message || "").toLowerCase();
|
|
8423
|
+
const isInvalidMessage = errorMsg.includes("invalid message");
|
|
8424
|
+
if (isInvalidMessage || !hasCriteria) {
|
|
8412
8425
|
allUids = await this.collectUidsViaFetch(query);
|
|
8413
8426
|
} else {
|
|
8414
8427
|
throw searchError;
|
|
@@ -8426,18 +8439,47 @@ var init_adapter3 = __esm({
|
|
|
8426
8439
|
}
|
|
8427
8440
|
/**
|
|
8428
8441
|
* Fallback UID collection when UID SEARCH fails (e.g. iCloud "Invalid message number").
|
|
8429
|
-
* Uses
|
|
8430
|
-
*
|
|
8442
|
+
* Uses a multi-level fallback chain:
|
|
8443
|
+
* 1. FETCH 1:* with sequence numbers
|
|
8444
|
+
* 2. FETCH 1:N using mailbox.exists as explicit range
|
|
8445
|
+
* 3. Individual sequence number fetches (slowest but most resilient)
|
|
8431
8446
|
*/
|
|
8432
8447
|
async collectUidsViaFetch(query) {
|
|
8433
8448
|
if (!this.client) return [];
|
|
8434
8449
|
const uids = [];
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8450
|
+
try {
|
|
8451
|
+
for await (const msg of this.client.fetch("1:*", { uid: true, flags: true })) {
|
|
8452
|
+
if (query.unreadOnly && msg.flags?.has("\\Seen")) continue;
|
|
8453
|
+
if (query.starredOnly && !msg.flags?.has("\\Flagged")) continue;
|
|
8454
|
+
uids.push(msg.uid);
|
|
8455
|
+
}
|
|
8456
|
+
return uids;
|
|
8457
|
+
} catch {
|
|
8458
|
+
const exists = this.client.mailbox?.exists ?? 0;
|
|
8459
|
+
if (exists > 0) {
|
|
8460
|
+
try {
|
|
8461
|
+
for await (const msg of this.client.fetch(`1:${exists}`, { uid: true, flags: true })) {
|
|
8462
|
+
if (query.unreadOnly && msg.flags?.has("\\Seen")) continue;
|
|
8463
|
+
if (query.starredOnly && !msg.flags?.has("\\Flagged")) continue;
|
|
8464
|
+
uids.push(msg.uid);
|
|
8465
|
+
}
|
|
8466
|
+
return uids;
|
|
8467
|
+
} catch {
|
|
8468
|
+
}
|
|
8469
|
+
}
|
|
8470
|
+
const count = exists > 0 ? exists : 50;
|
|
8471
|
+
for (let seq = 1; seq <= count; seq++) {
|
|
8472
|
+
try {
|
|
8473
|
+
for await (const msg of this.client.fetch(String(seq), { uid: true, flags: true })) {
|
|
8474
|
+
if (query.unreadOnly && msg.flags?.has("\\Seen")) continue;
|
|
8475
|
+
if (query.starredOnly && !msg.flags?.has("\\Flagged")) continue;
|
|
8476
|
+
uids.push(msg.uid);
|
|
8477
|
+
}
|
|
8478
|
+
} catch {
|
|
8479
|
+
}
|
|
8480
|
+
}
|
|
8481
|
+
return uids;
|
|
8439
8482
|
}
|
|
8440
|
-
return uids;
|
|
8441
8483
|
}
|
|
8442
8484
|
/**
|
|
8443
8485
|
* Fetches email data for a set of UIDs, either with full body or lightweight headers.
|
|
@@ -8624,7 +8666,8 @@ var init_adapter3 = __esm({
|
|
|
8624
8666
|
}
|
|
8625
8667
|
async deleteEmail(emailId, permanent, sourceFolder) {
|
|
8626
8668
|
if (!this.client) throw new Error("Not connected");
|
|
8627
|
-
const folder = sourceFolder
|
|
8669
|
+
const folder = sourceFolder ? await this.resolveFolder(sourceFolder) : "INBOX";
|
|
8670
|
+
const trashFolder = await this.resolveFolder("Trash");
|
|
8628
8671
|
let lock;
|
|
8629
8672
|
try {
|
|
8630
8673
|
lock = await this.client.getMailboxLock(folder);
|
|
@@ -8632,10 +8675,10 @@ var init_adapter3 = __esm({
|
|
|
8632
8675
|
throw formatImapError(error48, `Failed to open folder "${folder}"`);
|
|
8633
8676
|
}
|
|
8634
8677
|
try {
|
|
8635
|
-
if (permanent) {
|
|
8678
|
+
if (permanent || folder === trashFolder) {
|
|
8636
8679
|
await this.client.messageDelete(emailId, { uid: true });
|
|
8637
8680
|
} else {
|
|
8638
|
-
await this.client.messageMove(emailId,
|
|
8681
|
+
await this.client.messageMove(emailId, trashFolder, { uid: true });
|
|
8639
8682
|
}
|
|
8640
8683
|
} finally {
|
|
8641
8684
|
lock.release();
|
|
@@ -8668,7 +8711,9 @@ var init_adapter3 = __esm({
|
|
|
8668
8711
|
async batchDelete(emailIds, permanent, sourceFolder) {
|
|
8669
8712
|
if (!this.client) throw new Error("Not connected");
|
|
8670
8713
|
const result = { succeeded: [], failed: [] };
|
|
8671
|
-
const folder = sourceFolder
|
|
8714
|
+
const folder = sourceFolder ? await this.resolveFolder(sourceFolder) : "INBOX";
|
|
8715
|
+
const trashFolder = await this.resolveFolder("Trash");
|
|
8716
|
+
const shouldPermanentDelete = permanent || folder === trashFolder;
|
|
8672
8717
|
let lock;
|
|
8673
8718
|
try {
|
|
8674
8719
|
lock = await this.client.getMailboxLock(folder);
|
|
@@ -8677,19 +8722,19 @@ var init_adapter3 = __esm({
|
|
|
8677
8722
|
}
|
|
8678
8723
|
try {
|
|
8679
8724
|
const uidRange = emailIds.join(",");
|
|
8680
|
-
if (
|
|
8725
|
+
if (shouldPermanentDelete) {
|
|
8681
8726
|
await this.client.messageDelete(uidRange, { uid: true });
|
|
8682
8727
|
} else {
|
|
8683
|
-
await this.client.messageMove(uidRange,
|
|
8728
|
+
await this.client.messageMove(uidRange, trashFolder, { uid: true });
|
|
8684
8729
|
}
|
|
8685
8730
|
result.succeeded = [...emailIds];
|
|
8686
8731
|
} catch (error48) {
|
|
8687
8732
|
for (const id of emailIds) {
|
|
8688
8733
|
try {
|
|
8689
|
-
if (
|
|
8734
|
+
if (shouldPermanentDelete) {
|
|
8690
8735
|
await this.client.messageDelete(id, { uid: true });
|
|
8691
8736
|
} else {
|
|
8692
|
-
await this.client.messageMove(id,
|
|
8737
|
+
await this.client.messageMove(id, trashFolder, { uid: true });
|
|
8693
8738
|
}
|
|
8694
8739
|
result.succeeded.push(id);
|
|
8695
8740
|
} catch (e) {
|