apple-mail-mcp 2.8.2 → 2.8.3
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/README.md +5 -5
- package/build/cli.js +12083 -138
- package/build/index.js +82684 -1687
- package/package.json +3 -4
- package/build/cli.d.ts +0 -24
- package/build/cli.d.ts.map +0 -1
- package/build/index.d.ts +0 -23
- package/build/index.d.ts.map +0 -1
- package/build/services/appleMailManager.d.ts +0 -680
- package/build/services/appleMailManager.d.ts.map +0 -1
- package/build/services/appleMailManager.js +0 -3143
- package/build/services/fileConfig.d.ts +0 -7
- package/build/services/fileConfig.d.ts.map +0 -1
- package/build/services/fileConfig.js +0 -52
- package/build/services/imapClient.d.ts +0 -312
- package/build/services/imapClient.d.ts.map +0 -1
- package/build/services/imapClient.js +0 -1023
- package/build/services/imapIdle.d.ts +0 -58
- package/build/services/imapIdle.d.ts.map +0 -1
- package/build/services/imapIdle.js +0 -151
- package/build/services/imapMultiAccount.d.ts +0 -124
- package/build/services/imapMultiAccount.d.ts.map +0 -1
- package/build/services/imapMultiAccount.js +0 -253
- package/build/services/messageRouter.d.ts +0 -24
- package/build/services/messageRouter.d.ts.map +0 -1
- package/build/services/messageRouter.js +0 -31
- package/build/services/replyForward.d.ts +0 -87
- package/build/services/replyForward.d.ts.map +0 -1
- package/build/services/replyForward.js +0 -150
- package/build/services/smtpMailer.d.ts +0 -160
- package/build/services/smtpMailer.d.ts.map +0 -1
- package/build/services/smtpMailer.js +0 -268
- package/build/services/templateStore.d.ts +0 -18
- package/build/services/templateStore.d.ts.map +0 -1
- package/build/services/templateStore.js +0 -91
- package/build/tools/doctor.d.ts +0 -23
- package/build/tools/doctor.d.ts.map +0 -1
- package/build/tools/doctor.js +0 -74
- package/build/tools/resourcesAndPrompts.d.ts +0 -14
- package/build/tools/resourcesAndPrompts.d.ts.map +0 -1
- package/build/tools/resourcesAndPrompts.js +0 -109
- package/build/tools/respond.d.ts +0 -48
- package/build/tools/respond.d.ts.map +0 -1
- package/build/tools/respond.js +0 -95
- package/build/tools/thread.d.ts +0 -19
- package/build/tools/thread.d.ts.map +0 -1
- package/build/tools/thread.js +0 -32
- package/build/types.d.ts +0 -434
- package/build/types.d.ts.map +0 -1
- package/build/types.js +0 -13
- package/build/utils/applescript.d.ts +0 -45
- package/build/utils/applescript.d.ts.map +0 -1
- package/build/utils/applescript.js +0 -446
- package/build/utils/attachmentMaterialize.d.ts +0 -9
- package/build/utils/attachmentMaterialize.d.ts.map +0 -1
- package/build/utils/attachmentMaterialize.js +0 -38
- package/build/utils/mimeParse.d.ts +0 -62
- package/build/utils/mimeParse.d.ts.map +0 -1
- package/build/utils/mimeParse.js +0 -317
- package/build/utils/orphan.d.ts +0 -25
- package/build/utils/orphan.d.ts.map +0 -1
- package/build/utils/orphan.js +0 -26
- package/build/utils/serialize.d.ts +0 -30
- package/build/utils/serialize.d.ts.map +0 -1
- package/build/utils/serialize.js +0 -41
|
@@ -1,680 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Apple Mail Manager
|
|
3
|
-
*
|
|
4
|
-
* Handles all interactions with Apple Mail via AppleScript.
|
|
5
|
-
* This is the core service layer for the MCP server.
|
|
6
|
-
*
|
|
7
|
-
* Architecture:
|
|
8
|
-
* - Text escaping is handled by dedicated helper functions
|
|
9
|
-
* - AppleScript generation uses template builders for consistency
|
|
10
|
-
* - All public methods return typed results (no raw strings)
|
|
11
|
-
* - Error handling is consistent across all operations
|
|
12
|
-
*
|
|
13
|
-
* @module services/appleMailManager
|
|
14
|
-
*/
|
|
15
|
-
import type { Message, MessageContent, Mailbox, Account, Attachment, HealthCheckResult, MailStats, BatchOperationResult, SyncStatus, RecentlyReceivedStats, MailRule, RuleSpec, AttachmentInput, Contact, EmailTemplate, SerialEmailRecipient, SerialEmailResult, SearchDiagnostics, SearchResult } from "../types.js";
|
|
16
|
-
/**
|
|
17
|
-
* Merge a per-account SearchDiagnostics into an aggregate (all-accounts) one.
|
|
18
|
-
*
|
|
19
|
-
* Exported for unit testing.
|
|
20
|
-
*/
|
|
21
|
-
export declare function mergeSearchDiagnostics(into: SearchDiagnostics, from: SearchDiagnostics): void;
|
|
22
|
-
/**
|
|
23
|
-
* Split a per-account search payload into its message-list portion and parsed
|
|
24
|
-
* diagnostics. The AppleScript appends a trailer of the form (using the
|
|
25
|
-
* control-character separators defined above):
|
|
26
|
-
*
|
|
27
|
-
* <messages>{DIAG_MARKER}timedOut=true{DIAG_FIELD_SEP}skipped=Foo (9000){DIAG_ITEM_SEP}{DIAG_FIELD_SEP}notSearched=Bar{DIAG_ITEM_SEP}
|
|
28
|
-
*
|
|
29
|
-
* `skipped`/`notSearched` are DIAG_ITEM_SEP-separated mailbox names, each prefixed
|
|
30
|
-
* with the account name on the way out so the aggregate result is unambiguous.
|
|
31
|
-
*
|
|
32
|
-
* Exported (pure, no Mail.app dependency) for unit testing — this is the logic
|
|
33
|
-
* that turns a swallowed timeout into a visible partial result (issue #24).
|
|
34
|
-
*/
|
|
35
|
-
export declare function splitSearchDiagnostics(output: string, account: string): {
|
|
36
|
-
payload: string;
|
|
37
|
-
diagnostics: SearchDiagnostics;
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* True if `resolvedPath` is one of the allowed roots or strictly inside one.
|
|
41
|
-
*
|
|
42
|
-
* Uses a path-segment boundary check rather than a bare `startsWith`, which
|
|
43
|
-
* would let a sibling whose name merely shares the prefix slip through —
|
|
44
|
-
* `/Volumes-evil` startsWith `/Volumes`, `/Users/robother` startsWith
|
|
45
|
-
* `/Users/rob` (audit finding #12). `resolvedPath` must already be absolute
|
|
46
|
-
* (caller passes `resolve(...)` output).
|
|
47
|
-
*/
|
|
48
|
-
export declare function isPathWithinAllowedRoots(resolvedPath: string): boolean;
|
|
49
|
-
/**
|
|
50
|
-
* Turn a raw mailbox delete/rename failure into an actionable, non-retryable
|
|
51
|
-
* message when it's the known server-side-mailbox limitation (#42); otherwise
|
|
52
|
-
* return the raw error unchanged.
|
|
53
|
-
*
|
|
54
|
-
* Exported for unit testing.
|
|
55
|
-
*/
|
|
56
|
-
export declare function describeMailboxOpError(op: "create" | "delete" | "rename", raw: string): string;
|
|
57
|
-
/** Env var to pin the default account (matched by account name or email). */
|
|
58
|
-
export declare const DEFAULT_ACCOUNT_ENV = "APPLE_MAIL_MCP_DEFAULT_ACCOUNT";
|
|
59
|
-
/**
|
|
60
|
-
* Choose the account to use when a tool call omits `account`.
|
|
61
|
-
*
|
|
62
|
-
* Priority: explicit `override` (by name or email) → Mail's default-send
|
|
63
|
-
* account *if enabled* → first enabled account → first account → null. The key
|
|
64
|
-
* guarantee (issue #47): a **disabled** account is never chosen implicitly — it
|
|
65
|
-
* can only be selected via an explicit override (deliberate user intent) or as
|
|
66
|
-
* a last resort when no account is enabled. This prevents operations silently
|
|
67
|
-
* landing in a configured-but-disabled account (e.g. an unused iCloud account
|
|
68
|
-
* that's still addressable via AppleScript).
|
|
69
|
-
*
|
|
70
|
-
* Pure/exported for unit testing.
|
|
71
|
-
*/
|
|
72
|
-
export declare function chooseDefaultAccount(accounts: Account[], opts?: {
|
|
73
|
-
override?: string;
|
|
74
|
-
defaultSendEmail?: string;
|
|
75
|
-
}): string | null;
|
|
76
|
-
export declare function escapeForAppleScript(text: string): string;
|
|
77
|
-
/**
|
|
78
|
-
* Emits AppleScript that builds a date into the variable `varName` from numeric
|
|
79
|
-
* components.
|
|
80
|
-
*
|
|
81
|
-
* This is locale-independent, unlike `date "May 30, 2026"` string coercion,
|
|
82
|
-
* which AppleScript parses using the system locale. On a non-English locale
|
|
83
|
-
* (e.g. pt_PT) the English month name throws "Invalid date and time (-30720)";
|
|
84
|
-
* because the comparison happens inside the per-message `try` in searchMessages,
|
|
85
|
-
* that error is swallowed and every message is skipped, so the search returns
|
|
86
|
-
* zero results even when matches exist. See issue #15.
|
|
87
|
-
*
|
|
88
|
-
* `day` is reset to 1 before assigning month/year so an existing day-of-month
|
|
89
|
-
* (e.g. 31) cannot overflow into the next month when the month is changed.
|
|
90
|
-
*
|
|
91
|
-
* Exported for unit testing.
|
|
92
|
-
*/
|
|
93
|
-
export declare function buildAppleScriptDate(varName: string, d: Date): string;
|
|
94
|
-
/**
|
|
95
|
-
* Manager class for Apple Mail operations.
|
|
96
|
-
*
|
|
97
|
-
* Provides methods for:
|
|
98
|
-
* - Reading and searching messages
|
|
99
|
-
* - Sending emails
|
|
100
|
-
* - Managing mailboxes
|
|
101
|
-
* - Listing accounts
|
|
102
|
-
*
|
|
103
|
-
* All operations are synchronous since they rely on AppleScript
|
|
104
|
-
* execution via osascript. Error handling is consistent: methods
|
|
105
|
-
* return null/false/empty-array on failure rather than throwing.
|
|
106
|
-
*/
|
|
107
|
-
export interface SearchConditionFilters {
|
|
108
|
-
query?: string;
|
|
109
|
-
from?: string;
|
|
110
|
-
subject?: string;
|
|
111
|
-
isRead?: boolean;
|
|
112
|
-
isFlagged?: boolean;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Build the AppleScript `whose` clause for searchMessages from a filter set.
|
|
116
|
-
*
|
|
117
|
-
* - `query` is a subject-OR-sender substring match, parenthesized so it groups
|
|
118
|
-
* correctly when ANDed with other filters.
|
|
119
|
-
* - `from` and `subject` are substring matches (`sender`/`subject` contains).
|
|
120
|
-
* - `isRead` / `isFlagged` are boolean status checks.
|
|
121
|
-
* - Returns "" when no filters are set. Every interpolated value is escaped.
|
|
122
|
-
*
|
|
123
|
-
* Exported for unit testing: the bug this addresses (filters declared in the
|
|
124
|
-
* tool schema but silently dropped) lived in this logic, so it gets direct
|
|
125
|
-
* coverage independent of Mail.app.
|
|
126
|
-
*/
|
|
127
|
-
export declare function buildSearchCondition(filters: SearchConditionFilters): string;
|
|
128
|
-
export declare class AppleMailManager {
|
|
129
|
-
/**
|
|
130
|
-
* Default account used when no account is specified.
|
|
131
|
-
*/
|
|
132
|
-
private defaultAccount;
|
|
133
|
-
/**
|
|
134
|
-
* TTL cache for expensive AppleScript queries that rarely change.
|
|
135
|
-
* Caches account list and per-account mailbox names to avoid
|
|
136
|
-
* redundant AppleScript roundtrips on every tool call.
|
|
137
|
-
*/
|
|
138
|
-
private cache;
|
|
139
|
-
/** Cache TTL in milliseconds (60 seconds). */
|
|
140
|
-
private readonly CACHE_TTL_MS;
|
|
141
|
-
/**
|
|
142
|
-
* Returns cached accounts or fetches fresh data if cache is expired/empty.
|
|
143
|
-
*/
|
|
144
|
-
private getCachedAccounts;
|
|
145
|
-
/**
|
|
146
|
-
* Returns cached mailbox names for an account, or fetches fresh.
|
|
147
|
-
* This caches only the name list used by resolveMailbox(), not the
|
|
148
|
-
* full Mailbox objects with counts (which change frequently).
|
|
149
|
-
*/
|
|
150
|
-
private getCachedMailboxNames;
|
|
151
|
-
/**
|
|
152
|
-
* Invalidate all caches. Call after operations that change
|
|
153
|
-
* mailbox structure (create/delete/rename mailbox).
|
|
154
|
-
*/
|
|
155
|
-
private invalidateCache;
|
|
156
|
-
/**
|
|
157
|
-
* Reads the live `enabled` flag for an account directly from Mail (bypassing
|
|
158
|
-
* the 60 s account cache) so a guard reflects an account that was enabled or
|
|
159
|
-
* disabled out-of-band. Returns true/false when known, or null when the probe
|
|
160
|
-
* is inconclusive — account not found, or the probe itself failed. Callers
|
|
161
|
-
* treat null as "can't tell, don't block".
|
|
162
|
-
*/
|
|
163
|
-
private isAccountEnabled;
|
|
164
|
-
/**
|
|
165
|
-
* Reads an account's `account type` from Mail (e.g. "imap", "iCloud", "pop",
|
|
166
|
-
* ".Mac", or "unknown" for Exchange). Returns the lowercased type string, or
|
|
167
|
-
* null when the probe is inconclusive (account not found / probe failed).
|
|
168
|
-
* Used to decide whether AppleScript can safely create/delete/rename a
|
|
169
|
-
* mailbox on the account (BUG B).
|
|
170
|
-
*/
|
|
171
|
-
private accountTypeOf;
|
|
172
|
-
/**
|
|
173
|
-
* True when the account stores its mailboxes server-side (IMAP / iCloud /
|
|
174
|
-
* Exchange), so AppleScript CANNOT reliably create, delete, or rename its
|
|
175
|
-
* folders — those ops must go through the IMAP backend. POP accounts keep
|
|
176
|
-
* everything local, so their mailboxes ARE AppleScript-writable.
|
|
177
|
-
*
|
|
178
|
-
* Returns null when the type can't be determined (fail open: an inconclusive
|
|
179
|
-
* probe should not block an operation).
|
|
180
|
-
*/
|
|
181
|
-
private isServerSideAccount;
|
|
182
|
-
/**
|
|
183
|
-
* Guard for AppleScript create-mailbox on a server-side account (BUG B). When
|
|
184
|
-
* the account stores mailboxes server-side, AppleScript can CREATE a folder
|
|
185
|
-
* but cannot later delete or rename it — so a bare create would orphan a
|
|
186
|
-
* mailbox the server can never remove. If IMAP is configured for the account
|
|
187
|
-
* the tool layer routes the op to IMAP before reaching here; if it isn't, we
|
|
188
|
-
* refuse rather than create something we can't remove. Returns an error string
|
|
189
|
-
* when the op must be refused, else null (POP / local / indeterminate accounts
|
|
190
|
-
* fall through to AppleScript).
|
|
191
|
-
*/
|
|
192
|
-
private serverSideCreateGuard;
|
|
193
|
-
/**
|
|
194
|
-
* Guard for AppleScript-backed structural operations (create / delete / rename
|
|
195
|
-
* mailbox). When the target account is disabled in Mail, Mail holds no live
|
|
196
|
-
* server session for it, so the operation fails inside Mail with an opaque
|
|
197
|
-
* AppleEvent -10000 — and a multi-step op like rename can leave half-built
|
|
198
|
-
* state behind (an orphaned destination mailbox). Detect the disabled account
|
|
199
|
-
* up front and refuse with an actionable message instead of attempting the
|
|
200
|
-
* doomed op.
|
|
201
|
-
*
|
|
202
|
-
* Returns an error string when the account is known-disabled, else null —
|
|
203
|
-
* including when the state can't be determined. We fail open: an inconclusive
|
|
204
|
-
* probe never blocks an otherwise-valid operation.
|
|
205
|
-
*
|
|
206
|
-
* Applies only to the AppleScript backend. Direct-IMAP accounts talk to the
|
|
207
|
-
* server independent of Mail's enabled toggle and are routed before reaching
|
|
208
|
-
* the manager.
|
|
209
|
-
*/
|
|
210
|
-
private disabledAccountGuard;
|
|
211
|
-
/**
|
|
212
|
-
* Best-effort rollback for a failed rename: delete a just-created destination
|
|
213
|
-
* mailbox, but ONLY if it is empty, so any messages that did move are never
|
|
214
|
-
* destroyed. Returns true if the empty orphan was removed.
|
|
215
|
-
*/
|
|
216
|
-
private deleteMailboxIfEmpty;
|
|
217
|
-
/**
|
|
218
|
-
* Resolves the account to use for an operation when the caller omits one.
|
|
219
|
-
*
|
|
220
|
-
* Order (see chooseDefaultAccount): the APPLE_MAIL_MCP_DEFAULT_ACCOUNT env
|
|
221
|
-
* override → Mail.app's configured default-send account (if enabled) → the
|
|
222
|
-
* first enabled account. A disabled account is never chosen implicitly (#47).
|
|
223
|
-
*/
|
|
224
|
-
private resolveAccount;
|
|
225
|
-
/**
|
|
226
|
-
* Resolves a mailbox name to its actual name in the account.
|
|
227
|
-
*
|
|
228
|
-
* Different account types (IMAP, Exchange, iCloud) use different
|
|
229
|
-
* mailbox naming conventions:
|
|
230
|
-
* - IMAP/Gmail: "INBOX", "Sent", "Drafts"
|
|
231
|
-
* - Exchange: "Inbox", "Sent Items", "Deleted Items"
|
|
232
|
-
* - iCloud: "INBOX", "Sent", "Trash"
|
|
233
|
-
*
|
|
234
|
-
* This method tries to find a matching mailbox by:
|
|
235
|
-
* 1. Exact match
|
|
236
|
-
* 2. Case-insensitive match
|
|
237
|
-
* 3. Known aliases (e.g., "Sent" -> "Sent Items")
|
|
238
|
-
*
|
|
239
|
-
* @param mailbox - Requested mailbox name
|
|
240
|
-
* @param account - Account to search in
|
|
241
|
-
* @returns Actual mailbox name, or original if not found
|
|
242
|
-
*/
|
|
243
|
-
private resolveMailbox;
|
|
244
|
-
/**
|
|
245
|
-
* Search for messages matching criteria.
|
|
246
|
-
*
|
|
247
|
-
* @param query - Text to search for in subject or sender
|
|
248
|
-
* @param mailbox - Mailbox to search in (e.g., "INBOX")
|
|
249
|
-
* @param account - Account to search in
|
|
250
|
-
* @param limit - Maximum number of results
|
|
251
|
-
* @returns Array of matching messages
|
|
252
|
-
*/
|
|
253
|
-
searchMessages(query?: string, mailbox?: string, account?: string, limit?: number, dateFrom?: string, dateTo?: string, from?: string, subject?: string, isRead?: boolean, isFlagged?: boolean): Message[];
|
|
254
|
-
/**
|
|
255
|
-
* Search for messages, returning both the matches and diagnostics describing
|
|
256
|
-
* how complete the search was.
|
|
257
|
-
*
|
|
258
|
-
* This is the correctness fix for issue #24. The previous implementation ran
|
|
259
|
-
* an unbounded `messages of mb whose <predicate>` over every mailbox in an
|
|
260
|
-
* account; on large IMAP/Gmail mailboxes (tens of thousands of messages) that
|
|
261
|
-
* single Apple Event exceeded the timeout, the error was swallowed by a `try`,
|
|
262
|
-
* and the function returned a clean — but wrong — empty result. Callers/agents
|
|
263
|
-
* then confidently reported "no such mail."
|
|
264
|
-
*
|
|
265
|
-
* Two changes fix that:
|
|
266
|
-
* 1. Cheap count-guard: mailboxes larger than the scan threshold are skipped
|
|
267
|
-
* (Apple Mail can't search them before timing out anyway) and reported.
|
|
268
|
-
* 2. Honest diagnostics: per-account/per-mailbox timeouts are surfaced as a
|
|
269
|
-
* `partial` result with the affected scopes named, instead of an empty
|
|
270
|
-
* "success."
|
|
271
|
-
*/
|
|
272
|
-
searchMessagesWithDiagnostics(query?: string, mailbox?: string, account?: string, limit?: number, dateFrom?: string, dateTo?: string, from?: string, subject?: string, isRead?: boolean, isFlagged?: boolean): SearchResult;
|
|
273
|
-
/**
|
|
274
|
-
* Split a per-account search payload into its message list and the DIAG
|
|
275
|
-
* trailer, parse both, and return a SearchResult. See searchMessagesWithDiagnostics.
|
|
276
|
-
*/
|
|
277
|
-
private parseSearchResult;
|
|
278
|
-
/**
|
|
279
|
-
* Get a message by ID.
|
|
280
|
-
*
|
|
281
|
-
* Note: Mail.app message IDs are unique per mailbox. This method searches
|
|
282
|
-
* all mailboxes in all accounts to find the message.
|
|
283
|
-
*/
|
|
284
|
-
getMessageById(id: string, deepAttachmentCheck?: boolean): Message | null;
|
|
285
|
-
/**
|
|
286
|
-
* Get the content of a message.
|
|
287
|
-
*
|
|
288
|
-
* @param id - Message ID
|
|
289
|
-
* @param includeHtml - When true, also fetch the raw MIME source and extract
|
|
290
|
-
* the `text/html` body part into `htmlContent`. This is opt-in because the
|
|
291
|
-
* source can be MB-sized (it includes base64 attachments) and the plain-text
|
|
292
|
-
* path doesn't need it; fetching it unconditionally was both slow and, worse,
|
|
293
|
-
* returned the entire raw MIME blob mislabeled as HTML (#32).
|
|
294
|
-
*/
|
|
295
|
-
getMessageContent(id: string, includeHtml?: boolean): MessageContent | null;
|
|
296
|
-
/**
|
|
297
|
-
* Get the raw MIME source of a message.
|
|
298
|
-
* Used as fallback for attachment extraction when AppleScript
|
|
299
|
-
* mail attachments returns empty.
|
|
300
|
-
*
|
|
301
|
-
* Timeout is 2x the default (120s) because `source of msg` returns
|
|
302
|
-
* the entire raw message including base64-encoded attachments —
|
|
303
|
-
* a 20MB attachment can take several seconds over Exchange/IMAP.
|
|
304
|
-
*/
|
|
305
|
-
getRawSource(id: string): string | null;
|
|
306
|
-
/**
|
|
307
|
-
* List messages in a mailbox.
|
|
308
|
-
*
|
|
309
|
-
* @param mailbox - Mailbox to list from (default: INBOX)
|
|
310
|
-
* @param account - Account to list from
|
|
311
|
-
* @param limit - Maximum number of messages
|
|
312
|
-
* @returns Array of messages
|
|
313
|
-
*/
|
|
314
|
-
listMessages(mailbox?: string, account?: string, limit?: number, from?: string, offset?: number): Message[];
|
|
315
|
-
/**
|
|
316
|
-
* List messages, returning matches plus coverage diagnostics.
|
|
317
|
-
*
|
|
318
|
-
* Like `searchMessages`, the unscoped (all-mailboxes) path used to iterate
|
|
319
|
-
* `messages of mb` over every mailbox with a swallowing per-mailbox `try`,
|
|
320
|
-
* so a large IMAP/Gmail mailbox timed out and the method returned `[]` — a
|
|
321
|
-
* false "No messages found." This applies the same #24 discipline: skip
|
|
322
|
-
* mailboxes above the scan threshold (reported), enforce a per-account
|
|
323
|
-
* wall-clock budget, capture per-mailbox timeouts, and surface all of it as a
|
|
324
|
-
* partial result. (by-id lookups don't need this — `whose id is` is indexed
|
|
325
|
-
* and returns instantly even on a 44k-message mailbox.)
|
|
326
|
-
*/
|
|
327
|
-
listMessagesWithDiagnostics(mailbox?: string, account?: string, limit?: number, from?: string, offset?: number): SearchResult;
|
|
328
|
-
/**
|
|
329
|
-
* Parse message list output from AppleScript.
|
|
330
|
-
*
|
|
331
|
-
* Two emission schemas, disambiguated by length:
|
|
332
|
-
* 7 fields: single-mailbox — ...|hasAtt (mailbox from caller)
|
|
333
|
-
* 8 fields: all-mailboxes — ...|mailbox|hasAtt
|
|
334
|
-
*
|
|
335
|
-
* `hasAttachments` here is the fast-path AppleScript count only; it will
|
|
336
|
-
* false-negative for MIME-embedded attachments (a known AppleScript
|
|
337
|
-
* limitation). Use getMessage or list-attachments for authoritative info.
|
|
338
|
-
*/
|
|
339
|
-
private parseMessageList;
|
|
340
|
-
/**
|
|
341
|
-
* Send an email.
|
|
342
|
-
*
|
|
343
|
-
* @param to - Recipient email addresses
|
|
344
|
-
* @param subject - Email subject
|
|
345
|
-
* @param body - Email body (plain text)
|
|
346
|
-
* @param cc - CC recipients
|
|
347
|
-
* @param bcc - BCC recipients
|
|
348
|
-
* @param account - Account to send from
|
|
349
|
-
* @returns true if sent successfully
|
|
350
|
-
*/
|
|
351
|
-
sendEmail(to: string[], subject: string, body: string, cc?: string[], bcc?: string[], account?: string, attachments?: AttachmentInput[]): boolean;
|
|
352
|
-
private sendEmailWithPaths;
|
|
353
|
-
/**
|
|
354
|
-
* Send individual personalized emails to a list of recipients (mail merge).
|
|
355
|
-
*
|
|
356
|
-
* Replaces {{placeholder}} tokens in subject and body with per-recipient values.
|
|
357
|
-
* Each recipient receives their own individual email.
|
|
358
|
-
*
|
|
359
|
-
* @param recipients - List of recipient objects with email and variable values
|
|
360
|
-
* @param subject - Email subject (may contain {{placeholders}})
|
|
361
|
-
* @param body - Email body (may contain {{placeholders}})
|
|
362
|
-
* @param account - Account to send from
|
|
363
|
-
* @param delayMs - Delay between sends in milliseconds (default: 500, max: 10000)
|
|
364
|
-
* @returns Array of per-recipient results
|
|
365
|
-
*/
|
|
366
|
-
sendSerialEmail(recipients: SerialEmailRecipient[], subject: string, body: string, account?: string, delayMs?: number): SerialEmailResult[];
|
|
367
|
-
/**
|
|
368
|
-
* Create a draft email (saved to Drafts folder, not sent).
|
|
369
|
-
*
|
|
370
|
-
* @param to - Recipient email addresses
|
|
371
|
-
* @param subject - Email subject
|
|
372
|
-
* @param body - Email body (plain text)
|
|
373
|
-
* @param cc - CC recipients
|
|
374
|
-
* @param bcc - BCC recipients
|
|
375
|
-
* @param account - Account to create draft in
|
|
376
|
-
* @returns true if draft created successfully
|
|
377
|
-
*/
|
|
378
|
-
createDraft(to: string[], subject: string, body: string, cc?: string[], bcc?: string[], account?: string, attachments?: AttachmentInput[]): boolean;
|
|
379
|
-
private createDraftWithCommands;
|
|
380
|
-
/**
|
|
381
|
-
* Reply to a message.
|
|
382
|
-
*
|
|
383
|
-
* @param id - Message ID to reply to
|
|
384
|
-
* @param body - Reply body
|
|
385
|
-
* @param replyAll - If true, reply to all recipients
|
|
386
|
-
* @param send - If true, send immediately; if false, save as draft
|
|
387
|
-
* @returns true if reply created/sent successfully
|
|
388
|
-
*/
|
|
389
|
-
replyToMessage(id: string, body: string, replyAll?: boolean, send?: boolean): boolean;
|
|
390
|
-
/**
|
|
391
|
-
* Forward a message.
|
|
392
|
-
*
|
|
393
|
-
* @param id - Message ID to forward
|
|
394
|
-
* @param to - Recipients to forward to
|
|
395
|
-
* @param body - Optional body to prepend
|
|
396
|
-
* @param send - If true, send immediately; if false, save as draft
|
|
397
|
-
* @returns true if forward created/sent successfully
|
|
398
|
-
*/
|
|
399
|
-
forwardMessage(id: string, to: string[], body?: string, send?: boolean): boolean;
|
|
400
|
-
/**
|
|
401
|
-
* Helper to find and operate on a message by ID.
|
|
402
|
-
*/
|
|
403
|
-
private findMessageScript;
|
|
404
|
-
/**
|
|
405
|
-
* Mark a message as read.
|
|
406
|
-
*/
|
|
407
|
-
markAsRead(id: string): boolean;
|
|
408
|
-
/**
|
|
409
|
-
* Mark a message as unread.
|
|
410
|
-
*/
|
|
411
|
-
markAsUnread(id: string): boolean;
|
|
412
|
-
/**
|
|
413
|
-
* AppleScript statement(s) to flag a message variable, optionally setting its
|
|
414
|
-
* color. `colorIndex` is Apple's flag-index palette (0 red, 1 orange,
|
|
415
|
-
* 2 yellow, 3 green, 4 blue, 5 purple, 6 gray); it is validated to 0-6 by the
|
|
416
|
-
* schema layer and is a number, so it is safe to interpolate. Omitting it
|
|
417
|
-
* applies Mail's default flag without touching the color.
|
|
418
|
-
*/
|
|
419
|
-
private flagOperation;
|
|
420
|
-
/**
|
|
421
|
-
* Flag a message, optionally with a color (see {@link flagOperation}).
|
|
422
|
-
*/
|
|
423
|
-
flagMessage(id: string, colorIndex?: number): boolean;
|
|
424
|
-
/**
|
|
425
|
-
* Resolve a message's numeric Mail.app id from its RFC822 Message-ID (the
|
|
426
|
-
* backend-independent join key). This bridges an `imap:` id to the numeric id
|
|
427
|
-
* required to apply a flag *color* — IMAP flags are colorless, so a smart
|
|
428
|
-
* mailbox keyed on flag color can only ever match a message flagged via the
|
|
429
|
-
* AppleScript numeric-id path.
|
|
430
|
-
*
|
|
431
|
-
* The Message-ID is matched both bracketless and `<bracketed>` (Mail returns
|
|
432
|
-
* it bracketless; IMAP envelopes carry the brackets). When `accountName` is
|
|
433
|
-
* given the search is scoped to that account, checking its INBOX first (swept
|
|
434
|
-
* messages live there) to avoid scanning huge All Mail/Archive mailboxes.
|
|
435
|
-
*
|
|
436
|
-
* @returns the numeric id as a string, or null if no message matches.
|
|
437
|
-
*/
|
|
438
|
-
findNumericIdByMessageId(messageId: string, accountName?: string): string | null;
|
|
439
|
-
/**
|
|
440
|
-
* Unflag a message.
|
|
441
|
-
*/
|
|
442
|
-
unflagMessage(id: string): boolean;
|
|
443
|
-
/**
|
|
444
|
-
* Delete a message.
|
|
445
|
-
*/
|
|
446
|
-
deleteMessage(id: string): {
|
|
447
|
-
success: boolean;
|
|
448
|
-
error?: string;
|
|
449
|
-
};
|
|
450
|
-
/**
|
|
451
|
-
* Classify a failed message mutation (delete/move) into an actionable error.
|
|
452
|
-
*
|
|
453
|
-
* Mail.app's scripting bridge cannot delete or move drafts, and cannot mutate
|
|
454
|
-
* messages in some server-side special mailboxes — it throws `AppleEvent
|
|
455
|
-
* handler failed` rather than a useful message (#42). When that pattern is
|
|
456
|
-
* seen, look up the message's mailbox (cheap, indexed `whose id is`) to give a
|
|
457
|
-
* draft-specific or server-specific hint. Other errors (e.g. "Message not
|
|
458
|
-
* found", "ambiguous destination") pass through unchanged.
|
|
459
|
-
*/
|
|
460
|
-
private classifyMessageMutationError;
|
|
461
|
-
/**
|
|
462
|
-
* Move a message to a different mailbox.
|
|
463
|
-
*/
|
|
464
|
-
/**
|
|
465
|
-
* Move a message to a destination mailbox, with full nested-mailbox support.
|
|
466
|
-
*
|
|
467
|
-
* Resolving the destination as `mailbox "X" of account "Y"` only finds
|
|
468
|
-
* top-level mailboxes, so nested destinations (e.g. a "Moore" subfolder)
|
|
469
|
-
* silently failed. Instead we walk the target account's full mailbox tree and
|
|
470
|
-
* match by name. Resolution is:
|
|
471
|
-
* - account-scoped (won't move to a same-named mailbox in another account)
|
|
472
|
-
* - ambiguity-aware: if the name matches more than one mailbox in the
|
|
473
|
-
* account we refuse to guess and return an error — silently moving mail to
|
|
474
|
-
* the wrong folder is worse than failing.
|
|
475
|
-
* The source message is located by walking every account's tree breadth-first
|
|
476
|
-
* (top-level mailboxes like Inbox are checked first), so messages in nested
|
|
477
|
-
* mailboxes are found too.
|
|
478
|
-
*
|
|
479
|
-
* Returns a result object so batch callers can surface the specific failure
|
|
480
|
-
* (destination not found / ambiguous / message not found).
|
|
481
|
-
*/
|
|
482
|
-
private moveMessageInternal;
|
|
483
|
-
moveMessage(id: string, mailbox: string, account?: string): {
|
|
484
|
-
success: boolean;
|
|
485
|
-
error?: string;
|
|
486
|
-
};
|
|
487
|
-
/**
|
|
488
|
-
* Run one operation over many message IDs in a SINGLE osascript invocation.
|
|
489
|
-
*
|
|
490
|
-
* Previously each batch method looped and called the per-id method, so a
|
|
491
|
-
* 100-id batch spawned 100 osascript processes — each one re-resolving
|
|
492
|
-
* accounts and walking the whole account→mailbox tree — all serialized
|
|
493
|
-
* through the gate (issue #31). This walks the tree exactly once: for each
|
|
494
|
-
* mailbox it probes the still-pending IDs with `whose id is` (indexed, so
|
|
495
|
-
* effectively free) and applies `operation` to any match, tracking found IDs
|
|
496
|
-
* so it can stop early once all are accounted for. Per-id outcomes come back
|
|
497
|
-
* as control-char-delimited `id<FS>status` records (status: `ok`,
|
|
498
|
-
* `notfound`, or `error:<msg>`), and results are returned in input order.
|
|
499
|
-
*
|
|
500
|
-
* `setup` runs once before the walk (used by move to resolve the destination);
|
|
501
|
-
* it may bail the whole batch by returning a `BATCH_FATAL`-prefixed string.
|
|
502
|
-
*/
|
|
503
|
-
private runBatchOperation;
|
|
504
|
-
/**
|
|
505
|
-
* Delete multiple messages at once (single tree walk — see runBatchOperation).
|
|
506
|
-
*/
|
|
507
|
-
batchDeleteMessages(ids: string[]): BatchOperationResult[];
|
|
508
|
-
/**
|
|
509
|
-
* Move multiple messages to a mailbox at once (single tree walk).
|
|
510
|
-
*
|
|
511
|
-
* The destination is resolved once (account-scoped, ambiguity-aware — a name
|
|
512
|
-
* matching more than one mailbox fails the whole batch rather than guessing),
|
|
513
|
-
* then every matched message is moved in the same walk.
|
|
514
|
-
*/
|
|
515
|
-
batchMoveMessages(ids: string[], mailbox: string, account?: string): BatchOperationResult[];
|
|
516
|
-
/**
|
|
517
|
-
* Mark multiple messages as read at once (single tree walk).
|
|
518
|
-
*/
|
|
519
|
-
batchMarkAsRead(ids: string[]): BatchOperationResult[];
|
|
520
|
-
/**
|
|
521
|
-
* Mark multiple messages as unread at once (single tree walk).
|
|
522
|
-
*/
|
|
523
|
-
batchMarkAsUnread(ids: string[]): BatchOperationResult[];
|
|
524
|
-
/**
|
|
525
|
-
* Flag multiple messages at once (single tree walk).
|
|
526
|
-
*/
|
|
527
|
-
batchFlagMessages(ids: string[], colorIndex?: number): BatchOperationResult[];
|
|
528
|
-
/**
|
|
529
|
-
* Unflag multiple messages at once (single tree walk).
|
|
530
|
-
*/
|
|
531
|
-
batchUnflagMessages(ids: string[]): BatchOperationResult[];
|
|
532
|
-
/**
|
|
533
|
-
* List attachments for a message.
|
|
534
|
-
* Tries AppleScript first, falls back to MIME source parsing
|
|
535
|
-
* when AppleScript returns empty (known issue across all account types).
|
|
536
|
-
*/
|
|
537
|
-
listAttachments(id: string): Attachment[];
|
|
538
|
-
/**
|
|
539
|
-
* Save an attachment from a message to disk.
|
|
540
|
-
* Tries AppleScript first, falls back to MIME source extraction
|
|
541
|
-
* when AppleScript can't find the attachment.
|
|
542
|
-
*/
|
|
543
|
-
saveAttachment(id: string, attachmentName: string, savePath: string): boolean;
|
|
544
|
-
/**
|
|
545
|
-
* Fetch an attachment's bytes as base64 (B4) — the read counterpart to
|
|
546
|
-
* sending inline base64 content. Reuses saveAttachment via a throwaway temp
|
|
547
|
-
* dir (under an allowed root), then reads and encodes the file.
|
|
548
|
-
*/
|
|
549
|
-
getAttachmentBase64(id: string, attachmentName: string): {
|
|
550
|
-
success: boolean;
|
|
551
|
-
base64?: string;
|
|
552
|
-
bytes?: number;
|
|
553
|
-
error?: string;
|
|
554
|
-
};
|
|
555
|
-
/**
|
|
556
|
-
* List all mailboxes for an account.
|
|
557
|
-
*/
|
|
558
|
-
listMailboxes(account?: string): Mailbox[];
|
|
559
|
-
/**
|
|
560
|
-
* Get unread count for a mailbox.
|
|
561
|
-
*/
|
|
562
|
-
getUnreadCount(mailbox?: string, account?: string): number;
|
|
563
|
-
/**
|
|
564
|
-
* Create a new mailbox.
|
|
565
|
-
*/
|
|
566
|
-
createMailbox(name: string, account?: string): {
|
|
567
|
-
success: boolean;
|
|
568
|
-
error?: string;
|
|
569
|
-
};
|
|
570
|
-
/**
|
|
571
|
-
* Delete a mailbox.
|
|
572
|
-
*/
|
|
573
|
-
deleteMailbox(name: string, account?: string): {
|
|
574
|
-
success: boolean;
|
|
575
|
-
error?: string;
|
|
576
|
-
};
|
|
577
|
-
/**
|
|
578
|
-
* Rename a mailbox by creating a new one, moving messages, and deleting the old one.
|
|
579
|
-
*/
|
|
580
|
-
renameMailbox(oldName: string, newName: string, account?: string): {
|
|
581
|
-
success: boolean;
|
|
582
|
-
error?: string;
|
|
583
|
-
};
|
|
584
|
-
/**
|
|
585
|
-
* List all mail accounts (uses cache).
|
|
586
|
-
*/
|
|
587
|
-
listAccounts(): Account[];
|
|
588
|
-
/**
|
|
589
|
-
* Fetches account list directly from Mail.app via AppleScript.
|
|
590
|
-
* Used internally by the cache; prefer getCachedAccounts() or listAccounts().
|
|
591
|
-
*/
|
|
592
|
-
private fetchAccounts;
|
|
593
|
-
/**
|
|
594
|
-
* Fetches mailbox names for an account directly from Mail.app.
|
|
595
|
-
* Used internally by the cache; prefer getCachedMailboxNames().
|
|
596
|
-
*/
|
|
597
|
-
private fetchMailboxNames;
|
|
598
|
-
/**
|
|
599
|
-
* List all mail rules.
|
|
600
|
-
*/
|
|
601
|
-
listRules(): MailRule[];
|
|
602
|
-
/**
|
|
603
|
-
* Enable or disable a mail rule.
|
|
604
|
-
*/
|
|
605
|
-
setRuleEnabled(ruleName: string, enabled: boolean): boolean;
|
|
606
|
-
/**
|
|
607
|
-
* Create a mail rule (B2). Builds conditions (from/to/cc/subject/content with
|
|
608
|
-
* a match operator) and actions (mark read/flagged, delete, move to a
|
|
609
|
-
* mailbox) on a real Mail.app rule. Returns an error string on failure.
|
|
610
|
-
*/
|
|
611
|
-
createRule(opts: RuleSpec): {
|
|
612
|
-
success: boolean;
|
|
613
|
-
error?: string;
|
|
614
|
-
};
|
|
615
|
-
/**
|
|
616
|
-
* Delete a mail rule by name (B2). Returns false if no such rule exists.
|
|
617
|
-
*/
|
|
618
|
-
deleteRule(ruleName: string): boolean;
|
|
619
|
-
/**
|
|
620
|
-
* Search contacts by name or email.
|
|
621
|
-
*/
|
|
622
|
-
searchContacts(query: string): Contact[];
|
|
623
|
-
private templateStore;
|
|
624
|
-
/**
|
|
625
|
-
* List all stored templates.
|
|
626
|
-
*/
|
|
627
|
-
listTemplates(): EmailTemplate[];
|
|
628
|
-
/**
|
|
629
|
-
* Get a template by ID.
|
|
630
|
-
*/
|
|
631
|
-
getTemplate(id: string): EmailTemplate | null;
|
|
632
|
-
/**
|
|
633
|
-
* Create or update a template (persisted).
|
|
634
|
-
*/
|
|
635
|
-
saveTemplate(name: string, subject: string, body: string, to?: string[], cc?: string[], id?: string): EmailTemplate;
|
|
636
|
-
/**
|
|
637
|
-
* Delete a template (persisted).
|
|
638
|
-
*/
|
|
639
|
-
deleteTemplate(id: string): boolean;
|
|
640
|
-
/**
|
|
641
|
-
* Use a template to create a draft.
|
|
642
|
-
*/
|
|
643
|
-
useTemplate(id: string, overrides?: {
|
|
644
|
-
to?: string[];
|
|
645
|
-
cc?: string[];
|
|
646
|
-
subject?: string;
|
|
647
|
-
body?: string;
|
|
648
|
-
}): boolean;
|
|
649
|
-
/**
|
|
650
|
-
* Run health check on Mail.app connectivity.
|
|
651
|
-
*/
|
|
652
|
-
healthCheck(): HealthCheckResult;
|
|
653
|
-
/**
|
|
654
|
-
* Get mail statistics.
|
|
655
|
-
*/
|
|
656
|
-
getMailStats(): MailStats;
|
|
657
|
-
/**
|
|
658
|
-
* Get counts of recently received messages.
|
|
659
|
-
*
|
|
660
|
-
* Counts messages in each account's receiving mailbox for performance
|
|
661
|
-
* (scanning all mailboxes is too slow for large accounts): the literal
|
|
662
|
-
* "INBOX" for ordinary accounts, or the "All Mail" superset for Gmail-style
|
|
663
|
-
* accounts whose literal "INBOX" is an empty virtual shell (BUG A2).
|
|
664
|
-
*
|
|
665
|
-
* @returns Counts of messages received in last 24h, 7d, and 30d
|
|
666
|
-
*/
|
|
667
|
-
getRecentlyReceivedStats(): RecentlyReceivedStats;
|
|
668
|
-
/**
|
|
669
|
-
* Get sync status for Mail.app.
|
|
670
|
-
*
|
|
671
|
-
* Checks for sync activity indicators like:
|
|
672
|
-
* - Activity monitor status
|
|
673
|
-
* - Network activity status
|
|
674
|
-
* - Background refresh indicators
|
|
675
|
-
*
|
|
676
|
-
* @returns Sync status information
|
|
677
|
-
*/
|
|
678
|
-
getSyncStatus(): SyncStatus;
|
|
679
|
-
}
|
|
680
|
-
//# sourceMappingURL=appleMailManager.d.ts.map
|