@n24q02m/better-email-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.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/bin/cli.mjs +13 -0
  4. package/build/scripts/start-server.d.ts +6 -0
  5. package/build/scripts/start-server.d.ts.map +1 -0
  6. package/build/scripts/start-server.js +21 -0
  7. package/build/scripts/start-server.js.map +1 -0
  8. package/build/src/docs/attachments.md +48 -0
  9. package/build/src/docs/folders.md +45 -0
  10. package/build/src/docs/messages.md +92 -0
  11. package/build/src/docs/send.md +52 -0
  12. package/build/src/init-server.d.ts +40 -0
  13. package/build/src/init-server.d.ts.map +1 -0
  14. package/build/src/init-server.js +57 -0
  15. package/build/src/init-server.js.map +1 -0
  16. package/build/src/tools/composite/attachments.d.ts +17 -0
  17. package/build/src/tools/composite/attachments.d.ts.map +1 -0
  18. package/build/src/tools/composite/attachments.js +77 -0
  19. package/build/src/tools/composite/attachments.js.map +1 -0
  20. package/build/src/tools/composite/attachments.test.d.ts +2 -0
  21. package/build/src/tools/composite/attachments.test.d.ts.map +1 -0
  22. package/build/src/tools/composite/attachments.test.js +138 -0
  23. package/build/src/tools/composite/attachments.test.js.map +1 -0
  24. package/build/src/tools/composite/folders.d.ts +14 -0
  25. package/build/src/tools/composite/folders.d.ts.map +1 -0
  26. package/build/src/tools/composite/folders.js +57 -0
  27. package/build/src/tools/composite/folders.js.map +1 -0
  28. package/build/src/tools/composite/folders.test.d.ts +2 -0
  29. package/build/src/tools/composite/folders.test.d.ts.map +1 -0
  30. package/build/src/tools/composite/folders.test.js +61 -0
  31. package/build/src/tools/composite/folders.test.js.map +1 -0
  32. package/build/src/tools/composite/messages.d.ts +20 -0
  33. package/build/src/tools/composite/messages.d.ts.map +1 -0
  34. package/build/src/tools/composite/messages.js +244 -0
  35. package/build/src/tools/composite/messages.js.map +1 -0
  36. package/build/src/tools/composite/messages.test.d.ts +2 -0
  37. package/build/src/tools/composite/messages.test.d.ts.map +1 -0
  38. package/build/src/tools/composite/messages.test.js +217 -0
  39. package/build/src/tools/composite/messages.test.js.map +1 -0
  40. package/build/src/tools/composite/send.d.ts +21 -0
  41. package/build/src/tools/composite/send.d.ts.map +1 -0
  42. package/build/src/tools/composite/send.js +127 -0
  43. package/build/src/tools/composite/send.js.map +1 -0
  44. package/build/src/tools/composite/send.test.d.ts +2 -0
  45. package/build/src/tools/composite/send.test.d.ts.map +1 -0
  46. package/build/src/tools/composite/send.test.js +232 -0
  47. package/build/src/tools/composite/send.test.js.map +1 -0
  48. package/build/src/tools/helpers/config.d.ts +33 -0
  49. package/build/src/tools/helpers/config.d.ts.map +1 -0
  50. package/build/src/tools/helpers/config.js +167 -0
  51. package/build/src/tools/helpers/config.js.map +1 -0
  52. package/build/src/tools/helpers/config.test.d.ts +2 -0
  53. package/build/src/tools/helpers/config.test.d.ts.map +1 -0
  54. package/build/src/tools/helpers/config.test.js +141 -0
  55. package/build/src/tools/helpers/config.test.js.map +1 -0
  56. package/build/src/tools/helpers/errors.d.ts +34 -0
  57. package/build/src/tools/helpers/errors.d.ts.map +1 -0
  58. package/build/src/tools/helpers/errors.js +152 -0
  59. package/build/src/tools/helpers/errors.js.map +1 -0
  60. package/build/src/tools/helpers/errors.test.d.ts +2 -0
  61. package/build/src/tools/helpers/errors.test.d.ts.map +1 -0
  62. package/build/src/tools/helpers/errors.test.js +203 -0
  63. package/build/src/tools/helpers/errors.test.js.map +1 -0
  64. package/build/src/tools/helpers/html-utils.d.ts +10 -0
  65. package/build/src/tools/helpers/html-utils.d.ts.map +1 -0
  66. package/build/src/tools/helpers/html-utils.js +29 -0
  67. package/build/src/tools/helpers/html-utils.js.map +1 -0
  68. package/build/src/tools/helpers/html-utils.test.d.ts +2 -0
  69. package/build/src/tools/helpers/html-utils.test.d.ts.map +1 -0
  70. package/build/src/tools/helpers/html-utils.test.js +103 -0
  71. package/build/src/tools/helpers/html-utils.test.js.map +1 -0
  72. package/build/src/tools/helpers/imap-client.d.ts +90 -0
  73. package/build/src/tools/helpers/imap-client.d.ts.map +1 -0
  74. package/build/src/tools/helpers/imap-client.js +321 -0
  75. package/build/src/tools/helpers/imap-client.js.map +1 -0
  76. package/build/src/tools/helpers/imap-client.test.d.ts +2 -0
  77. package/build/src/tools/helpers/imap-client.test.d.ts.map +1 -0
  78. package/build/src/tools/helpers/imap-client.test.js +401 -0
  79. package/build/src/tools/helpers/imap-client.test.js.map +1 -0
  80. package/build/src/tools/helpers/smtp-client.d.ts +38 -0
  81. package/build/src/tools/helpers/smtp-client.d.ts.map +1 -0
  82. package/build/src/tools/helpers/smtp-client.js +124 -0
  83. package/build/src/tools/helpers/smtp-client.js.map +1 -0
  84. package/build/src/tools/helpers/smtp-client.test.d.ts +2 -0
  85. package/build/src/tools/helpers/smtp-client.test.d.ts.map +1 -0
  86. package/build/src/tools/helpers/smtp-client.test.js +210 -0
  87. package/build/src/tools/helpers/smtp-client.test.js.map +1 -0
  88. package/build/src/tools/registry.d.ts +11 -0
  89. package/build/src/tools/registry.d.ts.map +1 -0
  90. package/build/src/tools/registry.js +262 -0
  91. package/build/src/tools/registry.js.map +1 -0
  92. package/build/src/tools/registry.test.d.ts +2 -0
  93. package/build/src/tools/registry.test.d.ts.map +1 -0
  94. package/build/src/tools/registry.test.js +135 -0
  95. package/build/src/tools/registry.test.js.map +1 -0
  96. package/build/tsconfig.tsbuildinfo +1 -0
  97. package/package.json +81 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Messages Mega Tool
3
+ * All email message operations in one unified interface
4
+ */
5
+ import { EmailMCPError, withErrorHandling } from '../helpers/errors.js';
6
+ import { listFolders, modifyFlags, moveEmails, readEmail, searchEmails, trashEmails } from '../helpers/imap-client.js';
7
+ /**
8
+ * Resolve target accounts from input
9
+ */
10
+ function resolveAccounts(accounts, accountFilter) {
11
+ if (!accountFilter)
12
+ return accounts;
13
+ const lower = accountFilter.toLowerCase();
14
+ const matched = accounts.filter((a) => a.email.toLowerCase() === lower || a.id === lower || a.email.toLowerCase().includes(lower));
15
+ if (matched.length === 0) {
16
+ throw new EmailMCPError(`Account not found: ${accountFilter}`, 'ACCOUNT_NOT_FOUND', `Available accounts: ${accounts.map((a) => a.email).join(', ')}`);
17
+ }
18
+ return matched;
19
+ }
20
+ /**
21
+ * Resolve a single account (for operations that require exactly one)
22
+ */
23
+ function resolveSingleAccount(accounts, accountFilter) {
24
+ const resolved = resolveAccounts(accounts, accountFilter);
25
+ if (resolved.length > 1) {
26
+ throw new EmailMCPError('Multiple accounts matched. Specify the exact account email.', 'AMBIGUOUS_ACCOUNT', `Matched: ${resolved.map((a) => a.email).join(', ')}`);
27
+ }
28
+ return resolved[0];
29
+ }
30
+ /**
31
+ * Unified messages tool - handles all message operations
32
+ */
33
+ export async function messages(accounts, input) {
34
+ return withErrorHandling(async () => {
35
+ switch (input.action) {
36
+ case 'search':
37
+ return await handleSearch(accounts, input);
38
+ case 'read':
39
+ return await handleRead(accounts, input);
40
+ case 'mark_read':
41
+ return await handleMarkRead(accounts, input);
42
+ case 'mark_unread':
43
+ return await handleMarkUnread(accounts, input);
44
+ case 'flag':
45
+ return await handleFlag(accounts, input);
46
+ case 'unflag':
47
+ return await handleUnflag(accounts, input);
48
+ case 'move':
49
+ return await handleMove(accounts, input);
50
+ case 'archive':
51
+ return await handleArchive(accounts, input);
52
+ case 'trash':
53
+ return await handleTrash(accounts, input);
54
+ default:
55
+ throw new EmailMCPError(`Unknown action: ${input.action}`, 'VALIDATION_ERROR', 'Supported actions: search, read, mark_read, mark_unread, flag, unflag, move, archive, trash');
56
+ }
57
+ })();
58
+ }
59
+ /**
60
+ * Search emails across accounts
61
+ */
62
+ async function handleSearch(accounts, input) {
63
+ const targetAccounts = resolveAccounts(accounts, input.account);
64
+ const query = input.query || 'UNSEEN';
65
+ const folder = input.folder || 'INBOX';
66
+ const limit = input.limit || 20;
67
+ const results = await searchEmails(targetAccounts, query, folder, limit);
68
+ return {
69
+ action: 'search',
70
+ query,
71
+ folder,
72
+ total: results.length,
73
+ accounts_searched: targetAccounts.map((a) => a.email),
74
+ messages: results
75
+ };
76
+ }
77
+ /**
78
+ * Read a single email by UID
79
+ */
80
+ async function handleRead(accounts, input) {
81
+ if (!input.uid) {
82
+ throw new EmailMCPError('uid is required for read action', 'VALIDATION_ERROR', 'Provide the email UID from search');
83
+ }
84
+ const account = resolveSingleAccount(accounts, input.account);
85
+ const folder = input.folder || 'INBOX';
86
+ const email = await readEmail(account, input.uid, folder);
87
+ return {
88
+ action: 'read',
89
+ ...email
90
+ };
91
+ }
92
+ /**
93
+ * Mark emails as read
94
+ */
95
+ async function handleMarkRead(accounts, input) {
96
+ const uids = input.uids || (input.uid ? [input.uid] : []);
97
+ if (uids.length === 0) {
98
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
99
+ }
100
+ const account = resolveSingleAccount(accounts, input.account);
101
+ const folder = input.folder || 'INBOX';
102
+ const result = await modifyFlags(account, uids, folder, ['\\Seen'], 'add');
103
+ return {
104
+ action: 'mark_read',
105
+ account: account.email,
106
+ folder,
107
+ ...result
108
+ };
109
+ }
110
+ /**
111
+ * Mark emails as unread
112
+ */
113
+ async function handleMarkUnread(accounts, input) {
114
+ const uids = input.uids || (input.uid ? [input.uid] : []);
115
+ if (uids.length === 0) {
116
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
117
+ }
118
+ const account = resolveSingleAccount(accounts, input.account);
119
+ const folder = input.folder || 'INBOX';
120
+ const result = await modifyFlags(account, uids, folder, ['\\Seen'], 'remove');
121
+ return {
122
+ action: 'mark_unread',
123
+ account: account.email,
124
+ folder,
125
+ ...result
126
+ };
127
+ }
128
+ /**
129
+ * Flag (star) emails
130
+ */
131
+ async function handleFlag(accounts, input) {
132
+ const uids = input.uids || (input.uid ? [input.uid] : []);
133
+ if (uids.length === 0) {
134
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
135
+ }
136
+ const account = resolveSingleAccount(accounts, input.account);
137
+ const folder = input.folder || 'INBOX';
138
+ const result = await modifyFlags(account, uids, folder, ['\\Flagged'], 'add');
139
+ return {
140
+ action: 'flag',
141
+ account: account.email,
142
+ folder,
143
+ ...result
144
+ };
145
+ }
146
+ /**
147
+ * Unflag (unstar) emails
148
+ */
149
+ async function handleUnflag(accounts, input) {
150
+ const uids = input.uids || (input.uid ? [input.uid] : []);
151
+ if (uids.length === 0) {
152
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
153
+ }
154
+ const account = resolveSingleAccount(accounts, input.account);
155
+ const folder = input.folder || 'INBOX';
156
+ const result = await modifyFlags(account, uids, folder, ['\\Flagged'], 'remove');
157
+ return {
158
+ action: 'unflag',
159
+ account: account.email,
160
+ folder,
161
+ ...result
162
+ };
163
+ }
164
+ /**
165
+ * Move emails to another folder
166
+ */
167
+ async function handleMove(accounts, input) {
168
+ const uids = input.uids || (input.uid ? [input.uid] : []);
169
+ if (uids.length === 0) {
170
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
171
+ }
172
+ if (!input.destination) {
173
+ throw new EmailMCPError('destination is required for move action', 'VALIDATION_ERROR', 'Provide the target folder name. Use folders tool to list available folders.');
174
+ }
175
+ const account = resolveSingleAccount(accounts, input.account);
176
+ const folder = input.folder || 'INBOX';
177
+ const result = await moveEmails(account, uids, folder, input.destination);
178
+ return {
179
+ action: 'move',
180
+ account: account.email,
181
+ from_folder: folder,
182
+ to_folder: input.destination,
183
+ ...result
184
+ };
185
+ }
186
+ /**
187
+ * Archive emails (move to archive folder)
188
+ */
189
+ async function handleArchive(accounts, input) {
190
+ const uids = input.uids || (input.uid ? [input.uid] : []);
191
+ if (uids.length === 0) {
192
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
193
+ }
194
+ const account = resolveSingleAccount(accounts, input.account);
195
+ const folder = input.folder || 'INBOX';
196
+ // Detect archive folder based on provider
197
+ let archiveFolder = '[Gmail]/All Mail';
198
+ if (account.imap.host.includes('office365') || account.imap.host.includes('outlook')) {
199
+ archiveFolder = 'Archive';
200
+ }
201
+ else if (account.imap.host.includes('yahoo')) {
202
+ archiveFolder = 'Archive';
203
+ }
204
+ // Try to find actual archive folder
205
+ try {
206
+ const folders = await listFolders(account);
207
+ const found = folders.find((f) => f.path.toLowerCase().includes('archive') ||
208
+ f.path.toLowerCase().includes('all mail') ||
209
+ f.flags.some((flag) => flag.toLowerCase().includes('archive') || flag.toLowerCase().includes('all')));
210
+ if (found) {
211
+ archiveFolder = found.path;
212
+ }
213
+ }
214
+ catch {
215
+ // Use default if folder listing fails
216
+ }
217
+ const result = await moveEmails(account, uids, folder, archiveFolder);
218
+ return {
219
+ action: 'archive',
220
+ account: account.email,
221
+ from_folder: folder,
222
+ archive_folder: archiveFolder,
223
+ ...result
224
+ };
225
+ }
226
+ /**
227
+ * Trash emails
228
+ */
229
+ async function handleTrash(accounts, input) {
230
+ const uids = input.uids || (input.uid ? [input.uid] : []);
231
+ if (uids.length === 0) {
232
+ throw new EmailMCPError('uid or uids required', 'VALIDATION_ERROR', 'Provide at least one email UID');
233
+ }
234
+ const account = resolveSingleAccount(accounts, input.account);
235
+ const folder = input.folder || 'INBOX';
236
+ const result = await trashEmails(account, uids, folder);
237
+ return {
238
+ action: 'trash',
239
+ account: account.email,
240
+ folder,
241
+ ...result
242
+ };
243
+ }
244
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../src/tools/composite/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=messages.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.test.d.ts","sourceRoot":"","sources":["../../../../src/tools/composite/messages.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,217 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ // --- Mocks ---
3
+ vi.mock('../helpers/imap-client.js', () => ({
4
+ searchEmails: vi.fn(),
5
+ readEmail: vi.fn(),
6
+ modifyFlags: vi.fn(),
7
+ moveEmails: vi.fn(),
8
+ trashEmails: vi.fn(),
9
+ listFolders: vi.fn()
10
+ }));
11
+ import { listFolders, modifyFlags, moveEmails, readEmail, searchEmails, trashEmails } from '../helpers/imap-client.js';
12
+ import { messages } from './messages.js';
13
+ const mockSearchEmails = vi.mocked(searchEmails);
14
+ const mockReadEmail = vi.mocked(readEmail);
15
+ const mockModifyFlags = vi.mocked(modifyFlags);
16
+ const mockMoveEmails = vi.mocked(moveEmails);
17
+ const mockTrashEmails = vi.mocked(trashEmails);
18
+ const mockListFolders = vi.mocked(listFolders);
19
+ const accounts = [
20
+ {
21
+ id: 'user1_gmail_com',
22
+ email: 'user1@gmail.com',
23
+ password: 'pass1',
24
+ imap: { host: 'imap.gmail.com', port: 993, secure: true },
25
+ smtp: { host: 'smtp.gmail.com', port: 465, secure: true }
26
+ },
27
+ {
28
+ id: 'user2_outlook_com',
29
+ email: 'user2@outlook.com',
30
+ password: 'pass2',
31
+ imap: { host: 'outlook.office365.com', port: 993, secure: true },
32
+ smtp: { host: 'smtp.office365.com', port: 587, secure: false }
33
+ }
34
+ ];
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ });
38
+ // ============================================================================
39
+ // search
40
+ // ============================================================================
41
+ describe('messages - search', () => {
42
+ it('searches all accounts by default', async () => {
43
+ mockSearchEmails.mockResolvedValue([]);
44
+ const result = await messages(accounts, { action: 'search' });
45
+ expect(result.action).toBe('search');
46
+ expect(result.query).toBe('UNSEEN');
47
+ expect(result.folder).toBe('INBOX');
48
+ expect(result.accounts_searched).toHaveLength(2);
49
+ expect(mockSearchEmails).toHaveBeenCalledWith(accounts, 'UNSEEN', 'INBOX', 20);
50
+ });
51
+ it('filters by account when specified', async () => {
52
+ mockSearchEmails.mockResolvedValue([]);
53
+ await messages(accounts, { action: 'search', account: 'user1@gmail.com' });
54
+ expect(mockSearchEmails).toHaveBeenCalledWith([accounts[0]], expect.any(String), expect.any(String), expect.any(Number));
55
+ });
56
+ it('uses custom query, folder, and limit', async () => {
57
+ mockSearchEmails.mockResolvedValue([]);
58
+ await messages(accounts, { action: 'search', query: 'FLAGGED', folder: 'Sent', limit: 5 });
59
+ expect(mockSearchEmails).toHaveBeenCalledWith(accounts, 'FLAGGED', 'Sent', 5);
60
+ });
61
+ it('throws when account not found', async () => {
62
+ await expect(messages(accounts, { action: 'search', account: 'nonexistent@test.com' })).rejects.toThrow('Account not found');
63
+ });
64
+ });
65
+ // ============================================================================
66
+ // read
67
+ // ============================================================================
68
+ describe('messages - read', () => {
69
+ it('reads email by UID', async () => {
70
+ mockReadEmail.mockResolvedValue({
71
+ account_id: 'user1_gmail_com',
72
+ account_email: 'user1@gmail.com',
73
+ uid: 42,
74
+ subject: 'Test',
75
+ from: 'sender@test.com',
76
+ to: 'user1@gmail.com',
77
+ date: '2025-01-01',
78
+ flags: ['\\Seen'],
79
+ body_text: 'Hello',
80
+ attachments: []
81
+ });
82
+ const result = await messages(accounts, { action: 'read', uid: 42, account: 'user1@gmail.com' });
83
+ expect(result.action).toBe('read');
84
+ expect(result.uid).toBe(42);
85
+ expect(result.subject).toBe('Test');
86
+ });
87
+ it('throws when uid is missing', async () => {
88
+ await expect(messages(accounts, { action: 'read', account: 'user1@gmail.com' })).rejects.toThrow('uid is required');
89
+ });
90
+ it('throws when multiple accounts match', async () => {
91
+ await expect(messages(accounts, { action: 'read', uid: 1, account: '.com' })).rejects.toThrow('Multiple accounts matched');
92
+ });
93
+ });
94
+ // ============================================================================
95
+ // mark_read / mark_unread
96
+ // ============================================================================
97
+ describe('messages - mark_read', () => {
98
+ it('adds \\Seen flag', async () => {
99
+ mockModifyFlags.mockResolvedValue({ success: true, modified: 1 });
100
+ const result = await messages(accounts, { action: 'mark_read', uid: 5, account: 'user1@gmail.com' });
101
+ expect(result.action).toBe('mark_read');
102
+ expect(mockModifyFlags).toHaveBeenCalledWith(accounts[0], [5], 'INBOX', ['\\Seen'], 'add');
103
+ });
104
+ it('supports batch uids', async () => {
105
+ mockModifyFlags.mockResolvedValue({ success: true, modified: 3 });
106
+ await messages(accounts, { action: 'mark_read', uids: [1, 2, 3], account: 'user1@gmail.com' });
107
+ expect(mockModifyFlags).toHaveBeenCalledWith(accounts[0], [1, 2, 3], 'INBOX', ['\\Seen'], 'add');
108
+ });
109
+ it('throws when no uids provided', async () => {
110
+ await expect(messages(accounts, { action: 'mark_read', account: 'user1@gmail.com' })).rejects.toThrow('uid or uids required');
111
+ });
112
+ });
113
+ describe('messages - mark_unread', () => {
114
+ it('removes \\Seen flag', async () => {
115
+ mockModifyFlags.mockResolvedValue({ success: true, modified: 1 });
116
+ await messages(accounts, { action: 'mark_unread', uid: 5, account: 'user1@gmail.com' });
117
+ expect(mockModifyFlags).toHaveBeenCalledWith(accounts[0], [5], 'INBOX', ['\\Seen'], 'remove');
118
+ });
119
+ });
120
+ // ============================================================================
121
+ // flag / unflag
122
+ // ============================================================================
123
+ describe('messages - flag', () => {
124
+ it('adds \\Flagged flag', async () => {
125
+ mockModifyFlags.mockResolvedValue({ success: true, modified: 1 });
126
+ await messages(accounts, { action: 'flag', uid: 10, account: 'user1@gmail.com' });
127
+ expect(mockModifyFlags).toHaveBeenCalledWith(accounts[0], [10], 'INBOX', ['\\Flagged'], 'add');
128
+ });
129
+ });
130
+ describe('messages - unflag', () => {
131
+ it('removes \\Flagged flag', async () => {
132
+ mockModifyFlags.mockResolvedValue({ success: true, modified: 1 });
133
+ await messages(accounts, { action: 'unflag', uid: 10, account: 'user1@gmail.com' });
134
+ expect(mockModifyFlags).toHaveBeenCalledWith(accounts[0], [10], 'INBOX', ['\\Flagged'], 'remove');
135
+ });
136
+ });
137
+ // ============================================================================
138
+ // move
139
+ // ============================================================================
140
+ describe('messages - move', () => {
141
+ it('moves emails to destination folder', async () => {
142
+ mockMoveEmails.mockResolvedValue({ success: true, moved: 2 });
143
+ const result = await messages(accounts, {
144
+ action: 'move',
145
+ uids: [1, 2],
146
+ destination: 'Archive',
147
+ account: 'user1@gmail.com'
148
+ });
149
+ expect(result.action).toBe('move');
150
+ expect(result.to_folder).toBe('Archive');
151
+ expect(mockMoveEmails).toHaveBeenCalledWith(accounts[0], [1, 2], 'INBOX', 'Archive');
152
+ });
153
+ it('throws when destination is missing', async () => {
154
+ await expect(messages(accounts, { action: 'move', uid: 1, account: 'user1@gmail.com' })).rejects.toThrow('destination is required');
155
+ });
156
+ });
157
+ // ============================================================================
158
+ // archive
159
+ // ============================================================================
160
+ describe('messages - archive', () => {
161
+ it('moves to Gmail archive folder', async () => {
162
+ mockListFolders.mockResolvedValue([
163
+ { name: 'All Mail', path: '[Gmail]/All Mail', flags: ['\\All'], delimiter: '/' }
164
+ ]);
165
+ mockMoveEmails.mockResolvedValue({ success: true, moved: 1 });
166
+ const result = await messages(accounts, { action: 'archive', uid: 1, account: 'user1@gmail.com' });
167
+ expect(result.action).toBe('archive');
168
+ expect(result.archive_folder).toBe('[Gmail]/All Mail');
169
+ });
170
+ it('falls back to default archive folder if listing fails', async () => {
171
+ mockListFolders.mockRejectedValue(new Error('fail'));
172
+ mockMoveEmails.mockResolvedValue({ success: true, moved: 1 });
173
+ const result = await messages(accounts, { action: 'archive', uid: 1, account: 'user1@gmail.com' });
174
+ expect(result.archive_folder).toBe('[Gmail]/All Mail');
175
+ });
176
+ it('uses Archive for Outlook accounts', async () => {
177
+ mockListFolders.mockResolvedValue([{ name: 'Archive', path: 'Archive', flags: ['\\Archive'], delimiter: '/' }]);
178
+ mockMoveEmails.mockResolvedValue({ success: true, moved: 1 });
179
+ const result = await messages(accounts, { action: 'archive', uid: 1, account: 'user2@outlook.com' });
180
+ expect(result.archive_folder).toBe('Archive');
181
+ });
182
+ });
183
+ // ============================================================================
184
+ // trash
185
+ // ============================================================================
186
+ describe('messages - trash', () => {
187
+ it('trashes emails', async () => {
188
+ mockTrashEmails.mockResolvedValue({ success: true, trashed: 1 });
189
+ const result = await messages(accounts, { action: 'trash', uid: 99, account: 'user1@gmail.com' });
190
+ expect(result.action).toBe('trash');
191
+ expect(mockTrashEmails).toHaveBeenCalledWith(accounts[0], [99], 'INBOX');
192
+ });
193
+ });
194
+ // ============================================================================
195
+ // unknown action
196
+ // ============================================================================
197
+ describe('messages - unknown action', () => {
198
+ it('throws for unknown action', async () => {
199
+ await expect(messages(accounts, { action: 'unknown_action' })).rejects.toThrow();
200
+ });
201
+ });
202
+ // ============================================================================
203
+ // account resolution
204
+ // ============================================================================
205
+ describe('account resolution', () => {
206
+ it('matches by partial email', async () => {
207
+ mockSearchEmails.mockResolvedValue([]);
208
+ await messages(accounts, { action: 'search', account: 'gmail' });
209
+ expect(mockSearchEmails).toHaveBeenCalledWith([accounts[0]], expect.any(String), expect.any(String), expect.any(Number));
210
+ });
211
+ it('matches by account id', async () => {
212
+ mockSearchEmails.mockResolvedValue([]);
213
+ await messages(accounts, { action: 'search', account: 'user1_gmail_com' });
214
+ expect(mockSearchEmails).toHaveBeenCalledWith([accounts[0]], expect.any(String), expect.any(String), expect.any(Number));
215
+ });
216
+ });
217
+ //# sourceMappingURL=messages.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.test.js","sourceRoot":"","sources":["../../../../src/tools/composite/messages.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Send Mega Tool
3
+ * Send new emails, reply, and forward via SMTP
4
+ */
5
+ import type { AccountConfig } from '../helpers/config.js';
6
+ export interface SendInput {
7
+ action: 'new' | 'reply' | 'forward';
8
+ account: string;
9
+ to: string;
10
+ subject: string;
11
+ body: string;
12
+ cc?: string;
13
+ bcc?: string;
14
+ uid?: number;
15
+ folder?: string;
16
+ }
17
+ /**
18
+ * Unified send tool - handles all outbound email operations
19
+ */
20
+ export declare function send(accounts: AccountConfig[], input: SendInput): Promise<any>;
21
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../../../src/tools/composite/send.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAKzD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAA;IAGnC,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IAGZ,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IAGZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AA8BD;;GAEG;AACH,wBAAsB,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAoCpF"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Send Mega Tool
3
+ * Send new emails, reply, and forward via SMTP
4
+ */
5
+ import { EmailMCPError, withErrorHandling } from '../helpers/errors.js';
6
+ import { readEmail } from '../helpers/imap-client.js';
7
+ import { forwardEmail, replyToEmail, sendNewEmail } from '../helpers/smtp-client.js';
8
+ /**
9
+ * Resolve a single account by filter
10
+ */
11
+ function resolveSingleAccount(accounts, accountFilter) {
12
+ const lower = accountFilter.toLowerCase();
13
+ const matched = accounts.filter((a) => a.email.toLowerCase() === lower || a.id === lower || a.email.toLowerCase().includes(lower));
14
+ if (matched.length === 0) {
15
+ throw new EmailMCPError(`Account not found: ${accountFilter}`, 'ACCOUNT_NOT_FOUND', `Available accounts: ${accounts.map((a) => a.email).join(', ')}`);
16
+ }
17
+ if (matched.length > 1) {
18
+ throw new EmailMCPError('Multiple accounts matched. Specify the exact account email.', 'AMBIGUOUS_ACCOUNT', `Matched: ${matched.map((a) => a.email).join(', ')}`);
19
+ }
20
+ return matched[0];
21
+ }
22
+ /**
23
+ * Unified send tool - handles all outbound email operations
24
+ */
25
+ export async function send(accounts, input) {
26
+ return withErrorHandling(async () => {
27
+ if (!input.account) {
28
+ throw new EmailMCPError('account is required for send operations', 'VALIDATION_ERROR', 'Provide the sender account email address');
29
+ }
30
+ if (!input.to) {
31
+ throw new EmailMCPError('to is required', 'VALIDATION_ERROR', 'Provide recipient email address');
32
+ }
33
+ if (!input.body) {
34
+ throw new EmailMCPError('body is required', 'VALIDATION_ERROR', 'Provide the email body text');
35
+ }
36
+ switch (input.action) {
37
+ case 'new':
38
+ return await handleNew(accounts, input);
39
+ case 'reply':
40
+ return await handleReply(accounts, input);
41
+ case 'forward':
42
+ return await handleForward(accounts, input);
43
+ default:
44
+ throw new EmailMCPError(`Unknown action: ${input.action}`, 'VALIDATION_ERROR', 'Supported actions: new, reply, forward');
45
+ }
46
+ })();
47
+ }
48
+ /**
49
+ * Send a new email
50
+ */
51
+ async function handleNew(accounts, input) {
52
+ if (!input.subject) {
53
+ throw new EmailMCPError('subject is required for new email', 'VALIDATION_ERROR', 'Provide the email subject');
54
+ }
55
+ const account = resolveSingleAccount(accounts, input.account);
56
+ const result = await sendNewEmail(account, {
57
+ to: input.to,
58
+ subject: input.subject,
59
+ body: input.body,
60
+ cc: input.cc,
61
+ bcc: input.bcc
62
+ });
63
+ return {
64
+ action: 'new',
65
+ from: account.email,
66
+ to: input.to,
67
+ subject: input.subject,
68
+ ...result
69
+ };
70
+ }
71
+ /**
72
+ * Reply to an email (maintains thread headers)
73
+ */
74
+ async function handleReply(accounts, input) {
75
+ if (!input.uid) {
76
+ throw new EmailMCPError('uid is required for reply action', 'VALIDATION_ERROR', 'Provide the UID of the email to reply to (from search/read)');
77
+ }
78
+ const account = resolveSingleAccount(accounts, input.account);
79
+ const folder = input.folder || 'INBOX';
80
+ // Read original email to get threading headers
81
+ const original = await readEmail(account, input.uid, folder);
82
+ const result = await replyToEmail(account, {
83
+ to: input.to,
84
+ subject: input.subject || original.subject,
85
+ body: input.body,
86
+ cc: input.cc,
87
+ bcc: input.bcc,
88
+ in_reply_to: original.message_id,
89
+ references: original.references || original.message_id
90
+ });
91
+ return {
92
+ action: 'reply',
93
+ from: account.email,
94
+ to: input.to,
95
+ subject: input.subject || `Re: ${original.subject}`,
96
+ in_reply_to: original.message_id,
97
+ ...result
98
+ };
99
+ }
100
+ /**
101
+ * Forward an email
102
+ */
103
+ async function handleForward(accounts, input) {
104
+ if (!input.uid) {
105
+ throw new EmailMCPError('uid is required for forward action', 'VALIDATION_ERROR', 'Provide the UID of the email to forward (from search/read)');
106
+ }
107
+ const account = resolveSingleAccount(accounts, input.account);
108
+ const folder = input.folder || 'INBOX';
109
+ // Read original email to include in forward
110
+ const original = await readEmail(account, input.uid, folder);
111
+ const result = await forwardEmail(account, {
112
+ to: input.to,
113
+ subject: input.subject || original.subject,
114
+ body: input.body,
115
+ cc: input.cc,
116
+ bcc: input.bcc,
117
+ original_body: original.body_text
118
+ });
119
+ return {
120
+ action: 'forward',
121
+ from: account.email,
122
+ to: input.to,
123
+ subject: input.subject || `Fwd: ${original.subject}`,
124
+ ...result
125
+ };
126
+ }
127
+ //# sourceMappingURL=send.js.map