@marlinjai/email-mcp 1.2.0 → 1.2.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/dist/index.js +86 -45
- package/dist/index.js.map +3 -3
- package/dist/setup/wizard.js +86 -45
- package/dist/setup/wizard.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7680,11 +7680,16 @@ var init_adapter2 = __esm({
|
|
|
7680
7680
|
}
|
|
7681
7681
|
this.accountId = credentials.id;
|
|
7682
7682
|
this.accessToken = credentials.oauth.access_token;
|
|
7683
|
-
|
|
7683
|
+
const client = Client.init({
|
|
7684
7684
|
authProvider: (done) => {
|
|
7685
7685
|
done(null, this.accessToken);
|
|
7686
7686
|
}
|
|
7687
7687
|
});
|
|
7688
|
+
const originalApi = client.api.bind(client);
|
|
7689
|
+
client.api = (path3) => {
|
|
7690
|
+
return originalApi(path3).header("Prefer", 'IdType="ImmutableId"');
|
|
7691
|
+
};
|
|
7692
|
+
this.client = client;
|
|
7688
7693
|
}
|
|
7689
7694
|
async disconnect() {
|
|
7690
7695
|
this.client = null;
|
|
@@ -8389,60 +8394,96 @@ var init_adapter3 = __esm({
|
|
|
8389
8394
|
throw formatImapError(error48, `Failed to open folder "${folder}"`);
|
|
8390
8395
|
}
|
|
8391
8396
|
try {
|
|
8397
|
+
const mailboxExists = this.client.mailbox?.exists ?? -1;
|
|
8398
|
+
if (mailboxExists === 0) {
|
|
8399
|
+
return [];
|
|
8400
|
+
}
|
|
8392
8401
|
const criteria = this.buildSearchCriteria(query);
|
|
8393
|
-
const
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8402
|
+
const hasCriteria = Object.keys(criteria).length > 0;
|
|
8403
|
+
let allUids;
|
|
8404
|
+
try {
|
|
8405
|
+
const searchResult = await this.client.search(
|
|
8406
|
+
hasCriteria ? criteria : { all: true },
|
|
8407
|
+
{ uid: true }
|
|
8408
|
+
);
|
|
8409
|
+
allUids = Array.isArray(searchResult) ? searchResult : [];
|
|
8410
|
+
} catch (searchError) {
|
|
8411
|
+
if (!hasCriteria) {
|
|
8412
|
+
allUids = await this.collectUidsViaFetch(query);
|
|
8413
|
+
} else {
|
|
8414
|
+
throw searchError;
|
|
8415
|
+
}
|
|
8416
|
+
}
|
|
8398
8417
|
const offset = query.offset || 0;
|
|
8399
8418
|
const slicedUids = query.limit ? allUids.slice(offset, offset + query.limit) : allUids.slice(offset);
|
|
8400
8419
|
if (slicedUids.length === 0) return [];
|
|
8401
|
-
|
|
8402
|
-
if (query.returnBody) {
|
|
8403
|
-
for await (const msg of this.client.fetch(slicedUids, { source: true, uid: true, flags: true })) {
|
|
8404
|
-
const parsed = await simpleParser(msg.source);
|
|
8405
|
-
parsed.flags = msg.flags;
|
|
8406
|
-
emails.push(mapParsedEmail(parsed, folder, this.accountId, msg.uid));
|
|
8407
|
-
}
|
|
8408
|
-
} else {
|
|
8409
|
-
for await (const msg of this.client.fetch(slicedUids, {
|
|
8410
|
-
envelope: true,
|
|
8411
|
-
uid: true,
|
|
8412
|
-
flags: true,
|
|
8413
|
-
bodyStructure: true
|
|
8414
|
-
})) {
|
|
8415
|
-
const env = msg.envelope;
|
|
8416
|
-
emails.push({
|
|
8417
|
-
id: String(msg.uid),
|
|
8418
|
-
accountId: this.accountId,
|
|
8419
|
-
threadId: env.messageId || void 0,
|
|
8420
|
-
folder,
|
|
8421
|
-
from: env.from?.[0] ? { name: env.from[0].name || void 0, email: env.from[0].address || "" } : { email: "" },
|
|
8422
|
-
to: (env.to || []).map((a) => ({ name: a.name || void 0, email: a.address || "" })),
|
|
8423
|
-
cc: env.cc?.length ? env.cc.map((a) => ({ name: a.name || void 0, email: a.address || "" })) : void 0,
|
|
8424
|
-
bcc: env.bcc?.length ? env.bcc.map((a) => ({ name: a.name || void 0, email: a.address || "" })) : void 0,
|
|
8425
|
-
subject: env.subject || "(no subject)",
|
|
8426
|
-
date: env.date ? new Date(env.date).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
8427
|
-
body: { text: void 0, html: void 0 },
|
|
8428
|
-
snippet: env.subject || "",
|
|
8429
|
-
attachments: [],
|
|
8430
|
-
flags: {
|
|
8431
|
-
read: msg.flags?.has("\\Seen") ?? false,
|
|
8432
|
-
starred: msg.flags?.has("\\Flagged") ?? false,
|
|
8433
|
-
flagged: msg.flags?.has("\\Flagged") ?? false,
|
|
8434
|
-
draft: msg.flags?.has("\\Draft") ?? false
|
|
8435
|
-
}
|
|
8436
|
-
});
|
|
8437
|
-
}
|
|
8438
|
-
}
|
|
8439
|
-
return emails;
|
|
8420
|
+
return await this.fetchEmails(slicedUids, folder, query.returnBody);
|
|
8440
8421
|
} catch (error48) {
|
|
8441
8422
|
throw formatImapError(error48, `Search failed in folder "${folder}"`);
|
|
8442
8423
|
} finally {
|
|
8443
8424
|
lock.release();
|
|
8444
8425
|
}
|
|
8445
8426
|
}
|
|
8427
|
+
/**
|
|
8428
|
+
* Fallback UID collection when UID SEARCH fails (e.g. iCloud "Invalid message number").
|
|
8429
|
+
* Uses FETCH 1:* with sequence numbers to collect UIDs directly, optionally filtering
|
|
8430
|
+
* by flag-based criteria (unread, starred).
|
|
8431
|
+
*/
|
|
8432
|
+
async collectUidsViaFetch(query) {
|
|
8433
|
+
if (!this.client) return [];
|
|
8434
|
+
const uids = [];
|
|
8435
|
+
for await (const msg of this.client.fetch("1:*", { uid: true, flags: true })) {
|
|
8436
|
+
if (query.unreadOnly && msg.flags?.has("\\Seen")) continue;
|
|
8437
|
+
if (query.starredOnly && !msg.flags?.has("\\Flagged")) continue;
|
|
8438
|
+
uids.push(msg.uid);
|
|
8439
|
+
}
|
|
8440
|
+
return uids;
|
|
8441
|
+
}
|
|
8442
|
+
/**
|
|
8443
|
+
* Fetches email data for a set of UIDs, either with full body or lightweight headers.
|
|
8444
|
+
*/
|
|
8445
|
+
async fetchEmails(uids, folder, returnBody) {
|
|
8446
|
+
if (!this.client) return [];
|
|
8447
|
+
const emails = [];
|
|
8448
|
+
if (returnBody) {
|
|
8449
|
+
for await (const msg of this.client.fetch(uids, { source: true, uid: true, flags: true })) {
|
|
8450
|
+
const parsed = await simpleParser(msg.source);
|
|
8451
|
+
parsed.flags = msg.flags;
|
|
8452
|
+
emails.push(mapParsedEmail(parsed, folder, this.accountId, msg.uid));
|
|
8453
|
+
}
|
|
8454
|
+
} else {
|
|
8455
|
+
for await (const msg of this.client.fetch(uids, {
|
|
8456
|
+
envelope: true,
|
|
8457
|
+
uid: true,
|
|
8458
|
+
flags: true,
|
|
8459
|
+
bodyStructure: true
|
|
8460
|
+
})) {
|
|
8461
|
+
const env = msg.envelope;
|
|
8462
|
+
emails.push({
|
|
8463
|
+
id: String(msg.uid),
|
|
8464
|
+
accountId: this.accountId,
|
|
8465
|
+
threadId: env.messageId || void 0,
|
|
8466
|
+
folder,
|
|
8467
|
+
from: env.from?.[0] ? { name: env.from[0].name || void 0, email: env.from[0].address || "" } : { email: "" },
|
|
8468
|
+
to: (env.to || []).map((a) => ({ name: a.name || void 0, email: a.address || "" })),
|
|
8469
|
+
cc: env.cc?.length ? env.cc.map((a) => ({ name: a.name || void 0, email: a.address || "" })) : void 0,
|
|
8470
|
+
bcc: env.bcc?.length ? env.bcc.map((a) => ({ name: a.name || void 0, email: a.address || "" })) : void 0,
|
|
8471
|
+
subject: env.subject || "(no subject)",
|
|
8472
|
+
date: env.date ? new Date(env.date).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
8473
|
+
body: { text: void 0, html: void 0 },
|
|
8474
|
+
snippet: env.subject || "",
|
|
8475
|
+
attachments: [],
|
|
8476
|
+
flags: {
|
|
8477
|
+
read: msg.flags?.has("\\Seen") ?? false,
|
|
8478
|
+
starred: msg.flags?.has("\\Flagged") ?? false,
|
|
8479
|
+
flagged: msg.flags?.has("\\Flagged") ?? false,
|
|
8480
|
+
draft: msg.flags?.has("\\Draft") ?? false
|
|
8481
|
+
}
|
|
8482
|
+
});
|
|
8483
|
+
}
|
|
8484
|
+
}
|
|
8485
|
+
return emails;
|
|
8486
|
+
}
|
|
8446
8487
|
async getEmail(id, folder) {
|
|
8447
8488
|
if (!this.client) throw new Error("Not connected");
|
|
8448
8489
|
const targetFolder = folder || "INBOX";
|