@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 CHANGED
@@ -7151,6 +7151,58 @@ var init_mapper = __esm({
7151
7151
  }
7152
7152
  });
7153
7153
 
7154
+ // src/providers/mime.ts
7155
+ import MailComposer from "nodemailer/lib/mail-composer/index.js";
7156
+ import { convert } from "html-to-text";
7157
+ function htmlToText(html) {
7158
+ return convert(html, {
7159
+ wordwrap: false,
7160
+ selectors: [
7161
+ { selector: "img", format: "skip" },
7162
+ { selector: "a", options: { hideLinkHrefIfSameAsText: true } }
7163
+ ]
7164
+ }).trim();
7165
+ }
7166
+ function normalizeBody(body) {
7167
+ const html = body.html ? body.html : void 0;
7168
+ if (body.text) return { text: body.text, html };
7169
+ if (html) return { text: htmlToText(html), html };
7170
+ return { text: "" };
7171
+ }
7172
+ function toAddress(contact) {
7173
+ return contact.name ? { name: contact.name, address: contact.email } : contact.email;
7174
+ }
7175
+ function toAddressList(contacts) {
7176
+ return contacts?.length ? contacts.map(toAddress) : void 0;
7177
+ }
7178
+ async function buildMimeMessage(from, params) {
7179
+ const { text, html } = normalizeBody(params.body);
7180
+ const mail = {
7181
+ from,
7182
+ to: toAddressList(params.to),
7183
+ cc: toAddressList(params.cc),
7184
+ bcc: toAddressList(params.bcc),
7185
+ subject: params.subject,
7186
+ text,
7187
+ html,
7188
+ inReplyTo: params.inReplyTo,
7189
+ references: params.references?.length ? params.references : void 0,
7190
+ attachments: params.attachments?.map((a) => ({
7191
+ filename: a.filename,
7192
+ content: a.content,
7193
+ contentType: a.contentType
7194
+ }))
7195
+ };
7196
+ const node = new MailComposer(mail).compile();
7197
+ node.keepBcc = true;
7198
+ return node.build();
7199
+ }
7200
+ var init_mime = __esm({
7201
+ "src/providers/mime.ts"() {
7202
+ "use strict";
7203
+ }
7204
+ });
7205
+
7154
7206
  // src/providers/gmail/adapter.ts
7155
7207
  import { Readable } from "node:stream";
7156
7208
  import { google } from "googleapis";
@@ -7161,6 +7213,7 @@ var init_adapter = __esm({
7161
7213
  "use strict";
7162
7214
  init_types();
7163
7215
  init_mapper();
7216
+ init_mime();
7164
7217
  GmailAdapter = class {
7165
7218
  providerType = ProviderType.Gmail;
7166
7219
  gmail = null;
@@ -7302,7 +7355,7 @@ var init_adapter = __esm({
7302
7355
  }
7303
7356
  async sendEmail(params) {
7304
7357
  const gmail = this.ensureConnected();
7305
- const raw = this.buildRfc2822(params);
7358
+ const raw = await this.buildRaw(params);
7306
7359
  const res = await gmail.users.messages.send({
7307
7360
  userId: "me",
7308
7361
  requestBody: { raw }
@@ -7314,7 +7367,7 @@ var init_adapter = __esm({
7314
7367
  }
7315
7368
  async createDraft(params) {
7316
7369
  const gmail = this.ensureConnected();
7317
- const raw = this.buildRfc2822(params);
7370
+ const raw = await this.buildRaw(params);
7318
7371
  const res = await gmail.users.drafts.create({
7319
7372
  userId: "me",
7320
7373
  requestBody: {
@@ -7325,7 +7378,7 @@ var init_adapter = __esm({
7325
7378
  }
7326
7379
  async updateDraft(draftId, params) {
7327
7380
  const gmail = this.ensureConnected();
7328
- const raw = this.buildRfc2822(params);
7381
+ const raw = await this.buildRaw(params);
7329
7382
  const res = await gmail.users.drafts.update({
7330
7383
  userId: "me",
7331
7384
  id: draftId,
@@ -7654,30 +7707,15 @@ var init_adapter = __esm({
7654
7707
  const gmail = this.ensureConnected();
7655
7708
  await gmail.users.settings.filters.delete({ userId: "me", id: ruleId });
7656
7709
  }
7657
- buildRfc2822(params) {
7658
- const lines = [];
7659
- lines.push(`From: ${this.email}`);
7660
- lines.push(
7661
- `To: ${params.to.map((c) => c.name ? `"${c.name}" <${c.email}>` : c.email).join(", ")}`
7662
- );
7663
- if (params.cc?.length) {
7664
- lines.push(`Cc: ${params.cc.map((c) => c.email).join(", ")}`);
7665
- }
7666
- if (params.bcc?.length) {
7667
- lines.push(`Bcc: ${params.bcc.map((c) => c.email).join(", ")}`);
7668
- }
7669
- lines.push(`Subject: ${params.subject}`);
7670
- if (params.inReplyTo) {
7671
- lines.push(`In-Reply-To: ${params.inReplyTo}`);
7672
- }
7673
- if (params.references?.length) {
7674
- lines.push(`References: ${params.references.join(" ")}`);
7675
- }
7676
- lines.push("MIME-Version: 1.0");
7677
- lines.push("Content-Type: text/plain; charset=UTF-8");
7678
- lines.push("");
7679
- lines.push(params.body.text || params.body.html || "");
7680
- return Buffer.from(lines.join("\r\n")).toString("base64url");
7710
+ /**
7711
+ * Builds the base64url `raw` payload Gmail expects for send, draft create and
7712
+ * draft update: a full MIME message with a text part, an HTML part when one
7713
+ * was given (or a text part derived from HTML-only input), encoded headers
7714
+ * and any attachments. See `buildMimeMessage`.
7715
+ */
7716
+ async buildRaw(params) {
7717
+ const message = await buildMimeMessage(this.email, params);
7718
+ return message.toString("base64url");
7681
7719
  }
7682
7720
  };
7683
7721
  }
@@ -8702,14 +8740,15 @@ function createSmtpTransport(email3, creds) {
8702
8740
  });
8703
8741
  }
8704
8742
  async function sendViaSmtp(transport, from, params) {
8743
+ const { text, html } = normalizeBody(params.body);
8705
8744
  const result = await transport.sendMail({
8706
8745
  from,
8707
- to: params.to.map((c) => c.name ? `"${c.name}" <${c.email}>` : c.email).join(", "),
8708
- cc: params.cc?.map((c) => c.email).join(", "),
8709
- bcc: params.bcc?.map((c) => c.email).join(", "),
8746
+ to: params.to.map(toAddress),
8747
+ cc: params.cc?.length ? params.cc.map(toAddress) : void 0,
8748
+ bcc: params.bcc?.length ? params.bcc.map(toAddress) : void 0,
8710
8749
  subject: params.subject,
8711
- text: params.body.text,
8712
- html: params.body.html,
8750
+ text,
8751
+ html,
8713
8752
  inReplyTo: params.inReplyTo,
8714
8753
  references: params.references?.join(" "),
8715
8754
  attachments: params.attachments?.map((a) => ({
@@ -8723,6 +8762,7 @@ async function sendViaSmtp(transport, from, params) {
8723
8762
  var init_smtp = __esm({
8724
8763
  "src/providers/imap/smtp.ts"() {
8725
8764
  "use strict";
8765
+ init_mime();
8726
8766
  }
8727
8767
  });
8728
8768
 
@@ -8755,6 +8795,7 @@ var init_adapter3 = __esm({
8755
8795
  init_types();
8756
8796
  init_mapper3();
8757
8797
  init_smtp();
8798
+ init_mime();
8758
8799
  ImapAdapter = class {
8759
8800
  providerType = ProviderType.IMAP;
8760
8801
  client = null;
@@ -9194,26 +9235,17 @@ var init_adapter3 = __esm({
9194
9235
  const messageId = await sendViaSmtp(transport, this.email, params);
9195
9236
  return { id: messageId };
9196
9237
  }
9197
- buildDraftRfc2822(params) {
9198
- const lines = [];
9199
- lines.push(`From: ${this.email}`);
9200
- lines.push(`To: ${params.to.map((c) => c.name ? `"${c.name}" <${c.email}>` : c.email).join(", ")}`);
9201
- if (params.cc?.length) {
9202
- lines.push(`Cc: ${params.cc.map((c) => c.email).join(", ")}`);
9203
- }
9204
- lines.push(`Subject: ${params.subject}`);
9205
- lines.push(`Date: ${(/* @__PURE__ */ new Date()).toUTCString()}`);
9206
- if (params.inReplyTo) lines.push(`In-Reply-To: ${params.inReplyTo}`);
9207
- if (params.references?.length) lines.push(`References: ${params.references.join(" ")}`);
9208
- lines.push("MIME-Version: 1.0");
9209
- lines.push("Content-Type: text/plain; charset=utf-8");
9210
- lines.push("");
9211
- lines.push(params.body.text || "");
9212
- return lines.join("\r\n");
9238
+ /**
9239
+ * Builds the full MIME message a draft is stored as: text and HTML parts,
9240
+ * Bcc kept so the draft remembers its recipients, encoded headers and any
9241
+ * attachments. See `buildMimeMessage`.
9242
+ */
9243
+ buildDraftMessage(params) {
9244
+ return buildMimeMessage(this.email, params);
9213
9245
  }
9214
9246
  async createDraft(params) {
9215
9247
  const client = await this.ensureConnected();
9216
- const rawMessage = this.buildDraftRfc2822(params);
9248
+ const rawMessage = await this.buildDraftMessage(params);
9217
9249
  const draftsFolder = await this.resolveFolder("Drafts");
9218
9250
  const result = await client.append(draftsFolder, rawMessage, ["\\Draft", "\\Seen"]);
9219
9251
  if (!result) throw new Error("Failed to append draft");
@@ -9228,6 +9260,7 @@ var init_adapter3 = __esm({
9228
9260
  async updateDraft(draftId, params, sourceFolder) {
9229
9261
  const client = await this.ensureConnected();
9230
9262
  const draftsFolder = sourceFolder ? await this.resolveFolder(sourceFolder) : await this.resolveFolder("Drafts");
9263
+ const rawMessage = await this.buildDraftMessage(params);
9231
9264
  let lock;
9232
9265
  try {
9233
9266
  lock = await client.getMailboxLock(draftsFolder);
@@ -9239,7 +9272,6 @@ var init_adapter3 = __esm({
9239
9272
  } finally {
9240
9273
  lock.release();
9241
9274
  }
9242
- const rawMessage = this.buildDraftRfc2822(params);
9243
9275
  const result = await client.append(draftsFolder, rawMessage, ["\\Draft", "\\Seen"]);
9244
9276
  if (!result) throw new Error("Failed to append updated draft");
9245
9277
  return { id: String(result.uid || result) };
@@ -34451,7 +34483,7 @@ function registerModerationTools(server, accountManager) {
34451
34483
  }
34452
34484
 
34453
34485
  // src/server.ts
34454
- var SERVER_VERSION = "1.8.0";
34486
+ var SERVER_VERSION = "1.8.1";
34455
34487
  async function createServer(accountManager) {
34456
34488
  const mgr = accountManager ?? new AccountManager();
34457
34489
  const server = new McpServer({