@marlinjai/email-mcp 1.8.0 → 1.8.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 +83 -51
- package/dist/index.js.map +3 -3
- package/dist/setup/wizard.js +74 -50
- package/dist/setup/wizard.js.map +3 -3
- package/package.json +3 -1
package/dist/setup/wizard.js
CHANGED
|
@@ -892,6 +892,53 @@ function buildGmailQuery(query) {
|
|
|
892
892
|
return parts.join(" ");
|
|
893
893
|
}
|
|
894
894
|
|
|
895
|
+
// src/providers/mime.ts
|
|
896
|
+
import MailComposer from "nodemailer/lib/mail-composer/index.js";
|
|
897
|
+
import { convert } from "html-to-text";
|
|
898
|
+
function htmlToText(html) {
|
|
899
|
+
return convert(html, {
|
|
900
|
+
wordwrap: false,
|
|
901
|
+
selectors: [
|
|
902
|
+
{ selector: "img", format: "skip" },
|
|
903
|
+
{ selector: "a", options: { hideLinkHrefIfSameAsText: true } }
|
|
904
|
+
]
|
|
905
|
+
}).trim();
|
|
906
|
+
}
|
|
907
|
+
function normalizeBody(body) {
|
|
908
|
+
const html = body.html ? body.html : void 0;
|
|
909
|
+
if (body.text) return { text: body.text, html };
|
|
910
|
+
if (html) return { text: htmlToText(html), html };
|
|
911
|
+
return { text: "" };
|
|
912
|
+
}
|
|
913
|
+
function toAddress(contact) {
|
|
914
|
+
return contact.name ? { name: contact.name, address: contact.email } : contact.email;
|
|
915
|
+
}
|
|
916
|
+
function toAddressList(contacts) {
|
|
917
|
+
return contacts?.length ? contacts.map(toAddress) : void 0;
|
|
918
|
+
}
|
|
919
|
+
async function buildMimeMessage(from, params) {
|
|
920
|
+
const { text, html } = normalizeBody(params.body);
|
|
921
|
+
const mail = {
|
|
922
|
+
from,
|
|
923
|
+
to: toAddressList(params.to),
|
|
924
|
+
cc: toAddressList(params.cc),
|
|
925
|
+
bcc: toAddressList(params.bcc),
|
|
926
|
+
subject: params.subject,
|
|
927
|
+
text,
|
|
928
|
+
html,
|
|
929
|
+
inReplyTo: params.inReplyTo,
|
|
930
|
+
references: params.references?.length ? params.references : void 0,
|
|
931
|
+
attachments: params.attachments?.map((a) => ({
|
|
932
|
+
filename: a.filename,
|
|
933
|
+
content: a.content,
|
|
934
|
+
contentType: a.contentType
|
|
935
|
+
}))
|
|
936
|
+
};
|
|
937
|
+
const node = new MailComposer(mail).compile();
|
|
938
|
+
node.keepBcc = true;
|
|
939
|
+
return node.build();
|
|
940
|
+
}
|
|
941
|
+
|
|
895
942
|
// src/providers/gmail/adapter.ts
|
|
896
943
|
var GmailAdapter = class {
|
|
897
944
|
providerType = ProviderType.Gmail;
|
|
@@ -1034,7 +1081,7 @@ var GmailAdapter = class {
|
|
|
1034
1081
|
}
|
|
1035
1082
|
async sendEmail(params) {
|
|
1036
1083
|
const gmail = this.ensureConnected();
|
|
1037
|
-
const raw = this.
|
|
1084
|
+
const raw = await this.buildRaw(params);
|
|
1038
1085
|
const res = await gmail.users.messages.send({
|
|
1039
1086
|
userId: "me",
|
|
1040
1087
|
requestBody: { raw }
|
|
@@ -1046,7 +1093,7 @@ var GmailAdapter = class {
|
|
|
1046
1093
|
}
|
|
1047
1094
|
async createDraft(params) {
|
|
1048
1095
|
const gmail = this.ensureConnected();
|
|
1049
|
-
const raw = this.
|
|
1096
|
+
const raw = await this.buildRaw(params);
|
|
1050
1097
|
const res = await gmail.users.drafts.create({
|
|
1051
1098
|
userId: "me",
|
|
1052
1099
|
requestBody: {
|
|
@@ -1057,7 +1104,7 @@ var GmailAdapter = class {
|
|
|
1057
1104
|
}
|
|
1058
1105
|
async updateDraft(draftId, params) {
|
|
1059
1106
|
const gmail = this.ensureConnected();
|
|
1060
|
-
const raw = this.
|
|
1107
|
+
const raw = await this.buildRaw(params);
|
|
1061
1108
|
const res = await gmail.users.drafts.update({
|
|
1062
1109
|
userId: "me",
|
|
1063
1110
|
id: draftId,
|
|
@@ -1386,30 +1433,15 @@ var GmailAdapter = class {
|
|
|
1386
1433
|
const gmail = this.ensureConnected();
|
|
1387
1434
|
await gmail.users.settings.filters.delete({ userId: "me", id: ruleId });
|
|
1388
1435
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
if (params.bcc?.length) {
|
|
1399
|
-
lines.push(`Bcc: ${params.bcc.map((c) => c.email).join(", ")}`);
|
|
1400
|
-
}
|
|
1401
|
-
lines.push(`Subject: ${params.subject}`);
|
|
1402
|
-
if (params.inReplyTo) {
|
|
1403
|
-
lines.push(`In-Reply-To: ${params.inReplyTo}`);
|
|
1404
|
-
}
|
|
1405
|
-
if (params.references?.length) {
|
|
1406
|
-
lines.push(`References: ${params.references.join(" ")}`);
|
|
1407
|
-
}
|
|
1408
|
-
lines.push("MIME-Version: 1.0");
|
|
1409
|
-
lines.push("Content-Type: text/plain; charset=UTF-8");
|
|
1410
|
-
lines.push("");
|
|
1411
|
-
lines.push(params.body.text || params.body.html || "");
|
|
1412
|
-
return Buffer.from(lines.join("\r\n")).toString("base64url");
|
|
1436
|
+
/**
|
|
1437
|
+
* Builds the base64url `raw` payload Gmail expects for send, draft create and
|
|
1438
|
+
* draft update: a full MIME message with a text part, an HTML part when one
|
|
1439
|
+
* was given (or a text part derived from HTML-only input), encoded headers
|
|
1440
|
+
* and any attachments. See `buildMimeMessage`.
|
|
1441
|
+
*/
|
|
1442
|
+
async buildRaw(params) {
|
|
1443
|
+
const message = await buildMimeMessage(this.email, params);
|
|
1444
|
+
return message.toString("base64url");
|
|
1413
1445
|
}
|
|
1414
1446
|
};
|
|
1415
1447
|
|
|
@@ -2094,14 +2126,15 @@ function createSmtpTransport(email, creds) {
|
|
|
2094
2126
|
});
|
|
2095
2127
|
}
|
|
2096
2128
|
async function sendViaSmtp(transport, from, params) {
|
|
2129
|
+
const { text, html } = normalizeBody(params.body);
|
|
2097
2130
|
const result = await transport.sendMail({
|
|
2098
2131
|
from,
|
|
2099
|
-
to: params.to.map(
|
|
2100
|
-
cc: params.cc?.
|
|
2101
|
-
bcc: params.bcc?.
|
|
2132
|
+
to: params.to.map(toAddress),
|
|
2133
|
+
cc: params.cc?.length ? params.cc.map(toAddress) : void 0,
|
|
2134
|
+
bcc: params.bcc?.length ? params.bcc.map(toAddress) : void 0,
|
|
2102
2135
|
subject: params.subject,
|
|
2103
|
-
text
|
|
2104
|
-
html
|
|
2136
|
+
text,
|
|
2137
|
+
html,
|
|
2105
2138
|
inReplyTo: params.inReplyTo,
|
|
2106
2139
|
references: params.references?.join(" "),
|
|
2107
2140
|
attachments: params.attachments?.map((a) => ({
|
|
@@ -2572,26 +2605,17 @@ var ImapAdapter = class {
|
|
|
2572
2605
|
const messageId = await sendViaSmtp(transport, this.email, params);
|
|
2573
2606
|
return { id: messageId };
|
|
2574
2607
|
}
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
lines.push(`Subject: ${params.subject}`);
|
|
2583
|
-
lines.push(`Date: ${(/* @__PURE__ */ new Date()).toUTCString()}`);
|
|
2584
|
-
if (params.inReplyTo) lines.push(`In-Reply-To: ${params.inReplyTo}`);
|
|
2585
|
-
if (params.references?.length) lines.push(`References: ${params.references.join(" ")}`);
|
|
2586
|
-
lines.push("MIME-Version: 1.0");
|
|
2587
|
-
lines.push("Content-Type: text/plain; charset=utf-8");
|
|
2588
|
-
lines.push("");
|
|
2589
|
-
lines.push(params.body.text || "");
|
|
2590
|
-
return lines.join("\r\n");
|
|
2608
|
+
/**
|
|
2609
|
+
* Builds the full MIME message a draft is stored as: text and HTML parts,
|
|
2610
|
+
* Bcc kept so the draft remembers its recipients, encoded headers and any
|
|
2611
|
+
* attachments. See `buildMimeMessage`.
|
|
2612
|
+
*/
|
|
2613
|
+
buildDraftMessage(params) {
|
|
2614
|
+
return buildMimeMessage(this.email, params);
|
|
2591
2615
|
}
|
|
2592
2616
|
async createDraft(params) {
|
|
2593
2617
|
const client = await this.ensureConnected();
|
|
2594
|
-
const rawMessage = this.
|
|
2618
|
+
const rawMessage = await this.buildDraftMessage(params);
|
|
2595
2619
|
const draftsFolder = await this.resolveFolder("Drafts");
|
|
2596
2620
|
const result = await client.append(draftsFolder, rawMessage, ["\\Draft", "\\Seen"]);
|
|
2597
2621
|
if (!result) throw new Error("Failed to append draft");
|
|
@@ -2606,6 +2630,7 @@ var ImapAdapter = class {
|
|
|
2606
2630
|
async updateDraft(draftId, params, sourceFolder) {
|
|
2607
2631
|
const client = await this.ensureConnected();
|
|
2608
2632
|
const draftsFolder = sourceFolder ? await this.resolveFolder(sourceFolder) : await this.resolveFolder("Drafts");
|
|
2633
|
+
const rawMessage = await this.buildDraftMessage(params);
|
|
2609
2634
|
let lock;
|
|
2610
2635
|
try {
|
|
2611
2636
|
lock = await client.getMailboxLock(draftsFolder);
|
|
@@ -2617,7 +2642,6 @@ var ImapAdapter = class {
|
|
|
2617
2642
|
} finally {
|
|
2618
2643
|
lock.release();
|
|
2619
2644
|
}
|
|
2620
|
-
const rawMessage = this.buildDraftRfc2822(params);
|
|
2621
2645
|
const result = await client.append(draftsFolder, rawMessage, ["\\Draft", "\\Seen"]);
|
|
2622
2646
|
if (!result) throw new Error("Failed to append updated draft");
|
|
2623
2647
|
return { id: String(result.uid || result) };
|