@marlinjai/email-mcp 1.10.1 → 1.11.0

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.
@@ -922,6 +922,17 @@ function normalizeBody(body) {
922
922
  function toAddress(contact) {
923
923
  return contact.name ? { name: contact.name, address: contact.email } : contact.email;
924
924
  }
925
+ var PROVIDER_LABELS = /* @__PURE__ */ new Set(["gmail", "outlook", "icloud", "imap"]);
926
+ function fromAddress(email, displayName, accountName) {
927
+ const own = displayName?.trim();
928
+ if (own) return { name: own, address: email };
929
+ const fallback = accountName?.trim();
930
+ const label = (name) => PROVIDER_LABELS.has(name) || name === email.toLowerCase() || name === email.toLowerCase().split("@")[0];
931
+ if (fallback && !label(fallback.toLowerCase())) {
932
+ return { name: fallback, address: email };
933
+ }
934
+ return email;
935
+ }
925
936
  function toAddressList(contacts) {
926
937
  return contacts?.length ? contacts.map(toAddress) : void 0;
927
938
  }
@@ -954,12 +965,14 @@ var GmailAdapter = class {
954
965
  gmail = null;
955
966
  accountId = "";
956
967
  email = "";
968
+ accountName = "";
957
969
  async connect(credentials) {
958
970
  if (!credentials.oauth) {
959
971
  throw new Error("Gmail adapter requires OAuth credentials");
960
972
  }
961
973
  this.accountId = credentials.id;
962
974
  this.email = credentials.email;
975
+ this.accountName = credentials.name;
963
976
  const auth = new OAuth2Client2();
964
977
  auth.setCredentials({
965
978
  access_token: credentials.oauth.access_token,
@@ -1157,6 +1170,43 @@ var GmailAdapter = class {
1157
1170
  });
1158
1171
  return { id: res.data.id || draftId };
1159
1172
  }
1173
+ /**
1174
+ * The signature Gmail's own editor would add: the one of the send-as
1175
+ * address the From header names (`this.email`, see buildRaw), or the
1176
+ * default send-as when that address is not listed. Read on every call, so
1177
+ * a signature changed in Gmail's settings applies to the next mail.
1178
+ */
1179
+ async getSignature() {
1180
+ const entries = await this.sendAsList();
1181
+ const entry = this.ownSendAs(entries) || entries.find((e) => e.isDefault);
1182
+ if (!entry) throw new Error(`Gmail lists no send-as address for ${this.email}`);
1183
+ const html = (entry.signature || "").trim();
1184
+ return { sendAs: entry.sendAsEmail || this.email, html: html || null };
1185
+ }
1186
+ async sendAsList() {
1187
+ const gmail = this.ensureConnected();
1188
+ const res = await gmail.users.settings.sendAs.list({ userId: "me" });
1189
+ return res.data.sendAs || [];
1190
+ }
1191
+ ownSendAs(entries) {
1192
+ const own = this.email.toLowerCase();
1193
+ return entries.find((e) => (e.sendAsEmail || "").toLowerCase() === own);
1194
+ }
1195
+ /**
1196
+ * The From header: the account's address with the display name Gmail
1197
+ * keeps for it as a send-as address. When the settings cannot be read the
1198
+ * mail still goes out, named after the account (see `fromAddress`); the
1199
+ * signature outcome in the tool result already reports that failure.
1200
+ */
1201
+ async from() {
1202
+ let displayName;
1203
+ try {
1204
+ displayName = this.ownSendAs(await this.sendAsList())?.displayName || void 0;
1205
+ } catch {
1206
+ displayName = void 0;
1207
+ }
1208
+ return fromAddress(this.email, displayName, this.accountName);
1209
+ }
1160
1210
  async listDrafts(limit, _offset) {
1161
1211
  const gmail = this.ensureConnected();
1162
1212
  const res = await gmail.users.drafts.list({
@@ -1583,7 +1633,7 @@ var GmailAdapter = class {
1583
1633
  * and any attachments. See `buildMimeMessage`.
1584
1634
  */
1585
1635
  async buildRaw(params) {
1586
- const message = await buildMimeMessage(this.email, params);
1636
+ const message = await buildMimeMessage(await this.from(), params);
1587
1637
  return message.toString("base64url");
1588
1638
  }
1589
1639
  };
@@ -2498,6 +2548,7 @@ var ImapAdapter = class {
2498
2548
  client = null;
2499
2549
  accountId = "";
2500
2550
  email = "";
2551
+ accountName = "";
2501
2552
  passwordCreds = null;
2502
2553
  connectingPromise = null;
2503
2554
  async connect(credentials) {
@@ -2506,6 +2557,7 @@ var ImapAdapter = class {
2506
2557
  }
2507
2558
  this.accountId = credentials.id;
2508
2559
  this.email = credentials.email;
2560
+ this.accountName = credentials.name;
2509
2561
  this.passwordCreds = credentials.password;
2510
2562
  await this.ensureConnected();
2511
2563
  }
@@ -2938,7 +2990,7 @@ var ImapAdapter = class {
2938
2990
  async sendEmail(params) {
2939
2991
  if (!this.passwordCreds) throw new Error("No credentials available");
2940
2992
  const transport = createSmtpTransport(this.email, this.passwordCreds);
2941
- const messageId = await sendViaSmtp(transport, this.email, params);
2993
+ const messageId = await sendViaSmtp(transport, this.from(), params);
2942
2994
  return { id: messageId };
2943
2995
  }
2944
2996
  /**
@@ -2947,7 +2999,12 @@ var ImapAdapter = class {
2947
2999
  * attachments. See `buildMimeMessage`.
2948
3000
  */
2949
3001
  buildDraftMessage(params) {
2950
- return buildMimeMessage(this.email, params);
3002
+ return buildMimeMessage(this.from(), params);
3003
+ }
3004
+ /** IMAP keeps no display name on the server, so the account's name is the
3005
+ * only one there is (see `fromAddress`). */
3006
+ from() {
3007
+ return fromAddress(this.email, void 0, this.accountName);
2951
3008
  }
2952
3009
  async createDraft(params) {
2953
3010
  const client = await this.ensureConnected();