@honest-magic/mail-mcp 1.0.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.
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/cli/accounts.d.ts +7 -0
- package/dist/cli/accounts.js +171 -0
- package/dist/cli/accounts.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.js +48 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +658 -0
- package/dist/index.js +556 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/imap.d.ts +29 -0
- package/dist/protocol/imap.js +255 -0
- package/dist/protocol/imap.js.map +1 -0
- package/dist/protocol/smtp.d.ts +8 -0
- package/dist/protocol/smtp.js +56 -0
- package/dist/protocol/smtp.js.map +1 -0
- package/dist/security/keychain.d.ts +3 -0
- package/dist/security/keychain.js +18 -0
- package/dist/security/keychain.js.map +1 -0
- package/dist/security/oauth2.d.ts +9 -0
- package/dist/security/oauth2.js +51 -0
- package/dist/security/oauth2.js.map +1 -0
- package/dist/services/mail.d.ts +45 -0
- package/dist/services/mail.js +200 -0
- package/dist/services/mail.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/markdown.d.ts +1 -0
- package/dist/utils/markdown.js +11 -0
- package/dist/utils/markdown.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { ImapClient } from '../protocol/imap.js';
|
|
2
|
+
import { SmtpClient } from '../protocol/smtp.js';
|
|
3
|
+
import { htmlToMarkdown } from '../utils/markdown.js';
|
|
4
|
+
export class MailService {
|
|
5
|
+
readOnly;
|
|
6
|
+
imapClient;
|
|
7
|
+
smtpClient;
|
|
8
|
+
account;
|
|
9
|
+
smtpConnected = false;
|
|
10
|
+
constructor(account, readOnly = false) {
|
|
11
|
+
this.readOnly = readOnly;
|
|
12
|
+
this.account = account;
|
|
13
|
+
this.imapClient = new ImapClient(account);
|
|
14
|
+
this.smtpClient = new SmtpClient(account);
|
|
15
|
+
}
|
|
16
|
+
async connect() {
|
|
17
|
+
await this.imapClient.connect();
|
|
18
|
+
}
|
|
19
|
+
async ensureSmtp() {
|
|
20
|
+
if (!this.smtpConnected) {
|
|
21
|
+
await this.smtpClient.connect();
|
|
22
|
+
this.smtpConnected = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async disconnect() {
|
|
26
|
+
await this.imapClient.disconnect();
|
|
27
|
+
// nodemailer transporter doesn't strictly need closing, but good practice if pooling
|
|
28
|
+
}
|
|
29
|
+
async listEmails(folder = 'INBOX', count = 10) {
|
|
30
|
+
return this.imapClient.listMessages(folder, count);
|
|
31
|
+
}
|
|
32
|
+
async searchEmails(query, folder = 'INBOX', count = 10) {
|
|
33
|
+
const criteria = {};
|
|
34
|
+
if (query.from)
|
|
35
|
+
criteria.from = query.from;
|
|
36
|
+
if (query.subject)
|
|
37
|
+
criteria.subject = query.subject;
|
|
38
|
+
if (query.since)
|
|
39
|
+
criteria.since = query.since;
|
|
40
|
+
if (query.before)
|
|
41
|
+
criteria.before = query.before;
|
|
42
|
+
if (query.keywords)
|
|
43
|
+
criteria.body = query.keywords;
|
|
44
|
+
return this.imapClient.searchMessages(criteria, folder, count);
|
|
45
|
+
}
|
|
46
|
+
async sendEmail(to, subject, body, isHtml = false, cc, bcc) {
|
|
47
|
+
// Build raw message before sending so we can append to Sent folder
|
|
48
|
+
const rawMessage = [
|
|
49
|
+
`From: ${this.account.user}`,
|
|
50
|
+
`To: ${to}`,
|
|
51
|
+
...(cc ? [`Cc: ${cc}`] : []),
|
|
52
|
+
...(bcc ? [`Bcc: ${bcc}`] : []),
|
|
53
|
+
`Subject: ${subject}`,
|
|
54
|
+
'MIME-Version: 1.0',
|
|
55
|
+
`Content-Type: ${isHtml ? 'text/html' : 'text/plain'}; charset=utf-8`,
|
|
56
|
+
'',
|
|
57
|
+
body
|
|
58
|
+
].join('\r\n');
|
|
59
|
+
await this.ensureSmtp();
|
|
60
|
+
const info = await this.smtpClient.send(to, subject, body, isHtml, cc, bcc);
|
|
61
|
+
try {
|
|
62
|
+
await this.imapClient.appendMessage('Sent', rawMessage, ['\\Seen']);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
console.error('Failed to append to Sent folder:', e);
|
|
66
|
+
}
|
|
67
|
+
return info;
|
|
68
|
+
}
|
|
69
|
+
async createDraft(to, subject, body, isHtml = false, cc, bcc) {
|
|
70
|
+
const headers = [
|
|
71
|
+
`From: ${this.account.user}`,
|
|
72
|
+
`To: ${to}`,
|
|
73
|
+
...(cc ? [`Cc: ${cc}`] : []),
|
|
74
|
+
...(bcc ? [`Bcc: ${bcc}`] : []),
|
|
75
|
+
`Subject: ${subject}`,
|
|
76
|
+
'MIME-Version: 1.0',
|
|
77
|
+
`Content-Type: ${isHtml ? 'text/html' : 'text/plain'}; charset=utf-8`,
|
|
78
|
+
'',
|
|
79
|
+
body
|
|
80
|
+
].join('\r\n');
|
|
81
|
+
await this.imapClient.appendMessage('Drafts', headers, ['\\Draft']);
|
|
82
|
+
}
|
|
83
|
+
async readEmail(uid, folder = 'INBOX') {
|
|
84
|
+
const parsed = await this.imapClient.fetchMessageBody(uid, folder);
|
|
85
|
+
let content = '';
|
|
86
|
+
if (parsed.html) {
|
|
87
|
+
let html = parsed.html;
|
|
88
|
+
// Convert inline images to base64 if needed
|
|
89
|
+
if (parsed.attachments) {
|
|
90
|
+
for (const att of parsed.attachments) {
|
|
91
|
+
if (att.contentId && att.content && att.contentType.startsWith('image/')) {
|
|
92
|
+
const base64 = att.content.toString('base64');
|
|
93
|
+
const dataUri = `data:${att.contentType};base64,${base64}`;
|
|
94
|
+
const cidRegex = new RegExp(`cid:${att.contentId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`, 'g');
|
|
95
|
+
html = html.replace(cidRegex, dataUri);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
content = htmlToMarkdown(html);
|
|
100
|
+
}
|
|
101
|
+
else if (parsed.textAsHtml) {
|
|
102
|
+
content = htmlToMarkdown(parsed.textAsHtml);
|
|
103
|
+
}
|
|
104
|
+
else if (parsed.text) {
|
|
105
|
+
content = parsed.text;
|
|
106
|
+
}
|
|
107
|
+
let attachmentInfo = '';
|
|
108
|
+
if (parsed.attachments && parsed.attachments.length > 0) {
|
|
109
|
+
attachmentInfo = '\n\n**Attachments:**\n';
|
|
110
|
+
parsed.attachments.forEach(att => {
|
|
111
|
+
attachmentInfo += `- ${att.filename || 'Unnamed'} (${att.contentType}, ${Math.round(att.size / 1024)} KB)\n`;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
let header = `**From:** ${parsed.from?.text || 'Unknown'}\n`;
|
|
115
|
+
const toText = Array.isArray(parsed.to) ? parsed.to.map(t => t.text).join(', ') : parsed.to?.text;
|
|
116
|
+
header += `**To:** ${toText || 'Unknown'}\n`;
|
|
117
|
+
if (parsed.cc) {
|
|
118
|
+
const ccText = Array.isArray(parsed.cc) ? parsed.cc.map(t => t.text).join(', ') : parsed.cc.text;
|
|
119
|
+
header += `**Cc:** ${ccText}\n`;
|
|
120
|
+
}
|
|
121
|
+
header += `**Subject:** ${parsed.subject || 'No Subject'}\n`;
|
|
122
|
+
header += `**Date:** ${parsed.date?.toISOString() || 'Unknown'}\n`;
|
|
123
|
+
// Check for thread ID in headers
|
|
124
|
+
const threadId = parsed.headers.get('x-gm-thrid');
|
|
125
|
+
if (threadId) {
|
|
126
|
+
header += `**Thread ID:** ${threadId}\n`;
|
|
127
|
+
}
|
|
128
|
+
// Expose Message-ID so non-Gmail callers have a threadId for get_thread
|
|
129
|
+
const messageId = parsed.messageId || parsed.headers.get('message-id');
|
|
130
|
+
if (messageId) {
|
|
131
|
+
header += `**Message-ID:** ${messageId}\n`;
|
|
132
|
+
}
|
|
133
|
+
header += `\n---\n\n`;
|
|
134
|
+
return header + content + attachmentInfo;
|
|
135
|
+
}
|
|
136
|
+
async getThread(threadId, folder = 'INBOX') {
|
|
137
|
+
return this.imapClient.fetchThreadMessages(threadId, folder);
|
|
138
|
+
}
|
|
139
|
+
async downloadAttachment(uid, filename, folder = 'INBOX') {
|
|
140
|
+
const parsed = await this.imapClient.fetchMessageBody(uid, folder);
|
|
141
|
+
if (!parsed.attachments || parsed.attachments.length === 0) {
|
|
142
|
+
throw new Error('No attachments found in this email');
|
|
143
|
+
}
|
|
144
|
+
const attachment = parsed.attachments.find(a => a.filename === filename);
|
|
145
|
+
if (!attachment) {
|
|
146
|
+
throw new Error(`Attachment "${filename}" not found`);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
content: attachment.content,
|
|
150
|
+
contentType: attachment.contentType
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
async extractAttachmentText(uid, filename, folder = 'INBOX') {
|
|
154
|
+
const { content, contentType } = await this.downloadAttachment(uid, filename, folder);
|
|
155
|
+
if (contentType === 'application/pdf') {
|
|
156
|
+
const pdf = await import('pdf-parse');
|
|
157
|
+
// Some modules have a .default property when imported via dynamic import in ESM
|
|
158
|
+
const pdfParser = pdf.default || pdf;
|
|
159
|
+
const data = await pdfParser(content);
|
|
160
|
+
return data.text;
|
|
161
|
+
}
|
|
162
|
+
else if (contentType.startsWith('text/')) {
|
|
163
|
+
return content.toString('utf-8');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
throw new Error(`Extraction not supported for content type: ${contentType}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async listFolders() {
|
|
170
|
+
return this.imapClient.listFolders();
|
|
171
|
+
}
|
|
172
|
+
async moveMessage(uid, sourceFolder, targetFolder) {
|
|
173
|
+
return this.imapClient.moveMessage(uid, sourceFolder, targetFolder);
|
|
174
|
+
}
|
|
175
|
+
async modifyLabels(uid, folder, addLabels, removeLabels) {
|
|
176
|
+
return this.imapClient.modifyLabels(uid, folder, addLabels, removeLabels);
|
|
177
|
+
}
|
|
178
|
+
async batchOperations(uids, folder, operation) {
|
|
179
|
+
if (uids.length === 0) {
|
|
180
|
+
throw new Error('No UIDs provided for batch operation');
|
|
181
|
+
}
|
|
182
|
+
if (uids.length > 100) {
|
|
183
|
+
throw new Error('Batch operations are limited to 100 emails at once');
|
|
184
|
+
}
|
|
185
|
+
if (operation.type === 'move') {
|
|
186
|
+
await this.imapClient.batchMoveMessages(uids, folder, operation.targetFolder);
|
|
187
|
+
}
|
|
188
|
+
else if (operation.type === 'delete') {
|
|
189
|
+
await this.imapClient.batchDeleteMessages(uids, folder);
|
|
190
|
+
}
|
|
191
|
+
else if (operation.type === 'label') {
|
|
192
|
+
await this.imapClient.batchModifyLabels(uids, folder, operation.addLabels || [], operation.removeLabels || []);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
throw new Error(`Unknown batch operation type: ${operation.type}`);
|
|
196
|
+
}
|
|
197
|
+
return { processed: uids.length };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=mail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail.js","sourceRoot":"","sources":["../../src/services/mail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type AuthType = 'login' | 'oauth2';
|
|
2
|
+
export interface EmailAccount {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
smtpHost?: string;
|
|
8
|
+
smtpPort?: number;
|
|
9
|
+
user: string;
|
|
10
|
+
authType: AuthType;
|
|
11
|
+
useTLS: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface Credentials {
|
|
14
|
+
password?: string;
|
|
15
|
+
accessToken?: string;
|
|
16
|
+
refreshToken?: string;
|
|
17
|
+
expiryDate?: number;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function htmlToMarkdown(html: string): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import TurndownService from 'turndown';
|
|
2
|
+
const turndownService = new TurndownService({
|
|
3
|
+
headingStyle: 'atx',
|
|
4
|
+
codeBlockStyle: 'fenced',
|
|
5
|
+
});
|
|
6
|
+
export function htmlToMarkdown(html) {
|
|
7
|
+
if (!html)
|
|
8
|
+
return '';
|
|
9
|
+
return turndownService.turndown(html);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,UAAU,CAAC;AAEvC,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;IAC1C,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,QAAQ;CACzB,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@honest-magic/mail-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for AI-powered email access via IMAP and SMTP",
|
|
5
|
+
"keywords": ["mcp", "email", "imap", "smtp", "ai", "llm", "model-context-protocol"],
|
|
6
|
+
"author": "honest-magic",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/honest-magic/mail-mcp#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/honest-magic/mail-mcp.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/honest-magic/mail-mcp/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18.0.0"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"bin": {
|
|
21
|
+
"mail-mcp": "dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"start": "node dist/index.js",
|
|
30
|
+
"test": "vitest run"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
34
|
+
"cross-keychain": "^1.1.0",
|
|
35
|
+
"dotenv": "^17.3.1",
|
|
36
|
+
"imapflow": "^1.2.16",
|
|
37
|
+
"mailparser": "^3.9.4",
|
|
38
|
+
"nodemailer": "^8.0.3",
|
|
39
|
+
"pdf-parse": "^2.4.5",
|
|
40
|
+
"turndown": "^7.2.2",
|
|
41
|
+
"zod": "^4.3.6"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/mailparser": "^3.4.6",
|
|
45
|
+
"@types/node": "^25.5.0",
|
|
46
|
+
"@types/nodemailer": "^7.0.11",
|
|
47
|
+
"@types/pdf-parse": "^1.1.5",
|
|
48
|
+
"@types/turndown": "^5.0.6",
|
|
49
|
+
"ts-node": "^10.9.2",
|
|
50
|
+
"typescript": "^5.9.3",
|
|
51
|
+
"vitest": "^4.1.0"
|
|
52
|
+
}
|
|
53
|
+
}
|