email-smtp-imap-mcp 2.0.0 → 2.0.4

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/.env.example CHANGED
@@ -9,6 +9,8 @@ EMAIL_ACCOUNTS_JSON='{
9
9
  "smtp_secure": false,
10
10
  "smtp_user": "your-email@icloud.com",
11
11
  "smtp_pass": "your-app-specific-password",
12
+ "imap_user": "your-email@icloud.com",
13
+ "imap_pass": "your-app-specific-password",
12
14
  "imap_host": "imap.mail.me.com",
13
15
  "imap_port": 993,
14
16
  "imap_secure": true,
@@ -20,6 +22,8 @@ EMAIL_ACCOUNTS_JSON='{
20
22
  "smtp_secure": false,
21
23
  "smtp_user": "your-email@gmail.com",
22
24
  "smtp_pass": "your-app-specific-password",
25
+ "imap_user": "your-email@gmail.com",
26
+ "imap_pass": "your-app-specific-password",
23
27
  "imap_host": "imap.gmail.com",
24
28
  "imap_port": 993,
25
29
  "imap_secure": true,
@@ -37,9 +41,15 @@ DEFAULT_EMAIL_ACCOUNT="work"
37
41
  # SMTP_SECURE=false
38
42
  # SMTP_USER="your-email@icloud.com"
39
43
  # SMTP_PASS="your-app-specific-password"
44
+ # SMTP_USERNAME="your-email@icloud.com" # Alias for SMTP_USER
45
+ # SMTP_PASSWORD="your-app-specific-password" # Alias for SMTP_PASS
40
46
  # IMAP_HOST="imap.mail.me.com"
41
47
  # IMAP_PORT=993
42
48
  # IMAP_SECURE=true
49
+ # IMAP_USER="your-email@icloud.com"
50
+ # IMAP_PASS="your-app-specific-password"
51
+ # IMAP_USERNAME="your-email@icloud.com" # Alias for IMAP_USER
52
+ # IMAP_PASSWORD="your-app-specific-password" # Alias for IMAP_PASS
43
53
  # DEFAULT_FROM_NAME="Your Name"
44
54
 
45
55
  # ===== NOTES =====
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sami Halawa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,38 +1,36 @@
1
1
  # Email MCP Server
2
2
 
3
- A clean, simple MCP server for email operations (SMTP + IMAP).
3
+ A clean, simple stdio MCP server for email operations supporting both SMTP (sending) and IMAP (reading).
4
+
5
+ [![npm version](https://badge.fury.io/js/email-smtp-imap-mcp.svg)](https://www.npmjs.com/package/email-smtp-imap-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
7
 
5
8
  ## Features
6
9
 
7
- - ✅ **Send emails** (HTML + attachments)
8
- - ✅ **Search emails** (flexible filters)
9
- - ✅ **Reply/Forward** (with threading)
10
+ - ✅ **Send emails** with HTML and attachments
11
+ - ✅ **Search emails** with flexible filters
12
+ - ✅ **Reply/Forward** with proper threading
10
13
  - ✅ **Organize** (mark read, archive, flag)
11
- - ✅ **List folders**
14
+ - ✅ **Multi-account support** for managing multiple email accounts
15
+ - ✅ **List folders** to browse your mailbox structure
12
16
 
13
17
  ## Quick Start
14
18
 
15
- ### 1. Install
19
+ ### Installation
16
20
 
17
21
  ```bash
18
- npm install
19
- npm run build
22
+ npx -y email-smtp-imap-mcp
20
23
  ```
21
24
 
22
- ### 2. Configure
25
+ Or install globally:
23
26
 
24
- Create `.env`:
25
-
26
- ```env
27
- EMAIL_ACCOUNTS_JSON={"icloud":{"smtp":{"host":"smtp.mail.me.com","port":587,"user":"your@icloud.com","password":"your-app-password"},"imap":{"host":"imap.mail.me.com","port":993},"default_from_name":"Your Name","sender_emails":["your@icloud.com","alias@domain.com"]}}
28
- DEFAULT_EMAIL_ACCOUNT=icloud
27
+ ```bash
28
+ npm install -g email-smtp-imap-mcp
29
29
  ```
30
30
 
31
- ### 3. Add to MCP-Supported Software
31
+ ### Configuration
32
32
 
33
- #### Claude Desktop
34
-
35
- Add to your `claude_desktop_config.json`:
33
+ Add to your Claude Desktop config file:
36
34
 
37
35
  **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
38
36
  **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
@@ -41,47 +39,121 @@ Add to your `claude_desktop_config.json`:
41
39
  {
42
40
  "mcpServers": {
43
41
  "email": {
44
- "command": "node",
45
- "args": ["/absolute/path/to/email-smtp-imap-mcp/build/index.js"],
42
+ "command": "npx",
43
+ "args": ["-y", "email-smtp-imap-mcp"],
46
44
  "env": {
47
- "EMAIL_ACCOUNTS_JSON": "{\"icloud\":{\"smtp\":{\"host\":\"smtp.mail.me.com\",\"port\":587,\"user\":\"your@icloud.com\",\"password\":\"your-app-password\"},\"imap\":{\"host\":\"imap.mail.me.com\",\"port\":993},\"default_from_name\":\"Your Name\",\"sender_emails\":[\"your@icloud.com\"]}}",
48
- "DEFAULT_EMAIL_ACCOUNT": "icloud"
45
+ "EMAIL_ACCOUNTS_JSON": "{\"work\":{\"smtp\":{\"host\":\"smtp.gmail.com\",\"port\":587,\"user\":\"your@gmail.com\",\"password\":\"app-password\"},\"imap\":{\"host\":\"imap.gmail.com\",\"port\":993,\"user\":\"your@gmail.com\",\"password\":\"app-password\"},\"default_from_name\":\"Your Name\",\"sender_emails\":[\"your@gmail.com\"]}}",
46
+ "DEFAULT_EMAIL_ACCOUNT": "work"
49
47
  }
50
48
  }
51
49
  }
52
50
  }
53
51
  ```
54
52
 
55
- **Note**: Replace `/absolute/path/to/email-smtp-imap-mcp` with your actual installation path. You can also use a `.env` file instead of inline env config.
53
+ **⚠️ Important**: Restart Claude Desktop after adding this configuration.
54
+
55
+ ## Email Provider Settings
56
+
57
+ ### Gmail
58
+ ```json
59
+ "EMAIL_ACCOUNTS_JSON": "{\"gmail\":{\"smtp\":{\"host\":\"smtp.gmail.com\",\"port\":587,\"user\":\"your@gmail.com\",\"password\":\"app-password\"},\"imap\":{\"host\":\"imap.gmail.com\",\"port\":993,\"user\":\"your@gmail.com\",\"password\":\"app-password\"},\"default_from_name\":\"Your Name\",\"sender_emails\":[\"your@gmail.com\"]}}"
60
+ ```
61
+ **Setup**: [Create App Password](https://support.google.com/accounts/answer/185833)
62
+
63
+ ### iCloud Mail
64
+ ```json
65
+ "EMAIL_ACCOUNTS_JSON": "{\"icloud\":{\"smtp\":{\"host\":\"smtp.mail.me.com\",\"port\":587,\"user\":\"your@icloud.com\",\"password\":\"app-specific-password\"},\"imap\":{\"host\":\"imap.mail.me.com\",\"port\":993,\"user\":\"your@icloud.com\",\"password\":\"app-specific-password\"},\"default_from_name\":\"Your Name\",\"sender_emails\":[\"your@icloud.com\"]}}"
66
+ ```
67
+ **Setup**: [Generate App-Specific Password](https://support.apple.com/en-us/102654)
68
+
69
+ ### Outlook/Office 365
70
+ ```json
71
+ "EMAIL_ACCOUNTS_JSON": "{\"outlook\":{\"smtp\":{\"host\":\"smtp-mail.outlook.com\",\"port\":587,\"user\":\"your@outlook.com\",\"password\":\"your-password\"},\"imap\":{\"host\":\"outlook.office365.com\",\"port\":993,\"user\":\"your@outlook.com\",\"password\":\"your-password\"},\"default_from_name\":\"Your Name\",\"sender_emails\":[\"your@outlook.com\"]}}"
72
+ ```
73
+
74
+ ### Multiple Accounts
75
+ ```json
76
+ "EMAIL_ACCOUNTS_JSON": "{\"work\":{\"smtp\":{\"host\":\"smtp.gmail.com\",\"port\":587,\"user\":\"work@company.com\",\"password\":\"app-password\"},\"imap\":{\"host\":\"imap.gmail.com\",\"port\":993,\"user\":\"work@company.com\",\"password\":\"app-password\"},\"default_from_name\":\"John Doe\"},\"personal\":{\"smtp\":{\"host\":\"smtp.mail.me.com\",\"port\":587,\"user\":\"me@icloud.com\",\"password\":\"app-password\"},\"imap\":{\"host\":\"imap.mail.me.com\",\"port\":993,\"user\":\"me@icloud.com\",\"password\":\"app-password\"},\"default_from_name\":\"John\"}}",
77
+ "DEFAULT_EMAIL_ACCOUNT": "work"
78
+ ```
56
79
 
57
- Restart Claude Desktop to load the MCP server.
80
+ The server also accepts flat or single-account environment variables. For compatibility, `SMTP_USERNAME`/`SMTP_PASSWORD` are aliases for `SMTP_USER`/`SMTP_PASS`, `IMAP_USERNAME`/`IMAP_PASSWORD` are aliases for `IMAP_USER`/`IMAP_PASS`, and `IMAP_USER`/`IMAP_PASS` fall back to the SMTP credentials when omitted.
58
81
 
59
- ## 5 Tools
82
+ ## Available Tools
60
83
 
61
- | Tool | Purpose |
62
- |------|---------|
63
- | `emails_find` | Search emails with filters |
64
- | `emails_modify` | Mark read, archive, flag |
65
- | `email_send` | Send new emails |
66
- | `email_respond` | Reply or forward |
67
- | `folders_list` | List folders |
84
+ | Tool | Description |
85
+ |------|-------------|
86
+ | `emails_find` | Search emails with flexible filters (sender, subject, date, attachments, etc.) |
87
+ | `emails_modify` | Mark as read/unread, flag, archive, or move emails |
88
+ | `email_send` | Send new emails with HTML content and attachments |
89
+ | `email_respond` | Reply or forward emails with proper threading |
90
+ | `folders_list` | List all available email folders |
68
91
 
69
92
  ## Usage Examples
70
93
 
94
+ Ask Claude to:
95
+
96
+ - "Find unread emails from last week"
97
+ - "Send an email to team@company.com about the meeting"
98
+ - "Reply to the last email from Sarah"
99
+ - "Archive all emails older than 30 days"
100
+ - "List my email folders"
101
+ - "Find emails with attachments from my boss"
102
+ - "Mark all emails from newsletter@site.com as read"
103
+
104
+ ## Security Notes
105
+
106
+ - **Never commit** `.env` files or credentials to version control
107
+ - Use **app-specific passwords** or **app passwords**, not your main account password
108
+ - The server runs **locally** on your machine - credentials stay private
109
+ - All email connections use **TLS encryption** (ports 587 for SMTP, 993 for IMAP)
110
+
111
+ ## Development
112
+
113
+ ```bash
114
+ # Clone the repository
115
+ git clone https://github.com/samihalawa/email-smtp-imap-mcp.git
116
+ cd email-smtp-imap-mcp
117
+
118
+ # Install dependencies
119
+ npm install
120
+
121
+ # Build
122
+ npm run build
123
+
124
+ # Run locally
125
+ npm start
71
126
  ```
72
- "Find unread emails from last week"
73
- "Send an email to team@company.com"
74
- "Reply to the last email from John"
75
- "Archive all emails older than 30 days"
76
- "List my email folders"
77
- ```
78
127
 
79
- ## Documentation
128
+ ## Troubleshooting
129
+
130
+ ### Authentication Errors
131
+ - Make sure you're using an **app password**, not your regular password
132
+ - For Gmail: [Create App Password](https://support.google.com/accounts/answer/185833)
133
+ - For iCloud: [Generate App-Specific Password](https://support.apple.com/en-us/102654)
134
+
135
+ ### Server Not Starting
136
+ - Verify your configuration JSON is properly escaped
137
+ - Check that ports 587 (SMTP) and 993 (IMAP) are not blocked by your firewall
138
+ - Restart Claude Desktop after configuration changes
80
139
 
81
- - **QUICK_REFERENCE.md** - Command examples
82
- - **DESIGN.md** - Architecture details
83
- - **SETUP_COMPLETE.md** - Full setup guide
140
+ ### Connection Issues
141
+ - Confirm your email provider allows IMAP/SMTP access
142
+ - Check your internet connection
143
+ - Verify the SMTP/IMAP host and port settings for your provider
84
144
 
85
145
  ## License
86
146
 
87
- MIT
147
+ MIT License - see [LICENSE](LICENSE) file for details
148
+
149
+ ## Contributing
150
+
151
+ Contributions are welcome! Please feel free to submit a Pull Request.
152
+
153
+ ## Author
154
+
155
+ **Sami Halawa** - [GitHub](https://github.com/samihalawa)
156
+
157
+ ---
158
+
159
+ Made with ❤️ for the MCP community
@@ -1,6 +1,48 @@
1
1
  /**
2
2
  * Email account configuration management
3
3
  */
4
+ function firstDefined(...values) {
5
+ return values.find((value) => value !== undefined && value !== '') || '';
6
+ }
7
+ function parsePort(value, fallback) {
8
+ if (typeof value === 'number')
9
+ return value;
10
+ if (typeof value === 'string' && value.trim() !== '') {
11
+ const parsed = Number.parseInt(value, 10);
12
+ if (!Number.isNaN(parsed))
13
+ return parsed;
14
+ }
15
+ return fallback;
16
+ }
17
+ function toBoolean(value, fallback) {
18
+ if (value === undefined || value === null || value === '')
19
+ return fallback;
20
+ if (typeof value === 'boolean')
21
+ return value;
22
+ return String(value).toLowerCase() === 'true';
23
+ }
24
+ function normalizeAccountConfig(cfg) {
25
+ const smtp = cfg.smtp || {};
26
+ const imap = cfg.imap || {};
27
+ const smtpUser = firstDefined(smtp.user, cfg.smtp_user, cfg.SMTP_USER, cfg.SMTP_USERNAME);
28
+ const smtpPass = firstDefined(smtp.password, smtp.pass, cfg.smtp_pass, cfg.SMTP_PASS, cfg.SMTP_PASSWORD);
29
+ const imapUser = firstDefined(imap.user, imap.username, cfg.imap_user, cfg.IMAP_USER, cfg.IMAP_USERNAME, smtpUser);
30
+ const imapPass = firstDefined(imap.password, imap.pass, cfg.imap_pass, cfg.IMAP_PASS, cfg.IMAP_PASSWORD, smtpPass);
31
+ return {
32
+ smtp_host: firstDefined(smtp.host, cfg.smtp_host, cfg.SMTP_HOST, cfg.SMTP_SERVER, cfg.MTP_SERVER),
33
+ smtp_port: parsePort(smtp.port ?? cfg.smtp_port ?? cfg.SMTP_PORT, 587),
34
+ smtp_secure: toBoolean(smtp.secure ?? cfg.smtp_secure ?? cfg.SMTP_SECURE, parsePort(smtp.port ?? cfg.smtp_port ?? cfg.SMTP_PORT, 587) === 465),
35
+ smtp_user: smtpUser,
36
+ smtp_pass: smtpPass,
37
+ imap_user: imapUser,
38
+ imap_pass: imapPass,
39
+ imap_host: firstDefined(imap.host, cfg.imap_host, cfg.IMAP_HOST, cfg.IMAP_SERVER),
40
+ imap_port: parsePort(imap.port ?? cfg.imap_port ?? cfg.IMAP_PORT, 993),
41
+ imap_secure: toBoolean(imap.secure ?? cfg.imap_secure ?? cfg.IMAP_SECURE, parsePort(imap.port ?? cfg.imap_port ?? cfg.IMAP_PORT, 993) === 993),
42
+ default_from_name: cfg.default_from_name || cfg.DEFAULT_FROM_NAME,
43
+ sender_emails: cfg.sender_emails || cfg.SENDER_EMAILS
44
+ };
45
+ }
4
46
  /**
5
47
  * Load email accounts from environment variables
6
48
  */
@@ -9,7 +51,14 @@ export function loadAccounts() {
9
51
  const jsonConfig = process.env.EMAIL_ACCOUNTS_JSON;
10
52
  if (jsonConfig) {
11
53
  try {
12
- return JSON.parse(jsonConfig);
54
+ const parsed = JSON.parse(jsonConfig);
55
+ // Transform nested structure to flat structure
56
+ const accounts = {};
57
+ for (const [accountName, config] of Object.entries(parsed)) {
58
+ const cfg = config;
59
+ accounts[accountName] = normalizeAccountConfig(cfg);
60
+ }
61
+ return accounts;
13
62
  }
14
63
  catch (error) {
15
64
  throw new Error(`Failed to parse EMAIL_ACCOUNTS_JSON: ${error}`);
@@ -17,19 +66,34 @@ export function loadAccounts() {
17
66
  }
18
67
  // Fall back to single account from individual ENV vars
19
68
  const singleAccount = {
20
- smtp_host: process.env.SMTP_HOST || '',
21
- smtp_port: parseInt(process.env.SMTP_PORT || '587'),
22
- smtp_secure: process.env.SMTP_SECURE === 'true',
23
- smtp_user: process.env.SMTP_USER || '',
24
- smtp_pass: process.env.SMTP_PASS || '',
25
- imap_host: process.env.IMAP_HOST || '',
26
- imap_port: parseInt(process.env.IMAP_PORT || '993'),
27
- imap_secure: process.env.IMAP_SECURE !== 'false', // Default to true
69
+ smtp_host: firstDefined(process.env.SMTP_HOST, process.env.SMTP_SERVER, process.env.MTP_SERVER),
70
+ smtp_port: parsePort(process.env.SMTP_PORT, 587),
71
+ smtp_secure: toBoolean(process.env.SMTP_SECURE, parsePort(process.env.SMTP_PORT, 587) === 465),
72
+ smtp_user: firstDefined(process.env.SMTP_USER, process.env.SMTP_USERNAME),
73
+ smtp_pass: firstDefined(process.env.SMTP_PASS, process.env.SMTP_PASSWORD),
74
+ imap_user: firstDefined(process.env.IMAP_USER, process.env.IMAP_USERNAME, process.env.SMTP_USER, process.env.SMTP_USERNAME),
75
+ imap_pass: firstDefined(process.env.IMAP_PASS, process.env.IMAP_PASSWORD, process.env.SMTP_PASS, process.env.SMTP_PASSWORD),
76
+ imap_host: firstDefined(process.env.IMAP_HOST, process.env.IMAP_SERVER),
77
+ imap_port: parsePort(process.env.IMAP_PORT, 993),
78
+ imap_secure: toBoolean(process.env.IMAP_SECURE, parsePort(process.env.IMAP_PORT, 993) === 993),
28
79
  default_from_name: process.env.DEFAULT_FROM_NAME
29
80
  };
30
81
  // Validate single account has required fields
31
- if (!singleAccount.smtp_host || !singleAccount.smtp_user || !singleAccount.smtp_pass) {
32
- throw new Error('Email account configuration not found. Set EMAIL_ACCOUNTS_JSON or individual SMTP_* variables.');
82
+ const missingFields = [];
83
+ if (!singleAccount.smtp_host)
84
+ missingFields.push('SMTP_HOST');
85
+ if (!singleAccount.smtp_user)
86
+ missingFields.push('SMTP_USER');
87
+ if (!singleAccount.smtp_pass)
88
+ missingFields.push('SMTP_PASS');
89
+ if (!singleAccount.imap_host)
90
+ missingFields.push('IMAP_HOST');
91
+ if (!singleAccount.imap_user)
92
+ missingFields.push('IMAP_USER');
93
+ if (!singleAccount.imap_pass)
94
+ missingFields.push('IMAP_PASS');
95
+ if (missingFields.length > 0) {
96
+ throw new Error(`Missing required email configuration: ${missingFields.join(', ')}. Set EMAIL_ACCOUNTS_JSON or individual environment variables.`);
33
97
  }
34
98
  // Use DEFAULT_EMAIL_ACCOUNT as the account name, or "default"
35
99
  const accountName = process.env.DEFAULT_EMAIL_ACCOUNT || 'default';
@@ -18,6 +18,7 @@ export async function handleEmailsFind(args) {
18
18
  return JSON.stringify({
19
19
  success: true,
20
20
  account: name,
21
+ total_found: emails.length,
21
22
  count: emails.length,
22
23
  emails
23
24
  }, null, 2);