@vox-ai-app/integrations 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/README.md +125 -0
- package/package.json +42 -0
- package/src/imessage/def.js +41 -0
- package/src/imessage/index.js +9 -0
- package/src/imessage/mac/data.js +144 -0
- package/src/imessage/mac/reply.js +68 -0
- package/src/imessage/mac/service.js +141 -0
- package/src/imessage/tools.js +44 -0
- package/src/index.js +7 -0
- package/src/mail/def.js +317 -0
- package/src/mail/index.js +165 -0
- package/src/mail/manage/index.js +10 -0
- package/src/mail/manage/mac/index.js +275 -0
- package/src/mail/read/index.js +1 -0
- package/src/mail/read/mac/accounts.js +53 -0
- package/src/mail/read/mac/index.js +170 -0
- package/src/mail/read/mac/permission.js +29 -0
- package/src/mail/read/mac/sync.js +98 -0
- package/src/mail/read/mac/transform.js +55 -0
- package/src/mail/send/index.js +1 -0
- package/src/mail/send/mac/index.js +93 -0
- package/src/mail/shared/index.js +6 -0
- package/src/mail/shared/mac/index.js +48 -0
- package/src/mail/tools.js +41 -0
- package/src/screen/capture/index.js +1 -0
- package/src/screen/capture/mac/index.js +109 -0
- package/src/screen/control/index.js +15 -0
- package/src/screen/control/mac/accessibility.js +25 -0
- package/src/screen/control/mac/apps.js +62 -0
- package/src/screen/control/mac/exec.js +66 -0
- package/src/screen/control/mac/helpers.js +5 -0
- package/src/screen/control/mac/index.js +10 -0
- package/src/screen/control/mac/keyboard.js +34 -0
- package/src/screen/control/mac/keycodes.js +87 -0
- package/src/screen/control/mac/mouse.js +59 -0
- package/src/screen/control/mac/python-keyboard.js +66 -0
- package/src/screen/control/mac/python-mouse.js +66 -0
- package/src/screen/control/mac/python.js +2 -0
- package/src/screen/control/mac/ui-scan.js +45 -0
- package/src/screen/def.js +304 -0
- package/src/screen/index.js +17 -0
- package/src/screen/queue.js +54 -0
- package/src/screen/tools.js +50 -0
- package/src/tools.js +6 -0
package/src/mail/def.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
export const MAIL_TOOL_DEFINITIONS = [
|
|
2
|
+
{
|
|
3
|
+
name: 'read_emails',
|
|
4
|
+
description:
|
|
5
|
+
"Read emails from the user's Mail.app on macOS. By default 20 emails per account are returned; use offset for pagination. Returns a list of messages with id, sender, subject, date, read/unread status, flagged status, and account name, ordered newest first. Each message includes a unique id that can be used with other email tools (get_email_body, reply_to_email, forward_email, mark_email_read, delete_email, move_email, save_attachment). Requires Full Disk Access in System Settings → Privacy & Security.",
|
|
6
|
+
parameters: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
folder: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description:
|
|
12
|
+
'Mailbox folder name to read from. Default is "INBOX". Other examples: "Sent", "Drafts", "Archive".'
|
|
13
|
+
},
|
|
14
|
+
limit: {
|
|
15
|
+
type: 'number',
|
|
16
|
+
description: 'Maximum number of emails to return. Default 20, max 200.'
|
|
17
|
+
},
|
|
18
|
+
offset: {
|
|
19
|
+
type: 'number',
|
|
20
|
+
description:
|
|
21
|
+
'Number of matching messages to skip before returning results. Use for pagination. Default 0.'
|
|
22
|
+
},
|
|
23
|
+
unread_only: {
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
description: 'If true, only return unread emails. Default false.'
|
|
26
|
+
},
|
|
27
|
+
search: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description:
|
|
30
|
+
'Optional keyword to filter results by sender or subject. Case-insensitive. Filtering happens in the mail client for speed.'
|
|
31
|
+
},
|
|
32
|
+
account: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
description:
|
|
35
|
+
'Optional account name to read from (partial match, case-insensitive). If omitted, reads from all accounts. The account name is returned in read_emails results.'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
required: []
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'search_contacts',
|
|
43
|
+
description:
|
|
44
|
+
"Search the user's Contacts.app on macOS by name. Returns matching contacts with their name, email address, and where available: phone number, company, and job title. Call this before send_email whenever the user refers to a person by name rather than a full email address.",
|
|
45
|
+
parameters: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
query: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description:
|
|
51
|
+
'Name (or partial name) to search for. Case-insensitive. Examples: "Sara", "John Smith".'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
required: ['query']
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'send_email',
|
|
59
|
+
description:
|
|
60
|
+
"Send an email from a specific or the default mail account via Mail.app on macOS. Always call search_contacts first if you only know the recipient's name, not their full email address.",
|
|
61
|
+
parameters: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
to: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description:
|
|
67
|
+
'Recipient email address or comma-separated list of addresses. Must be fully resolved email addresses (e.g. sara@example.com), not names. Use search_contacts first if needed.'
|
|
68
|
+
},
|
|
69
|
+
subject: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'Email subject line.'
|
|
72
|
+
},
|
|
73
|
+
body: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
description: 'Plain text email body.'
|
|
76
|
+
},
|
|
77
|
+
cc: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: 'Optional CC email address or comma-separated list.'
|
|
80
|
+
},
|
|
81
|
+
bcc: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
description: 'Optional BCC email address or comma-separated list.'
|
|
84
|
+
},
|
|
85
|
+
attachments: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description:
|
|
88
|
+
'Optional comma-separated list of absolute local file paths to attach. Supports ~/ shortcuts.'
|
|
89
|
+
},
|
|
90
|
+
account: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description:
|
|
93
|
+
'Optional account name to send from (partial match, case-insensitive). If omitted, sends from the default account.'
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
required: ['to', 'subject', 'body']
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'get_email_body',
|
|
101
|
+
description:
|
|
102
|
+
"Retrieve the full body/content of a specific email from the user's local mail client. Also returns a list of attachment names if the email has any. Prefer using message_id (from read_emails) for fast, unambiguous lookup. Falls back to sender/subject search if no id provided.",
|
|
103
|
+
parameters: {
|
|
104
|
+
type: 'object',
|
|
105
|
+
properties: {
|
|
106
|
+
message_id: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
description:
|
|
109
|
+
'The unique message id returned by read_emails. Fastest and most reliable way to identify a specific email.'
|
|
110
|
+
},
|
|
111
|
+
sender: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
description:
|
|
114
|
+
'Sender name or email address to match (partial match, case-insensitive). Used only if message_id is not provided.'
|
|
115
|
+
},
|
|
116
|
+
subject: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description:
|
|
119
|
+
'Subject text to match (partial match, case-insensitive). Used only if message_id is not provided.'
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
required: []
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'reply_to_email',
|
|
127
|
+
description:
|
|
128
|
+
'Reply to a specific email. Sends the reply immediately via the local mail client. Use the message id from read_emails or get_email_body to identify the email.',
|
|
129
|
+
parameters: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
message_id: {
|
|
133
|
+
type: 'string',
|
|
134
|
+
description: 'The unique message id of the email to reply to (from read_emails).'
|
|
135
|
+
},
|
|
136
|
+
body: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
description: 'The reply body text.'
|
|
139
|
+
},
|
|
140
|
+
reply_all: {
|
|
141
|
+
type: 'boolean',
|
|
142
|
+
description: 'If true, reply to all recipients. Default false.'
|
|
143
|
+
},
|
|
144
|
+
account: {
|
|
145
|
+
type: 'string',
|
|
146
|
+
description:
|
|
147
|
+
'Optional account name to send the reply from (partial match). If omitted, replies from the account that received the email.'
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
required: ['message_id', 'body']
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'forward_email',
|
|
155
|
+
description:
|
|
156
|
+
'Forward a specific email to one or more recipients. Sends immediately via the local mail client.',
|
|
157
|
+
parameters: {
|
|
158
|
+
type: 'object',
|
|
159
|
+
properties: {
|
|
160
|
+
message_id: {
|
|
161
|
+
type: 'string',
|
|
162
|
+
description: 'The unique message id of the email to forward (from read_emails).'
|
|
163
|
+
},
|
|
164
|
+
to: {
|
|
165
|
+
type: 'string',
|
|
166
|
+
description:
|
|
167
|
+
'Recipient email address or comma-separated list to forward to. Must be resolved email addresses.'
|
|
168
|
+
},
|
|
169
|
+
body: {
|
|
170
|
+
type: 'string',
|
|
171
|
+
description: 'Optional message to prepend above the forwarded content.'
|
|
172
|
+
},
|
|
173
|
+
account: {
|
|
174
|
+
type: 'string',
|
|
175
|
+
description:
|
|
176
|
+
'Optional account name to forward from (partial match). If omitted, forwards from the account that received the email.'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
required: ['message_id', 'to']
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'mark_email_read',
|
|
184
|
+
description: 'Mark a specific email as read or unread.',
|
|
185
|
+
parameters: {
|
|
186
|
+
type: 'object',
|
|
187
|
+
properties: {
|
|
188
|
+
message_id: {
|
|
189
|
+
type: 'string',
|
|
190
|
+
description: 'The unique message id of the email (from read_emails).'
|
|
191
|
+
},
|
|
192
|
+
read: {
|
|
193
|
+
type: 'boolean',
|
|
194
|
+
description: 'True to mark as read, false to mark as unread. Default true.'
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
required: ['message_id']
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: 'flag_email',
|
|
202
|
+
description: 'Flag or unflag a specific email.',
|
|
203
|
+
parameters: {
|
|
204
|
+
type: 'object',
|
|
205
|
+
properties: {
|
|
206
|
+
message_id: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'The unique message id of the email (from read_emails).'
|
|
209
|
+
},
|
|
210
|
+
flagged: {
|
|
211
|
+
type: 'boolean',
|
|
212
|
+
description: 'True to flag, false to unflag. Default true.'
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
required: ['message_id']
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: 'delete_email',
|
|
220
|
+
description:
|
|
221
|
+
'Delete a specific email (moves it to Trash). This action can usually be undone by the user in their mail client.',
|
|
222
|
+
parameters: {
|
|
223
|
+
type: 'object',
|
|
224
|
+
properties: {
|
|
225
|
+
message_id: {
|
|
226
|
+
type: 'string',
|
|
227
|
+
description: 'The unique message id of the email to delete (from read_emails).'
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
required: ['message_id']
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'move_email',
|
|
235
|
+
description:
|
|
236
|
+
'Move a specific email to a different mailbox folder (e.g. Archive, Work, Finance).',
|
|
237
|
+
parameters: {
|
|
238
|
+
type: 'object',
|
|
239
|
+
properties: {
|
|
240
|
+
message_id: {
|
|
241
|
+
type: 'string',
|
|
242
|
+
description: 'The unique message id of the email to move (from read_emails).'
|
|
243
|
+
},
|
|
244
|
+
target_folder: {
|
|
245
|
+
type: 'string',
|
|
246
|
+
description:
|
|
247
|
+
'Name of the destination mailbox folder. Partial match is supported (e.g. "Archive", "Work").'
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
required: ['message_id', 'target_folder']
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: 'create_draft',
|
|
255
|
+
description:
|
|
256
|
+
"Create an email draft without sending it. The draft opens in the user's mail client for review. Use this when the user wants to review before sending, or says 'draft' instead of 'send'.",
|
|
257
|
+
parameters: {
|
|
258
|
+
type: 'object',
|
|
259
|
+
properties: {
|
|
260
|
+
to: {
|
|
261
|
+
type: 'string',
|
|
262
|
+
description: 'Recipient email address or comma-separated list.'
|
|
263
|
+
},
|
|
264
|
+
subject: {
|
|
265
|
+
type: 'string',
|
|
266
|
+
description: 'Email subject line.'
|
|
267
|
+
},
|
|
268
|
+
body: {
|
|
269
|
+
type: 'string',
|
|
270
|
+
description: 'Email body text.'
|
|
271
|
+
},
|
|
272
|
+
cc: {
|
|
273
|
+
type: 'string',
|
|
274
|
+
description: 'Optional CC email address or comma-separated list.'
|
|
275
|
+
},
|
|
276
|
+
bcc: {
|
|
277
|
+
type: 'string',
|
|
278
|
+
description: 'Optional BCC email address or comma-separated list.'
|
|
279
|
+
},
|
|
280
|
+
attachments: {
|
|
281
|
+
type: 'string',
|
|
282
|
+
description: 'Optional comma-separated list of absolute local file paths to attach.'
|
|
283
|
+
},
|
|
284
|
+
account: {
|
|
285
|
+
type: 'string',
|
|
286
|
+
description:
|
|
287
|
+
'Optional account name to create the draft in (partial match). If omitted, uses the default account.'
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
required: ['to', 'subject', 'body']
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
name: 'save_attachment',
|
|
295
|
+
description:
|
|
296
|
+
'Save/download an email attachment to a local folder. Use get_email_body first to see the list of attachment names, then call this with the attachment name to save it.',
|
|
297
|
+
parameters: {
|
|
298
|
+
type: 'object',
|
|
299
|
+
properties: {
|
|
300
|
+
message_id: {
|
|
301
|
+
type: 'string',
|
|
302
|
+
description: 'The unique message id of the email containing the attachment.'
|
|
303
|
+
},
|
|
304
|
+
attachment_name: {
|
|
305
|
+
type: 'string',
|
|
306
|
+
description: 'Name of the attachment to save (from get_email_body attachment list).'
|
|
307
|
+
},
|
|
308
|
+
save_path: {
|
|
309
|
+
type: 'string',
|
|
310
|
+
description:
|
|
311
|
+
'Local directory path to save the attachment to. Defaults to ~/Downloads. Supports ~/ shortcuts.'
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
required: ['message_id', 'attachment_name']
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
]
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { sendEmailMac, searchContactsMac } from './send/index.js'
|
|
2
|
+
import { readEmailsMac, getEmailBodyMac } from './read/index.js'
|
|
3
|
+
import {
|
|
4
|
+
replyToEmailMac,
|
|
5
|
+
forwardEmailMac,
|
|
6
|
+
markEmailReadMac,
|
|
7
|
+
flagEmailMac,
|
|
8
|
+
deleteEmailMac,
|
|
9
|
+
moveEmailMac,
|
|
10
|
+
createDraftMac,
|
|
11
|
+
saveAttachmentMac
|
|
12
|
+
} from './manage/index.js'
|
|
13
|
+
const normalizeList = (v) => {
|
|
14
|
+
if (!v) return []
|
|
15
|
+
if (Array.isArray(v)) return v.map((s) => String(s).trim()).filter(Boolean)
|
|
16
|
+
return String(v)
|
|
17
|
+
.split(/[,;]/)
|
|
18
|
+
.map((s) => s.trim())
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
}
|
|
21
|
+
export const sendEmail = async (payload) => {
|
|
22
|
+
const to = normalizeList(payload?.to)
|
|
23
|
+
if (!to.length) throw new Error('"to" is required.')
|
|
24
|
+
const args = {
|
|
25
|
+
to,
|
|
26
|
+
cc: normalizeList(payload?.cc),
|
|
27
|
+
bcc: normalizeList(payload?.bcc),
|
|
28
|
+
subject: String(payload?.subject || '').trim(),
|
|
29
|
+
body: String(payload?.body ?? payload?.text ?? payload?.content ?? '').trim(),
|
|
30
|
+
attachments: normalizeList(payload?.attachments ?? payload?.attachment),
|
|
31
|
+
account: String(payload?.account ?? '').trim() || undefined
|
|
32
|
+
}
|
|
33
|
+
return sendEmailMac(args)
|
|
34
|
+
}
|
|
35
|
+
export const readEmails = async (payload) => {
|
|
36
|
+
const folder = String(payload?.folder ?? 'INBOX').trim()
|
|
37
|
+
const limit = Math.min(Math.max(1, Number(payload?.limit ?? 20)), 200)
|
|
38
|
+
const offset = Math.max(0, Number(payload?.offset ?? 0))
|
|
39
|
+
const unreadOnly = Boolean(payload?.unread_only ?? payload?.unreadOnly ?? false)
|
|
40
|
+
const search = String(payload?.search ?? '').trim()
|
|
41
|
+
const account = String(payload?.account ?? '').trim() || undefined
|
|
42
|
+
const args = {
|
|
43
|
+
folder,
|
|
44
|
+
limit,
|
|
45
|
+
offset,
|
|
46
|
+
unreadOnly,
|
|
47
|
+
search,
|
|
48
|
+
account
|
|
49
|
+
}
|
|
50
|
+
const messages = await readEmailsMac(args)
|
|
51
|
+
return {
|
|
52
|
+
folder,
|
|
53
|
+
count: messages.length,
|
|
54
|
+
messages
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export const searchContacts = async (payload) => {
|
|
58
|
+
const query = String(payload?.query ?? payload?.name ?? payload?.q ?? '').trim()
|
|
59
|
+
if (!query) throw new Error('"query" is required.')
|
|
60
|
+
const contacts = await searchContactsMac(query)
|
|
61
|
+
return {
|
|
62
|
+
query,
|
|
63
|
+
count: contacts.length,
|
|
64
|
+
contacts
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export const getEmailBody = async (payload) => {
|
|
68
|
+
const sender = String(payload?.sender ?? payload?.from ?? '').trim()
|
|
69
|
+
const subject = String(payload?.subject ?? '').trim()
|
|
70
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
71
|
+
const args = {
|
|
72
|
+
sender,
|
|
73
|
+
subject,
|
|
74
|
+
messageId
|
|
75
|
+
}
|
|
76
|
+
return getEmailBodyMac(args)
|
|
77
|
+
}
|
|
78
|
+
export const replyToEmail = async (payload) => {
|
|
79
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
80
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
81
|
+
const body = String(payload?.body ?? '').trim()
|
|
82
|
+
if (!body) throw new Error('"body" is required.')
|
|
83
|
+
const replyAll = Boolean(payload?.reply_all ?? payload?.replyAll ?? false)
|
|
84
|
+
const account = String(payload?.account ?? '').trim() || undefined
|
|
85
|
+
return replyToEmailMac({
|
|
86
|
+
messageId,
|
|
87
|
+
body,
|
|
88
|
+
replyAll,
|
|
89
|
+
account
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
export const forwardEmail = async (payload) => {
|
|
93
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
94
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
95
|
+
const to = normalizeList(payload?.to)
|
|
96
|
+
if (!to.length) throw new Error('"to" is required.')
|
|
97
|
+
const body = String(payload?.body ?? '').trim()
|
|
98
|
+
const account = String(payload?.account ?? '').trim() || undefined
|
|
99
|
+
return forwardEmailMac({
|
|
100
|
+
messageId,
|
|
101
|
+
to,
|
|
102
|
+
body,
|
|
103
|
+
account
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
export const markEmailRead = async (payload) => {
|
|
107
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
108
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
109
|
+
const read = payload?.read !== undefined ? Boolean(payload.read) : true
|
|
110
|
+
return markEmailReadMac({
|
|
111
|
+
messageId,
|
|
112
|
+
read
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
export const flagEmail = async (payload) => {
|
|
116
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
117
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
118
|
+
const flagged = payload?.flagged !== undefined ? Boolean(payload.flagged) : true
|
|
119
|
+
return flagEmailMac({
|
|
120
|
+
messageId,
|
|
121
|
+
flagged
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
export const deleteEmail = async (payload) => {
|
|
125
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
126
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
127
|
+
return deleteEmailMac({
|
|
128
|
+
messageId
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
export const moveEmail = async (payload) => {
|
|
132
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
133
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
134
|
+
const targetFolder = String(payload?.target_folder ?? payload?.targetFolder ?? '').trim()
|
|
135
|
+
if (!targetFolder) throw new Error('"target_folder" is required.')
|
|
136
|
+
return moveEmailMac({
|
|
137
|
+
messageId,
|
|
138
|
+
targetFolder
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
export const createDraft = async (payload) => {
|
|
142
|
+
const to = normalizeList(payload?.to)
|
|
143
|
+
if (!to.length) throw new Error('"to" is required.')
|
|
144
|
+
return createDraftMac({
|
|
145
|
+
to,
|
|
146
|
+
subject: String(payload?.subject || '').trim(),
|
|
147
|
+
body: String(payload?.body ?? payload?.text ?? payload?.content ?? '').trim(),
|
|
148
|
+
cc: normalizeList(payload?.cc),
|
|
149
|
+
bcc: normalizeList(payload?.bcc),
|
|
150
|
+
attachments: normalizeList(payload?.attachments ?? payload?.attachment),
|
|
151
|
+
account: String(payload?.account ?? '').trim() || undefined
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
export const saveAttachment = async (payload) => {
|
|
155
|
+
const messageId = String(payload?.message_id ?? payload?.messageId ?? '').trim()
|
|
156
|
+
if (!messageId) throw new Error('"message_id" is required.')
|
|
157
|
+
const attachmentName = String(payload?.attachment_name ?? payload?.attachmentName ?? '').trim()
|
|
158
|
+
if (!attachmentName) throw new Error('"attachment_name" is required.')
|
|
159
|
+
const savePath = String(payload?.save_path ?? payload?.savePath ?? '').trim() || undefined
|
|
160
|
+
return saveAttachmentMac({
|
|
161
|
+
messageId,
|
|
162
|
+
attachmentName,
|
|
163
|
+
savePath
|
|
164
|
+
})
|
|
165
|
+
}
|