@weijingwei/email 1.0.3 → 1.0.5

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.
Files changed (3) hide show
  1. package/dist/bundle.js +99 -39
  2. package/dist/cli.js +97 -38
  3. package/package.json +1 -1
package/dist/bundle.js CHANGED
@@ -82590,6 +82590,10 @@ function validateSmtpConfig(config2) {
82590
82590
  // src/services/imap.ts
82591
82591
  var import_imap_simple = __toESM(require_imap_simple());
82592
82592
  var import_mailparser = __toESM(require_mailparser());
82593
+ function isNeteaseMailbox(host) {
82594
+ const neteasePatterns = ["163.com", "126.com", "netease.com", "188.com"];
82595
+ return neteasePatterns.some((pattern) => host.includes(pattern));
82596
+ }
82593
82597
  function createImapConfig(config2) {
82594
82598
  return {
82595
82599
  imap: {
@@ -82608,18 +82612,35 @@ function createImapConfig(config2) {
82608
82612
  }
82609
82613
  async function connectImap(config2) {
82610
82614
  const imapConfig = createImapConfig(config2);
82611
- return await import_imap_simple.default.connect(imapConfig);
82615
+ const connection = await import_imap_simple.default.connect(imapConfig);
82616
+ if (isNeteaseMailbox(config2.host) && connection.imap.serverSupports("ID")) {
82617
+ await new Promise((resolve, reject) => {
82618
+ connection.imap.id({
82619
+ name: "EmailMCP",
82620
+ version: "1.0",
82621
+ vendor: "Weijingwei",
82622
+ "support-email": config2.username
82623
+ }, (err) => {
82624
+ if (err)
82625
+ reject(err);
82626
+ else
82627
+ resolve();
82628
+ });
82629
+ });
82630
+ }
82631
+ return connection;
82612
82632
  }
82613
82633
  async function listEmails(imapConfig, folder = "INBOX", page = 1, pageSize = 20) {
82614
82634
  const connection = await connectImap(imapConfig);
82615
82635
  try {
82616
82636
  await connection.openBox(folder);
82617
- const results = await connection.search(["ALL"], {
82618
- bodies: ["HEADER", "TEXT"],
82619
- struct: true,
82637
+ const startTime = Date.now();
82638
+ const uidResults = await connection.search(["ALL"], {
82639
+ bodies: [],
82640
+ struct: false,
82620
82641
  markSeen: false
82621
82642
  });
82622
- const sortedResults = results.sort((a, b) => {
82643
+ const sortedResults = uidResults.sort((a, b) => {
82623
82644
  const dateA = new Date(a.attributes.date || 0).getTime();
82624
82645
  const dateB = new Date(b.attributes.date || 0).getTime();
82625
82646
  return dateB - dateA;
@@ -82629,24 +82650,54 @@ async function listEmails(imapConfig, folder = "INBOX", page = 1, pageSize = 20)
82629
82650
  const pageResults = sortedResults.slice(startIndex, endIndex);
82630
82651
  const summaries = [];
82631
82652
  for (const item of pageResults) {
82632
- const header = item.parts.find((p) => p.which === "HEADER");
82633
- const text = item.parts.find((p) => p.which === "TEXT");
82634
- if (header) {
82635
- try {
82636
- const parsed = await (0, import_mailparser.simpleParser)(header.body);
82637
- const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
82638
- summaries.push({
82639
- uid,
82640
- from: parsed.from?.text || "",
82641
- to: parsed.to?.map((a) => a.text) || [],
82642
- subject: parsed.subject || "(\u65E0\u4E3B\u9898)",
82643
- date: parsed.date?.toISOString() || "",
82644
- flags: item.attributes.flags || [],
82645
- has_attachments: hasAttachments(item),
82646
- preview: text?.body ? String(text.body).substring(0, 100) : void 0
82647
- });
82648
- } catch {
82653
+ const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
82654
+ try {
82655
+ const emailResults = await connection.search([["UID", uid]], {
82656
+ bodies: ["HEADER"],
82657
+ struct: true,
82658
+ markSeen: false
82659
+ });
82660
+ if (emailResults.length > 0) {
82661
+ const emailItem = emailResults[0];
82662
+ const header = emailItem.parts.find((p) => p.which === "HEADER");
82663
+ if (header && header.body && typeof header.body === "object") {
82664
+ const headerObj = header.body;
82665
+ const from = Array.isArray(headerObj["from"]) ? headerObj["from"][0] : headerObj["from"] || "";
82666
+ const toArray = Array.isArray(headerObj["to"]) ? headerObj["to"] : headerObj["to"] ? [String(headerObj["to"])] : [];
82667
+ const subject = Array.isArray(headerObj["subject"]) ? headerObj["subject"][0] : headerObj["subject"] || "(\u65E0\u4E3B\u9898)";
82668
+ const dateStr = Array.isArray(headerObj["date"]) ? headerObj["date"][0] : headerObj["date"] || "";
82669
+ summaries.push({
82670
+ uid,
82671
+ from: String(from),
82672
+ to: toArray.map(String),
82673
+ subject: String(subject),
82674
+ date: dateStr ? new Date(dateStr).toISOString() : "",
82675
+ flags: emailItem.attributes.flags || [],
82676
+ has_attachments: hasAttachments(emailItem),
82677
+ preview: void 0
82678
+ });
82679
+ } else {
82680
+ summaries.push({
82681
+ uid,
82682
+ from: "",
82683
+ to: [],
82684
+ subject: "(\u65E0\u6CD5\u89E3\u6790\u5934\u90E8)",
82685
+ date: item.attributes.date?.toISOString() || "",
82686
+ flags: item.attributes.flags || [],
82687
+ has_attachments: false
82688
+ });
82689
+ }
82649
82690
  }
82691
+ } catch {
82692
+ summaries.push({
82693
+ uid,
82694
+ from: "",
82695
+ to: [],
82696
+ subject: "(\u89E3\u6790\u5931\u8D25)",
82697
+ date: item.attributes.date?.toISOString() || "",
82698
+ flags: item.attributes.flags || [],
82699
+ has_attachments: false
82700
+ });
82650
82701
  }
82651
82702
  }
82652
82703
  return summaries;
@@ -82750,21 +82801,22 @@ async function searchEmails(imapConfig, query, folder = "INBOX", page = 1, pageS
82750
82801
  const summaries = [];
82751
82802
  for (const item of pageResults) {
82752
82803
  const header = item.parts.find((p) => p.which === "HEADER");
82753
- if (header) {
82754
- try {
82755
- const parsed = await (0, import_mailparser.simpleParser)(header.body);
82756
- const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
82757
- summaries.push({
82758
- uid,
82759
- from: parsed.from?.text || "",
82760
- to: parsed.to?.map((a) => a.text) || [],
82761
- subject: parsed.subject || "(\u65E0\u4E3B\u9898)",
82762
- date: parsed.date?.toISOString() || "",
82763
- flags: item.attributes.flags || [],
82764
- has_attachments: hasAttachments(item)
82765
- });
82766
- } catch {
82767
- }
82804
+ const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
82805
+ if (header && header.body && typeof header.body === "object") {
82806
+ const headerObj = header.body;
82807
+ const from = Array.isArray(headerObj["from"]) ? headerObj["from"][0] : headerObj["from"] || "";
82808
+ const toArray = Array.isArray(headerObj["to"]) ? headerObj["to"] : headerObj["to"] ? [String(headerObj["to"])] : [];
82809
+ const subject = Array.isArray(headerObj["subject"]) ? headerObj["subject"][0] : headerObj["subject"] || "(\u65E0\u4E3B\u9898)";
82810
+ const dateStr = Array.isArray(headerObj["date"]) ? headerObj["date"][0] : headerObj["date"] || "";
82811
+ summaries.push({
82812
+ uid,
82813
+ from: String(from),
82814
+ to: toArray.map(String),
82815
+ subject: String(subject),
82816
+ date: dateStr ? new Date(dateStr).toISOString() : "",
82817
+ flags: item.attributes.flags || [],
82818
+ has_attachments: hasAttachments(item)
82819
+ });
82768
82820
  }
82769
82821
  }
82770
82822
  return summaries;
@@ -82776,10 +82828,17 @@ async function testImapConnection(config2) {
82776
82828
  try {
82777
82829
  const connection = await connectImap(config2);
82778
82830
  await connection.openBox("INBOX");
82831
+ let folders = [];
82832
+ try {
82833
+ const boxes = await connection.getBoxes();
82834
+ folders = Object.keys(boxes);
82835
+ } catch {
82836
+ }
82779
82837
  connection.end();
82780
82838
  return {
82781
82839
  success: true,
82782
- message: `IMAP \u8FDE\u63A5\u6210\u529F (${config2.host}:${config2.port})`
82840
+ message: `IMAP \u8FDE\u63A5\u6210\u529F (${config2.host}:${config2.port})`,
82841
+ folders
82783
82842
  };
82784
82843
  } catch (error2) {
82785
82844
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
@@ -83337,7 +83396,8 @@ server.registerTool(
83337
83396
  text: JSON.stringify({
83338
83397
  success: smtpResult.success && imapResult.success,
83339
83398
  smtp: smtpResult,
83340
- imap: imapResult
83399
+ imap: imapResult,
83400
+ folders: imapResult.folders
83341
83401
  }, null, 2)
83342
83402
  }]
83343
83403
  };
package/dist/cli.js CHANGED
@@ -65636,6 +65636,10 @@ async function testSmtpConnection(config) {
65636
65636
  // src/services/imap.ts
65637
65637
  var import_imap_simple = __toESM(require_imap_simple());
65638
65638
  var import_mailparser = __toESM(require_mailparser());
65639
+ function isNeteaseMailbox(host) {
65640
+ const neteasePatterns = ["163.com", "126.com", "netease.com", "188.com"];
65641
+ return neteasePatterns.some((pattern) => host.includes(pattern));
65642
+ }
65639
65643
  function createImapConfig(config) {
65640
65644
  return {
65641
65645
  imap: {
@@ -65654,18 +65658,35 @@ function createImapConfig(config) {
65654
65658
  }
65655
65659
  async function connectImap(config) {
65656
65660
  const imapConfig = createImapConfig(config);
65657
- return await import_imap_simple.default.connect(imapConfig);
65661
+ const connection = await import_imap_simple.default.connect(imapConfig);
65662
+ if (isNeteaseMailbox(config.host) && connection.imap.serverSupports("ID")) {
65663
+ await new Promise((resolve, reject) => {
65664
+ connection.imap.id({
65665
+ name: "EmailMCP",
65666
+ version: "1.0",
65667
+ vendor: "Weijingwei",
65668
+ "support-email": config.username
65669
+ }, (err) => {
65670
+ if (err)
65671
+ reject(err);
65672
+ else
65673
+ resolve();
65674
+ });
65675
+ });
65676
+ }
65677
+ return connection;
65658
65678
  }
65659
65679
  async function listEmails(imapConfig, folder = "INBOX", page = 1, pageSize = 20) {
65660
65680
  const connection = await connectImap(imapConfig);
65661
65681
  try {
65662
65682
  await connection.openBox(folder);
65663
- const results = await connection.search(["ALL"], {
65664
- bodies: ["HEADER", "TEXT"],
65665
- struct: true,
65683
+ const startTime = Date.now();
65684
+ const uidResults = await connection.search(["ALL"], {
65685
+ bodies: [],
65686
+ struct: false,
65666
65687
  markSeen: false
65667
65688
  });
65668
- const sortedResults = results.sort((a, b) => {
65689
+ const sortedResults = uidResults.sort((a, b) => {
65669
65690
  const dateA = new Date(a.attributes.date || 0).getTime();
65670
65691
  const dateB = new Date(b.attributes.date || 0).getTime();
65671
65692
  return dateB - dateA;
@@ -65675,24 +65696,54 @@ async function listEmails(imapConfig, folder = "INBOX", page = 1, pageSize = 20)
65675
65696
  const pageResults = sortedResults.slice(startIndex, endIndex);
65676
65697
  const summaries = [];
65677
65698
  for (const item of pageResults) {
65678
- const header = item.parts.find((p) => p.which === "HEADER");
65679
- const text = item.parts.find((p) => p.which === "TEXT");
65680
- if (header) {
65681
- try {
65682
- const parsed = await (0, import_mailparser.simpleParser)(header.body);
65683
- const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
65684
- summaries.push({
65685
- uid,
65686
- from: parsed.from?.text || "",
65687
- to: parsed.to?.map((a) => a.text) || [],
65688
- subject: parsed.subject || "(\u65E0\u4E3B\u9898)",
65689
- date: parsed.date?.toISOString() || "",
65690
- flags: item.attributes.flags || [],
65691
- has_attachments: hasAttachments(item),
65692
- preview: text?.body ? String(text.body).substring(0, 100) : void 0
65693
- });
65694
- } catch {
65699
+ const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
65700
+ try {
65701
+ const emailResults = await connection.search([["UID", uid]], {
65702
+ bodies: ["HEADER"],
65703
+ struct: true,
65704
+ markSeen: false
65705
+ });
65706
+ if (emailResults.length > 0) {
65707
+ const emailItem = emailResults[0];
65708
+ const header = emailItem.parts.find((p) => p.which === "HEADER");
65709
+ if (header && header.body && typeof header.body === "object") {
65710
+ const headerObj = header.body;
65711
+ const from = Array.isArray(headerObj["from"]) ? headerObj["from"][0] : headerObj["from"] || "";
65712
+ const toArray = Array.isArray(headerObj["to"]) ? headerObj["to"] : headerObj["to"] ? [String(headerObj["to"])] : [];
65713
+ const subject = Array.isArray(headerObj["subject"]) ? headerObj["subject"][0] : headerObj["subject"] || "(\u65E0\u4E3B\u9898)";
65714
+ const dateStr = Array.isArray(headerObj["date"]) ? headerObj["date"][0] : headerObj["date"] || "";
65715
+ summaries.push({
65716
+ uid,
65717
+ from: String(from),
65718
+ to: toArray.map(String),
65719
+ subject: String(subject),
65720
+ date: dateStr ? new Date(dateStr).toISOString() : "",
65721
+ flags: emailItem.attributes.flags || [],
65722
+ has_attachments: hasAttachments(emailItem),
65723
+ preview: void 0
65724
+ });
65725
+ } else {
65726
+ summaries.push({
65727
+ uid,
65728
+ from: "",
65729
+ to: [],
65730
+ subject: "(\u65E0\u6CD5\u89E3\u6790\u5934\u90E8)",
65731
+ date: item.attributes.date?.toISOString() || "",
65732
+ flags: item.attributes.flags || [],
65733
+ has_attachments: false
65734
+ });
65735
+ }
65695
65736
  }
65737
+ } catch {
65738
+ summaries.push({
65739
+ uid,
65740
+ from: "",
65741
+ to: [],
65742
+ subject: "(\u89E3\u6790\u5931\u8D25)",
65743
+ date: item.attributes.date?.toISOString() || "",
65744
+ flags: item.attributes.flags || [],
65745
+ has_attachments: false
65746
+ });
65696
65747
  }
65697
65748
  }
65698
65749
  return summaries;
@@ -65796,21 +65847,22 @@ async function searchEmails(imapConfig, query, folder = "INBOX", page = 1, pageS
65796
65847
  const summaries = [];
65797
65848
  for (const item of pageResults) {
65798
65849
  const header = item.parts.find((p) => p.which === "HEADER");
65799
- if (header) {
65800
- try {
65801
- const parsed = await (0, import_mailparser.simpleParser)(header.body);
65802
- const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
65803
- summaries.push({
65804
- uid,
65805
- from: parsed.from?.text || "",
65806
- to: parsed.to?.map((a) => a.text) || [],
65807
- subject: parsed.subject || "(\u65E0\u4E3B\u9898)",
65808
- date: parsed.date?.toISOString() || "",
65809
- flags: item.attributes.flags || [],
65810
- has_attachments: hasAttachments(item)
65811
- });
65812
- } catch {
65813
- }
65850
+ const uid = typeof item.attributes.uid === "number" ? item.attributes.uid : 0;
65851
+ if (header && header.body && typeof header.body === "object") {
65852
+ const headerObj = header.body;
65853
+ const from = Array.isArray(headerObj["from"]) ? headerObj["from"][0] : headerObj["from"] || "";
65854
+ const toArray = Array.isArray(headerObj["to"]) ? headerObj["to"] : headerObj["to"] ? [String(headerObj["to"])] : [];
65855
+ const subject = Array.isArray(headerObj["subject"]) ? headerObj["subject"][0] : headerObj["subject"] || "(\u65E0\u4E3B\u9898)";
65856
+ const dateStr = Array.isArray(headerObj["date"]) ? headerObj["date"][0] : headerObj["date"] || "";
65857
+ summaries.push({
65858
+ uid,
65859
+ from: String(from),
65860
+ to: toArray.map(String),
65861
+ subject: String(subject),
65862
+ date: dateStr ? new Date(dateStr).toISOString() : "",
65863
+ flags: item.attributes.flags || [],
65864
+ has_attachments: hasAttachments(item)
65865
+ });
65814
65866
  }
65815
65867
  }
65816
65868
  return summaries;
@@ -65822,10 +65874,17 @@ async function testImapConnection(config) {
65822
65874
  try {
65823
65875
  const connection = await connectImap(config);
65824
65876
  await connection.openBox("INBOX");
65877
+ let folders = [];
65878
+ try {
65879
+ const boxes = await connection.getBoxes();
65880
+ folders = Object.keys(boxes);
65881
+ } catch {
65882
+ }
65825
65883
  connection.end();
65826
65884
  return {
65827
65885
  success: true,
65828
- message: `IMAP \u8FDE\u63A5\u6210\u529F (${config.host}:${config.port})`
65886
+ message: `IMAP \u8FDE\u63A5\u6210\u529F (${config.host}:${config.port})`,
65887
+ folders
65829
65888
  };
65830
65889
  } catch (error) {
65831
65890
  const errorMessage = error instanceof Error ? error.message : String(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weijingwei/email",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Email MCP Server - SMTP/IMAP email operations via MCP protocol",
5
5
  "main": "dist/bundle.js",
6
6
  "bin": {