@lengelhard/imap-email-mcp 1.0.4 → 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 (2) hide show
  1. package/index.js +61 -60
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -347,30 +347,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
347
347
  required: ['to', 'subject']
348
348
  }
349
349
  },
350
- {
351
- name: 'move_email',
352
- description: 'Move an email from one folder to another (e.g. INBOX to Archive)',
353
- inputSchema: {
354
- type: 'object',
355
- properties: {
356
- uid: {
357
- type: 'number',
358
- description: 'Email UID to move'
359
- },
360
- from_folder: {
361
- type: 'string',
362
- description: 'Source folder (default: INBOX)',
363
- default: 'INBOX'
364
- },
365
- to_folder: {
366
- type: 'string',
367
- description: 'Destination folder (e.g. Archive, Sent, Trash)',
368
- default: 'Archive'
369
- }
370
- },
371
- required: ['uid']
372
- }
373
- },
374
350
  {
375
351
  name: 'delete_email',
376
352
  description: 'Delete an email by UID',
@@ -781,55 +757,80 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
781
757
  bcc: args.bcc
782
758
  };
783
759
 
760
+ // Send via SMTP and capture the raw RFC 5322 message
784
761
  const info = await transporter.sendMail(mailOptions);
785
762
 
763
+ // Build RFC 5322 message string to APPEND to Sent folder via IMAP
764
+ // Use the same content that was sent so the Sent copy is identical
765
+ const sentDate = new Date();
766
+ const boundary = `----=_Part_${Date.now()}`;
767
+ let rawMessage = '';
768
+ rawMessage += `From: ${SMTP_CONFIG.auth.user}\r\n`;
769
+ rawMessage += `To: ${args.to}\r\n`;
770
+ if (args.cc) rawMessage += `Cc: ${args.cc}\r\n`;
771
+ if (args.bcc) rawMessage += `Bcc: ${args.bcc}\r\n`;
772
+ rawMessage += `Subject: ${args.subject}\r\n`;
773
+ rawMessage += `Date: ${sentDate.toUTCString()}\r\n`;
774
+ rawMessage += `Message-ID: ${info.messageId}\r\n`;
775
+ rawMessage += `MIME-Version: 1.0\r\n`;
776
+
777
+ if (args.html) {
778
+ rawMessage += `Content-Type: multipart/alternative; boundary="${boundary}"\r\n\r\n`;
779
+ rawMessage += `--${boundary}\r\n`;
780
+ rawMessage += `Content-Type: text/plain; charset=utf-8\r\n\r\n`;
781
+ rawMessage += `${args.body || ''}\r\n`;
782
+ rawMessage += `--${boundary}\r\n`;
783
+ rawMessage += `Content-Type: text/html; charset=utf-8\r\n\r\n`;
784
+ rawMessage += `${args.html}\r\n`;
785
+ rawMessage += `--${boundary}--\r\n`;
786
+ } else {
787
+ rawMessage += `Content-Type: text/plain; charset=utf-8\r\n\r\n`;
788
+ rawMessage += `${args.body || ''}\r\n`;
789
+ }
790
+
791
+ // APPEND to Sent folder via IMAP
792
+ let sentFolderResult = 'skipped';
793
+ try {
794
+ const connection = await connectIMAP();
795
+ try {
796
+ // Try common Sent folder names in order
797
+ const sentFolderCandidates = ['Sent', 'INBOX.Sent', 'Sent Items', 'Sent Mail', '[Gmail]/Sent Mail'];
798
+ let sentFolder = 'Sent'; // default fallback
799
+
800
+ const folders = await connection.getBoxes();
801
+ const flatFolders = Object.keys(folders);
802
+ for (const candidate of sentFolderCandidates) {
803
+ if (flatFolders.some(f => f.toLowerCase() === candidate.toLowerCase())) {
804
+ sentFolder = candidate;
805
+ break;
806
+ }
807
+ }
808
+
809
+ await connection.append(rawMessage, {
810
+ mailbox: sentFolder,
811
+ flags: ['\\Seen']
812
+ });
813
+ sentFolderResult = `saved to ${sentFolder}`;
814
+ } finally {
815
+ connection.end();
816
+ }
817
+ } catch (appendErr) {
818
+ sentFolderResult = `failed: ${appendErr.message}`;
819
+ }
820
+
786
821
  return {
787
822
  content: [{
788
823
  type: 'text',
789
824
  text: JSON.stringify({
790
825
  success: true,
791
826
  messageId: info.messageId,
792
- response: info.response
827
+ response: info.response,
828
+ sentFolder: sentFolderResult
793
829
  }, null, 2)
794
830
  }]
795
831
  };
796
832
  }
797
833
 
798
- case 'move_email': {
799
- const fromFolder = args.from_folder || 'INBOX';
800
- const toFolder = args.to_folder || 'Archive';
801
- const connection = await connectIMAP();
802
-
803
- try {
804
- await connection.openBox(fromFolder);
805
-
806
- // imap-simple exposes the underlying imap connection via ._imap
807
- // Use it to copy the message then delete the original
808
- await new Promise((resolve, reject) => {
809
- connection.imap.copy(args.uid, toFolder, (err) => {
810
- if (err) reject(err);
811
- else resolve();
812
- });
813
- });
814
-
815
- // Mark original as deleted and expunge
816
- await connection.addFlags(args.uid, ['\\Deleted']);
817
- await connection.closeBox(true); // true = expunge on close
818
-
819
- return {
820
- content: [{
821
- type: 'text',
822
- text: JSON.stringify({
823
- success: true,
824
- message: `Email ${args.uid} moved from ${fromFolder} to ${toFolder}`
825
- }, null, 2)
826
- }]
827
- };
828
- } finally {
829
- connection.end();
830
- }
831
- }
832
-
833
834
  case 'delete_email': {
834
835
  const folder = args.folder || 'INBOX';
835
836
  const connection = await connectIMAP();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lengelhard/imap-email-mcp",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "MCP server for Claude Code that provides email capabilities through IMAP/SMTP. Read, search, compose, and manage emails from any IMAP provider.",
5
5
  "type": "module",
6
6
  "main": "index.js",