@jbctechsolutions/mcp-office365 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +667 -0
- package/dist/applescript/account-repository.d.ts +30 -0
- package/dist/applescript/account-repository.d.ts.map +1 -0
- package/dist/applescript/account-repository.js +38 -0
- package/dist/applescript/account-repository.js.map +1 -0
- package/dist/applescript/account-scripts.d.ts +21 -0
- package/dist/applescript/account-scripts.d.ts.map +1 -0
- package/dist/applescript/account-scripts.js +180 -0
- package/dist/applescript/account-scripts.js.map +1 -0
- package/dist/applescript/calendar-manager.d.ts +44 -0
- package/dist/applescript/calendar-manager.d.ts.map +1 -0
- package/dist/applescript/calendar-manager.js +92 -0
- package/dist/applescript/calendar-manager.js.map +1 -0
- package/dist/applescript/calendar-writer.d.ts +36 -0
- package/dist/applescript/calendar-writer.d.ts.map +1 -0
- package/dist/applescript/calendar-writer.js +94 -0
- package/dist/applescript/calendar-writer.js.map +1 -0
- package/dist/applescript/content-readers.d.ts +114 -0
- package/dist/applescript/content-readers.d.ts.map +1 -0
- package/dist/applescript/content-readers.js +328 -0
- package/dist/applescript/content-readers.js.map +1 -0
- package/dist/applescript/executor.d.ts +60 -0
- package/dist/applescript/executor.d.ts.map +1 -0
- package/dist/applescript/executor.js +173 -0
- package/dist/applescript/executor.js.map +1 -0
- package/dist/applescript/index.d.ts +20 -0
- package/dist/applescript/index.d.ts.map +1 -0
- package/dist/applescript/index.js +29 -0
- package/dist/applescript/index.js.map +1 -0
- package/dist/applescript/mail-sender.d.ts +38 -0
- package/dist/applescript/mail-sender.d.ts.map +1 -0
- package/dist/applescript/mail-sender.js +67 -0
- package/dist/applescript/mail-sender.js.map +1 -0
- package/dist/applescript/parser.d.ts +235 -0
- package/dist/applescript/parser.d.ts.map +1 -0
- package/dist/applescript/parser.js +496 -0
- package/dist/applescript/parser.js.map +1 -0
- package/dist/applescript/repository.d.ts +64 -0
- package/dist/applescript/repository.d.ts.map +1 -0
- package/dist/applescript/repository.js +444 -0
- package/dist/applescript/repository.js.map +1 -0
- package/dist/applescript/scripts.d.ts +265 -0
- package/dist/applescript/scripts.d.ts.map +1 -0
- package/dist/applescript/scripts.js +1483 -0
- package/dist/applescript/scripts.js.map +1 -0
- package/dist/approval/hash.d.ts +87 -0
- package/dist/approval/hash.d.ts.map +1 -0
- package/dist/approval/hash.js +102 -0
- package/dist/approval/hash.js.map +1 -0
- package/dist/approval/index.d.ts +13 -0
- package/dist/approval/index.d.ts.map +1 -0
- package/dist/approval/index.js +7 -0
- package/dist/approval/index.js.map +1 -0
- package/dist/approval/token-manager.d.ts +51 -0
- package/dist/approval/token-manager.d.ts.map +1 -0
- package/dist/approval/token-manager.js +111 -0
- package/dist/approval/token-manager.js.map +1 -0
- package/dist/approval/types.d.ts +44 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +6 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +143 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -0
- package/dist/database/connection.d.ts +77 -0
- package/dist/database/connection.d.ts.map +1 -0
- package/dist/database/connection.js +130 -0
- package/dist/database/connection.js.map +1 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +11 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/queries.d.ts +93 -0
- package/dist/database/queries.d.ts.map +1 -0
- package/dist/database/queries.js +430 -0
- package/dist/database/queries.js.map +1 -0
- package/dist/database/repository.d.ts +198 -0
- package/dist/database/repository.d.ts.map +1 -0
- package/dist/database/repository.js +199 -0
- package/dist/database/repository.js.map +1 -0
- package/dist/graph/attachments.d.ts +72 -0
- package/dist/graph/attachments.d.ts.map +1 -0
- package/dist/graph/attachments.js +207 -0
- package/dist/graph/attachments.js.map +1 -0
- package/dist/graph/auth/config.d.ts +34 -0
- package/dist/graph/auth/config.d.ts.map +1 -0
- package/dist/graph/auth/config.js +78 -0
- package/dist/graph/auth/config.js.map +1 -0
- package/dist/graph/auth/device-code-flow.d.ts +55 -0
- package/dist/graph/auth/device-code-flow.d.ts.map +1 -0
- package/dist/graph/auth/device-code-flow.js +180 -0
- package/dist/graph/auth/device-code-flow.js.map +1 -0
- package/dist/graph/auth/index.d.ts +13 -0
- package/dist/graph/auth/index.d.ts.map +1 -0
- package/dist/graph/auth/index.js +13 -0
- package/dist/graph/auth/index.js.map +1 -0
- package/dist/graph/auth/token-cache.d.ts +41 -0
- package/dist/graph/auth/token-cache.d.ts.map +1 -0
- package/dist/graph/auth/token-cache.js +105 -0
- package/dist/graph/auth/token-cache.js.map +1 -0
- package/dist/graph/client/batch.d.ts +38 -0
- package/dist/graph/client/batch.d.ts.map +1 -0
- package/dist/graph/client/batch.js +33 -0
- package/dist/graph/client/batch.js.map +1 -0
- package/dist/graph/client/cache.d.ts +64 -0
- package/dist/graph/client/cache.d.ts.map +1 -0
- package/dist/graph/client/cache.js +108 -0
- package/dist/graph/client/cache.js.map +1 -0
- package/dist/graph/client/graph-client.d.ts +630 -0
- package/dist/graph/client/graph-client.d.ts.map +1 -0
- package/dist/graph/client/graph-client.js +1771 -0
- package/dist/graph/client/graph-client.js.map +1 -0
- package/dist/graph/client/index.d.ts +12 -0
- package/dist/graph/client/index.d.ts.map +1 -0
- package/dist/graph/client/index.js +12 -0
- package/dist/graph/client/index.js.map +1 -0
- package/dist/graph/content-readers.d.ts +106 -0
- package/dist/graph/content-readers.d.ts.map +1 -0
- package/dist/graph/content-readers.js +321 -0
- package/dist/graph/content-readers.js.map +1 -0
- package/dist/graph/index.d.ts +18 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +23 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/mailbox-adapter.d.ts +30 -0
- package/dist/graph/mailbox-adapter.d.ts.map +1 -0
- package/dist/graph/mailbox-adapter.js +59 -0
- package/dist/graph/mailbox-adapter.js.map +1 -0
- package/dist/graph/mappers/contact-mapper.d.ts +14 -0
- package/dist/graph/mappers/contact-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/contact-mapper.js +20 -0
- package/dist/graph/mappers/contact-mapper.js.map +1 -0
- package/dist/graph/mappers/email-mapper.d.ts +14 -0
- package/dist/graph/mappers/email-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/email-mapper.js +44 -0
- package/dist/graph/mappers/email-mapper.js.map +1 -0
- package/dist/graph/mappers/event-mapper.d.ts +14 -0
- package/dist/graph/mappers/event-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/event-mapper.js +31 -0
- package/dist/graph/mappers/event-mapper.js.map +1 -0
- package/dist/graph/mappers/folder-mapper.d.ts +22 -0
- package/dist/graph/mappers/folder-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/folder-mapper.js +51 -0
- package/dist/graph/mappers/folder-mapper.js.map +1 -0
- package/dist/graph/mappers/index.d.ts +16 -0
- package/dist/graph/mappers/index.d.ts.map +1 -0
- package/dist/graph/mappers/index.js +16 -0
- package/dist/graph/mappers/index.js.map +1 -0
- package/dist/graph/mappers/task-mapper.d.ts +20 -0
- package/dist/graph/mappers/task-mapper.d.ts.map +1 -0
- package/dist/graph/mappers/task-mapper.js +27 -0
- package/dist/graph/mappers/task-mapper.js.map +1 -0
- package/dist/graph/mappers/utils.d.ts +97 -0
- package/dist/graph/mappers/utils.d.ts.map +1 -0
- package/dist/graph/mappers/utils.js +186 -0
- package/dist/graph/mappers/utils.js.map +1 -0
- package/dist/graph/repository.d.ts +1104 -0
- package/dist/graph/repository.d.ts.map +1 -0
- package/dist/graph/repository.js +2999 -0
- package/dist/graph/repository.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6052 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/html-stripper.d.ts +41 -0
- package/dist/parsers/html-stripper.d.ts.map +1 -0
- package/dist/parsers/html-stripper.js +179 -0
- package/dist/parsers/html-stripper.js.map +1 -0
- package/dist/parsers/index.d.ts +12 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +12 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/olk15.d.ts +87 -0
- package/dist/parsers/olk15.d.ts.map +1 -0
- package/dist/parsers/olk15.js +368 -0
- package/dist/parsers/olk15.js.map +1 -0
- package/dist/signature.d.ts +22 -0
- package/dist/signature.d.ts.map +1 -0
- package/dist/signature.js +89 -0
- package/dist/signature.js.map +1 -0
- package/dist/tools/calendar-permissions.d.ts +79 -0
- package/dist/tools/calendar-permissions.d.ts.map +1 -0
- package/dist/tools/calendar-permissions.js +121 -0
- package/dist/tools/calendar-permissions.js.map +1 -0
- package/dist/tools/calendar.d.ts +208 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +247 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/categories.d.ts +94 -0
- package/dist/tools/categories.d.ts.map +1 -0
- package/dist/tools/categories.js +117 -0
- package/dist/tools/categories.js.map +1 -0
- package/dist/tools/checklist-items.d.ts +89 -0
- package/dist/tools/checklist-items.d.ts.map +1 -0
- package/dist/tools/checklist-items.js +140 -0
- package/dist/tools/checklist-items.js.map +1 -0
- package/dist/tools/contacts.d.ts +94 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +134 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/excel.d.ts +96 -0
- package/dist/tools/excel.d.ts.map +1 -0
- package/dist/tools/excel.js +165 -0
- package/dist/tools/excel.js.map +1 -0
- package/dist/tools/focused-overrides.d.ts +70 -0
- package/dist/tools/focused-overrides.d.ts.map +1 -0
- package/dist/tools/focused-overrides.js +117 -0
- package/dist/tools/focused-overrides.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/linked-resources.d.ts +74 -0
- package/dist/tools/linked-resources.d.ts.map +1 -0
- package/dist/tools/linked-resources.js +122 -0
- package/dist/tools/linked-resources.js.map +1 -0
- package/dist/tools/mail-rules.d.ts +98 -0
- package/dist/tools/mail-rules.d.ts.map +1 -0
- package/dist/tools/mail-rules.js +169 -0
- package/dist/tools/mail-rules.js.map +1 -0
- package/dist/tools/mail-send.d.ts +314 -0
- package/dist/tools/mail-send.d.ts.map +1 -0
- package/dist/tools/mail-send.js +555 -0
- package/dist/tools/mail-send.js.map +1 -0
- package/dist/tools/mail.d.ts +127 -0
- package/dist/tools/mail.d.ts.map +1 -0
- package/dist/tools/mail.js +311 -0
- package/dist/tools/mail.js.map +1 -0
- package/dist/tools/mailbox-organization.d.ts +301 -0
- package/dist/tools/mailbox-organization.d.ts.map +1 -0
- package/dist/tools/mailbox-organization.js +541 -0
- package/dist/tools/mailbox-organization.js.map +1 -0
- package/dist/tools/meetings.d.ts +114 -0
- package/dist/tools/meetings.d.ts.map +1 -0
- package/dist/tools/meetings.js +110 -0
- package/dist/tools/meetings.js.map +1 -0
- package/dist/tools/notes.d.ts +74 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +136 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/onedrive.d.ts +194 -0
- package/dist/tools/onedrive.d.ts.map +1 -0
- package/dist/tools/onedrive.js +257 -0
- package/dist/tools/onedrive.js.map +1 -0
- package/dist/tools/people.d.ts +129 -0
- package/dist/tools/people.d.ts.map +1 -0
- package/dist/tools/people.js +195 -0
- package/dist/tools/people.js.map +1 -0
- package/dist/tools/planner-visualization.d.ts +91 -0
- package/dist/tools/planner-visualization.d.ts.map +1 -0
- package/dist/tools/planner-visualization.js +192 -0
- package/dist/tools/planner-visualization.js.map +1 -0
- package/dist/tools/planner.d.ts +288 -0
- package/dist/tools/planner.d.ts.map +1 -0
- package/dist/tools/planner.js +368 -0
- package/dist/tools/planner.js.map +1 -0
- package/dist/tools/scheduling.d.ts +49 -0
- package/dist/tools/scheduling.d.ts.map +1 -0
- package/dist/tools/scheduling.js +115 -0
- package/dist/tools/scheduling.js.map +1 -0
- package/dist/tools/sharepoint.d.ts +115 -0
- package/dist/tools/sharepoint.d.ts.map +1 -0
- package/dist/tools/sharepoint.js +99 -0
- package/dist/tools/sharepoint.js.map +1 -0
- package/dist/tools/task-attachments.d.ts +74 -0
- package/dist/tools/task-attachments.d.ts.map +1 -0
- package/dist/tools/task-attachments.js +122 -0
- package/dist/tools/task-attachments.js.map +1 -0
- package/dist/tools/tasks.d.ts +74 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +126 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +389 -0
- package/dist/tools/teams.d.ts.map +1 -0
- package/dist/tools/teams.js +546 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/types/calendar.d.ts +60 -0
- package/dist/types/calendar.d.ts.map +1 -0
- package/dist/types/calendar.js +15 -0
- package/dist/types/calendar.js.map +1 -0
- package/dist/types/contacts.d.ts +96 -0
- package/dist/types/contacts.d.ts.map +1 -0
- package/dist/types/contacts.js +41 -0
- package/dist/types/contacts.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mail.d.ts +108 -0
- package/dist/types/mail.d.ts.map +1 -0
- package/dist/types/mail.js +40 -0
- package/dist/types/mail.js.map +1 -0
- package/dist/types/notes.d.ts +26 -0
- package/dist/types/notes.d.ts.map +1 -0
- package/dist/types/notes.js +6 -0
- package/dist/types/notes.js.map +1 -0
- package/dist/types/tasks.d.ts +31 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +6 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/utils/dates.d.ts +66 -0
- package/dist/utils/dates.d.ts.map +1 -0
- package/dist/utils/dates.js +94 -0
- package/dist/utils/dates.js.map +1 -0
- package/dist/utils/errors.d.ts +218 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +306 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/visualization/html.d.ts +26 -0
- package/dist/visualization/html.d.ts.map +1 -0
- package/dist/visualization/html.js +306 -0
- package/dist/visualization/html.js.map +1 -0
- package/dist/visualization/markdown.d.ts +25 -0
- package/dist/visualization/markdown.d.ts.map +1 -0
- package/dist/visualization/markdown.js +186 -0
- package/dist/visualization/markdown.js.map +1 -0
- package/dist/visualization/mermaid.d.ts +25 -0
- package/dist/visualization/mermaid.d.ts.map +1 -0
- package/dist/visualization/mermaid.js +158 -0
- package/dist/visualization/mermaid.js.map +1 -0
- package/dist/visualization/svg.d.ts +25 -0
- package/dist/visualization/svg.d.ts.map +1 -0
- package/dist/visualization/svg.js +282 -0
- package/dist/visualization/svg.js.map +1 -0
- package/dist/visualization/types.d.ts +43 -0
- package/dist/visualization/types.d.ts.map +1 -0
- package/dist/visualization/types.js +34 -0
- package/dist/visualization/types.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,1483 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 JBC Tech Solutions, LLC
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* AppleScript template strings for Outlook operations.
|
|
7
|
+
*
|
|
8
|
+
* All scripts output data in a delimiter-based format for reliable parsing:
|
|
9
|
+
* - Records are separated by {{RECORD}}
|
|
10
|
+
* - Fields are separated by {{FIELD}}
|
|
11
|
+
* - Field names and values are separated by {{=}}
|
|
12
|
+
*
|
|
13
|
+
* Example output: {{RECORD}}id{{=}}1{{FIELD}}name{{=}}Inbox{{FIELD}}unread{{=}}5{{RECORD}}...
|
|
14
|
+
*/
|
|
15
|
+
import { escapeForAppleScript } from './executor.js';
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Delimiters
|
|
18
|
+
// =============================================================================
|
|
19
|
+
export const DELIMITERS = {
|
|
20
|
+
RECORD: '{{RECORD}}',
|
|
21
|
+
FIELD: '{{FIELD}}',
|
|
22
|
+
EQUALS: '{{=}}',
|
|
23
|
+
NULL: '{{NULL}}',
|
|
24
|
+
};
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// Mail Scripts
|
|
27
|
+
// =============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Lists all mail folders with their properties.
|
|
30
|
+
*/
|
|
31
|
+
export const LIST_MAIL_FOLDERS = `
|
|
32
|
+
tell application "Microsoft Outlook"
|
|
33
|
+
set output to ""
|
|
34
|
+
set allFolders to mail folders
|
|
35
|
+
repeat with f in allFolders
|
|
36
|
+
try
|
|
37
|
+
set fId to id of f
|
|
38
|
+
set fName to name of f
|
|
39
|
+
set uCount to unread count of f
|
|
40
|
+
set output to output & "{{RECORD}}id{{=}}" & fId & "{{FIELD}}name{{=}}" & fName & "{{FIELD}}unreadCount{{=}}" & uCount
|
|
41
|
+
end try
|
|
42
|
+
end repeat
|
|
43
|
+
return output
|
|
44
|
+
end tell
|
|
45
|
+
`;
|
|
46
|
+
/**
|
|
47
|
+
* Gets messages from a specific folder.
|
|
48
|
+
*/
|
|
49
|
+
export function listMessages(folderId, limit, offset, unreadOnly) {
|
|
50
|
+
const unreadFilter = unreadOnly ? ' whose is read is false' : '';
|
|
51
|
+
const totalToFetch = limit + offset;
|
|
52
|
+
return `
|
|
53
|
+
tell application "Microsoft Outlook"
|
|
54
|
+
set output to ""
|
|
55
|
+
set targetFolder to mail folder id ${folderId}
|
|
56
|
+
set allMsgs to (messages of targetFolder${unreadFilter})
|
|
57
|
+
set msgCount to count of allMsgs
|
|
58
|
+
set startIdx to ${offset + 1}
|
|
59
|
+
set endIdx to ${totalToFetch}
|
|
60
|
+
if endIdx > msgCount then set endIdx to msgCount
|
|
61
|
+
if startIdx > msgCount then return ""
|
|
62
|
+
|
|
63
|
+
repeat with i from startIdx to endIdx
|
|
64
|
+
try
|
|
65
|
+
set m to item i of allMsgs
|
|
66
|
+
set mId to id of m
|
|
67
|
+
set mSubject to subject of m
|
|
68
|
+
set mSender to ""
|
|
69
|
+
try
|
|
70
|
+
set mSender to address of sender of m
|
|
71
|
+
end try
|
|
72
|
+
set mSenderName to ""
|
|
73
|
+
try
|
|
74
|
+
set mSenderName to name of sender of m
|
|
75
|
+
end try
|
|
76
|
+
set mDate to ""
|
|
77
|
+
try
|
|
78
|
+
set mDate to time received of m as «class isot» as string
|
|
79
|
+
end try
|
|
80
|
+
set mRead to is read of m
|
|
81
|
+
set mPriority to "normal"
|
|
82
|
+
try
|
|
83
|
+
set p to priority of m
|
|
84
|
+
if p is priority high then
|
|
85
|
+
set mPriority to "high"
|
|
86
|
+
else if p is priority low then
|
|
87
|
+
set mPriority to "low"
|
|
88
|
+
end if
|
|
89
|
+
end try
|
|
90
|
+
set mPreview to ""
|
|
91
|
+
try
|
|
92
|
+
set mPreview to text 1 thru 200 of plain text content of m
|
|
93
|
+
on error
|
|
94
|
+
try
|
|
95
|
+
set mPreview to plain text content of m
|
|
96
|
+
end try
|
|
97
|
+
end try
|
|
98
|
+
|
|
99
|
+
set output to output & "{{RECORD}}id{{=}}" & mId & "{{FIELD}}subject{{=}}" & mSubject & "{{FIELD}}senderEmail{{=}}" & mSender & "{{FIELD}}senderName{{=}}" & mSenderName & "{{FIELD}}dateReceived{{=}}" & mDate & "{{FIELD}}isRead{{=}}" & mRead & "{{FIELD}}priority{{=}}" & mPriority & "{{FIELD}}preview{{=}}" & mPreview
|
|
100
|
+
end try
|
|
101
|
+
end repeat
|
|
102
|
+
return output
|
|
103
|
+
end tell
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Maximum number of messages to scan for sender-address matches.
|
|
108
|
+
* Keeps execution within the 30s AppleScript timeout.
|
|
109
|
+
*/
|
|
110
|
+
const SENDER_SCAN_LIMIT = 500;
|
|
111
|
+
/**
|
|
112
|
+
* Searches messages by query.
|
|
113
|
+
*
|
|
114
|
+
* Uses a two-phase approach to avoid crashes on emails with unresolvable sender
|
|
115
|
+
* addresses (the AppleScript WHERE clause cannot use try/catch):
|
|
116
|
+
* Phase 1 — subject matches via a safe WHERE clause
|
|
117
|
+
* Phase 2 — sender matches via a loop with try/catch protection
|
|
118
|
+
*/
|
|
119
|
+
export function searchMessages(query, folderId, limit) {
|
|
120
|
+
const escapedQuery = escapeForAppleScript(query);
|
|
121
|
+
const folderClause = folderId != null ? `of mail folder id ${folderId}` : '';
|
|
122
|
+
return `
|
|
123
|
+
tell application "Microsoft Outlook"
|
|
124
|
+
set output to ""
|
|
125
|
+
set matchedIds to {}
|
|
126
|
+
set resultCount to 0
|
|
127
|
+
set maxResults to ${limit}
|
|
128
|
+
|
|
129
|
+
-- Phase 1: Subject matches (safe WHERE clause)
|
|
130
|
+
set subjectMatches to (messages ${folderClause} whose subject contains "${escapedQuery}")
|
|
131
|
+
repeat with m in subjectMatches
|
|
132
|
+
if resultCount ≥ maxResults then exit repeat
|
|
133
|
+
try
|
|
134
|
+
set mId to id of m
|
|
135
|
+
set end of matchedIds to mId
|
|
136
|
+
set mSubject to subject of m
|
|
137
|
+
set mSender to ""
|
|
138
|
+
try
|
|
139
|
+
set mSender to address of sender of m
|
|
140
|
+
end try
|
|
141
|
+
set mSenderName to ""
|
|
142
|
+
try
|
|
143
|
+
set mSenderName to name of sender of m
|
|
144
|
+
end try
|
|
145
|
+
set mDate to ""
|
|
146
|
+
try
|
|
147
|
+
set mDate to time received of m as «class isot» as string
|
|
148
|
+
end try
|
|
149
|
+
set mRead to is read of m
|
|
150
|
+
set mPreview to ""
|
|
151
|
+
try
|
|
152
|
+
set mPreview to text 1 thru 200 of plain text content of m
|
|
153
|
+
on error
|
|
154
|
+
try
|
|
155
|
+
set mPreview to plain text content of m
|
|
156
|
+
end try
|
|
157
|
+
end try
|
|
158
|
+
set output to output & "{{RECORD}}id{{=}}" & mId & "{{FIELD}}subject{{=}}" & mSubject & "{{FIELD}}senderEmail{{=}}" & mSender & "{{FIELD}}senderName{{=}}" & mSenderName & "{{FIELD}}dateReceived{{=}}" & mDate & "{{FIELD}}isRead{{=}}" & mRead & "{{FIELD}}preview{{=}}" & mPreview
|
|
159
|
+
set resultCount to resultCount + 1
|
|
160
|
+
end try
|
|
161
|
+
end repeat
|
|
162
|
+
|
|
163
|
+
-- Phase 2: Sender matches (loop with try/catch for safety)
|
|
164
|
+
if resultCount < maxResults then
|
|
165
|
+
set allMsgs to messages ${folderClause}
|
|
166
|
+
set scanLimit to count of allMsgs
|
|
167
|
+
if scanLimit > ${SENDER_SCAN_LIMIT} then set scanLimit to ${SENDER_SCAN_LIMIT}
|
|
168
|
+
repeat with i from 1 to scanLimit
|
|
169
|
+
if resultCount ≥ maxResults then exit repeat
|
|
170
|
+
try
|
|
171
|
+
set m to item i of allMsgs
|
|
172
|
+
set mId to id of m
|
|
173
|
+
if matchedIds does not contain mId then
|
|
174
|
+
set mSender to ""
|
|
175
|
+
try
|
|
176
|
+
set mSender to address of sender of m
|
|
177
|
+
end try
|
|
178
|
+
if mSender contains "${escapedQuery}" then
|
|
179
|
+
set end of matchedIds to mId
|
|
180
|
+
set mSubject to subject of m
|
|
181
|
+
set mSenderName to ""
|
|
182
|
+
try
|
|
183
|
+
set mSenderName to name of sender of m
|
|
184
|
+
end try
|
|
185
|
+
set mDate to ""
|
|
186
|
+
try
|
|
187
|
+
set mDate to time received of m as «class isot» as string
|
|
188
|
+
end try
|
|
189
|
+
set mRead to is read of m
|
|
190
|
+
set mPreview to ""
|
|
191
|
+
try
|
|
192
|
+
set mPreview to text 1 thru 200 of plain text content of m
|
|
193
|
+
on error
|
|
194
|
+
try
|
|
195
|
+
set mPreview to plain text content of m
|
|
196
|
+
end try
|
|
197
|
+
end try
|
|
198
|
+
set output to output & "{{RECORD}}id{{=}}" & mId & "{{FIELD}}subject{{=}}" & mSubject & "{{FIELD}}senderEmail{{=}}" & mSender & "{{FIELD}}senderName{{=}}" & mSenderName & "{{FIELD}}dateReceived{{=}}" & mDate & "{{FIELD}}isRead{{=}}" & mRead & "{{FIELD}}preview{{=}}" & mPreview
|
|
199
|
+
set resultCount to resultCount + 1
|
|
200
|
+
end if
|
|
201
|
+
end if
|
|
202
|
+
end try
|
|
203
|
+
end repeat
|
|
204
|
+
end if
|
|
205
|
+
|
|
206
|
+
return output
|
|
207
|
+
end tell
|
|
208
|
+
`;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Gets a single message by ID with full content.
|
|
212
|
+
*/
|
|
213
|
+
export function getMessage(messageId) {
|
|
214
|
+
return `
|
|
215
|
+
tell application "Microsoft Outlook"
|
|
216
|
+
set m to message id ${messageId}
|
|
217
|
+
set mId to id of m
|
|
218
|
+
set mSubject to subject of m
|
|
219
|
+
set mSender to ""
|
|
220
|
+
try
|
|
221
|
+
set mSender to address of sender of m
|
|
222
|
+
end try
|
|
223
|
+
set mSenderName to ""
|
|
224
|
+
try
|
|
225
|
+
set mSenderName to name of sender of m
|
|
226
|
+
end try
|
|
227
|
+
set mDateReceived to ""
|
|
228
|
+
try
|
|
229
|
+
set mDateReceived to time received of m as «class isot» as string
|
|
230
|
+
end try
|
|
231
|
+
set mDateSent to ""
|
|
232
|
+
try
|
|
233
|
+
set mDateSent to time sent of m as «class isot» as string
|
|
234
|
+
end try
|
|
235
|
+
set mRead to is read of m
|
|
236
|
+
set mPriority to "normal"
|
|
237
|
+
try
|
|
238
|
+
set p to priority of m
|
|
239
|
+
if p is priority high then
|
|
240
|
+
set mPriority to "high"
|
|
241
|
+
else if p is priority low then
|
|
242
|
+
set mPriority to "low"
|
|
243
|
+
end if
|
|
244
|
+
end try
|
|
245
|
+
set mHtml to ""
|
|
246
|
+
try
|
|
247
|
+
set mHtml to content of m
|
|
248
|
+
end try
|
|
249
|
+
set mPlain to ""
|
|
250
|
+
try
|
|
251
|
+
set mPlain to plain text content of m
|
|
252
|
+
end try
|
|
253
|
+
set mHasHtml to has html of m
|
|
254
|
+
set mFolderId to ""
|
|
255
|
+
try
|
|
256
|
+
set mFolderId to id of folder of m
|
|
257
|
+
end try
|
|
258
|
+
|
|
259
|
+
-- Get recipients
|
|
260
|
+
set toList to ""
|
|
261
|
+
try
|
|
262
|
+
repeat with r in to recipients of m
|
|
263
|
+
set toList to toList & (address of r) & ","
|
|
264
|
+
end repeat
|
|
265
|
+
end try
|
|
266
|
+
set ccList to ""
|
|
267
|
+
try
|
|
268
|
+
repeat with r in cc recipients of m
|
|
269
|
+
set ccList to ccList & (address of r) & ","
|
|
270
|
+
end repeat
|
|
271
|
+
end try
|
|
272
|
+
|
|
273
|
+
-- Get attachments
|
|
274
|
+
set attachList to ""
|
|
275
|
+
set attachDetailList to ""
|
|
276
|
+
try
|
|
277
|
+
set idx to 1
|
|
278
|
+
repeat with a in attachments of m
|
|
279
|
+
set aName to name of a
|
|
280
|
+
set attachList to attachList & aName & ","
|
|
281
|
+
set aSize to 0
|
|
282
|
+
try
|
|
283
|
+
set aSize to file size of a
|
|
284
|
+
end try
|
|
285
|
+
set aType to ""
|
|
286
|
+
try
|
|
287
|
+
set aType to content type of a
|
|
288
|
+
end try
|
|
289
|
+
set attachDetailList to attachDetailList & idx & "|" & aName & "|" & aSize & "|" & aType & ","
|
|
290
|
+
set idx to idx + 1
|
|
291
|
+
end repeat
|
|
292
|
+
end try
|
|
293
|
+
|
|
294
|
+
return "{{RECORD}}id{{=}}" & mId & "{{FIELD}}subject{{=}}" & mSubject & "{{FIELD}}senderEmail{{=}}" & mSender & "{{FIELD}}senderName{{=}}" & mSenderName & "{{FIELD}}dateReceived{{=}}" & mDateReceived & "{{FIELD}}dateSent{{=}}" & mDateSent & "{{FIELD}}isRead{{=}}" & mRead & "{{FIELD}}priority{{=}}" & mPriority & "{{FIELD}}htmlContent{{=}}" & mHtml & "{{FIELD}}plainContent{{=}}" & mPlain & "{{FIELD}}hasHtml{{=}}" & mHasHtml & "{{FIELD}}folderId{{=}}" & mFolderId & "{{FIELD}}toRecipients{{=}}" & toList & "{{FIELD}}ccRecipients{{=}}" & ccList & "{{FIELD}}attachments{{=}}" & attachList & "{{FIELD}}attachmentDetails{{=}}" & attachDetailList
|
|
295
|
+
end tell
|
|
296
|
+
`;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Gets unread count for a folder.
|
|
300
|
+
*/
|
|
301
|
+
export function getUnreadCount(folderId) {
|
|
302
|
+
return `
|
|
303
|
+
tell application "Microsoft Outlook"
|
|
304
|
+
set f to mail folder id ${folderId}
|
|
305
|
+
return unread count of f
|
|
306
|
+
end tell
|
|
307
|
+
`;
|
|
308
|
+
}
|
|
309
|
+
// =============================================================================
|
|
310
|
+
// Attachment Scripts
|
|
311
|
+
// =============================================================================
|
|
312
|
+
/**
|
|
313
|
+
* Lists attachment metadata for a message.
|
|
314
|
+
*/
|
|
315
|
+
export function listAttachments(messageId) {
|
|
316
|
+
return `
|
|
317
|
+
tell application "Microsoft Outlook"
|
|
318
|
+
set m to message id ${messageId}
|
|
319
|
+
set output to ""
|
|
320
|
+
set attachList to attachments of m
|
|
321
|
+
set idx to 1
|
|
322
|
+
repeat with a in attachList
|
|
323
|
+
try
|
|
324
|
+
set aName to name of a
|
|
325
|
+
set aSize to 0
|
|
326
|
+
try
|
|
327
|
+
set aSize to file size of a
|
|
328
|
+
end try
|
|
329
|
+
set aType to ""
|
|
330
|
+
try
|
|
331
|
+
set aType to content type of a
|
|
332
|
+
end try
|
|
333
|
+
set output to output & "{{RECORD}}index{{=}}" & idx & "{{FIELD}}name{{=}}" & aName & "{{FIELD}}fileSize{{=}}" & aSize & "{{FIELD}}contentType{{=}}" & aType
|
|
334
|
+
end try
|
|
335
|
+
set idx to idx + 1
|
|
336
|
+
end repeat
|
|
337
|
+
return output
|
|
338
|
+
end tell
|
|
339
|
+
`;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Saves an attachment from a message to a file path.
|
|
343
|
+
* Uses 1-based attachment index.
|
|
344
|
+
*/
|
|
345
|
+
export function saveAttachment(messageId, attachmentIndex, savePath) {
|
|
346
|
+
const escapedPath = escapeForAppleScript(savePath);
|
|
347
|
+
return `
|
|
348
|
+
tell application "Microsoft Outlook"
|
|
349
|
+
try
|
|
350
|
+
set m to message id ${messageId}
|
|
351
|
+
set attachList to attachments of m
|
|
352
|
+
set attachCount to count of attachList
|
|
353
|
+
if ${attachmentIndex} > attachCount then
|
|
354
|
+
return "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}Attachment index ${attachmentIndex} out of range (message has " & attachCount & " attachments)"
|
|
355
|
+
end if
|
|
356
|
+
set a to item ${attachmentIndex} of attachList
|
|
357
|
+
set aName to name of a
|
|
358
|
+
set aSize to 0
|
|
359
|
+
try
|
|
360
|
+
set aSize to file size of a
|
|
361
|
+
end try
|
|
362
|
+
save a in POSIX file "${escapedPath}"
|
|
363
|
+
return "{{RECORD}}success{{=}}true{{FIELD}}name{{=}}" & aName & "{{FIELD}}savedTo{{=}}${escapedPath}" & "{{FIELD}}fileSize{{=}}" & aSize
|
|
364
|
+
on error errMsg
|
|
365
|
+
return "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}" & errMsg
|
|
366
|
+
end try
|
|
367
|
+
end tell
|
|
368
|
+
`;
|
|
369
|
+
}
|
|
370
|
+
// =============================================================================
|
|
371
|
+
// Calendar Scripts
|
|
372
|
+
// =============================================================================
|
|
373
|
+
/**
|
|
374
|
+
* Lists all calendars.
|
|
375
|
+
*/
|
|
376
|
+
export const LIST_CALENDARS = `
|
|
377
|
+
tell application "Microsoft Outlook"
|
|
378
|
+
set output to ""
|
|
379
|
+
set allCalendars to calendars
|
|
380
|
+
repeat with c in allCalendars
|
|
381
|
+
try
|
|
382
|
+
set cId to id of c
|
|
383
|
+
set cName to name of c
|
|
384
|
+
set output to output & "{{RECORD}}id{{=}}" & cId & "{{FIELD}}name{{=}}" & cName
|
|
385
|
+
end try
|
|
386
|
+
end repeat
|
|
387
|
+
return output
|
|
388
|
+
end tell
|
|
389
|
+
`;
|
|
390
|
+
/**
|
|
391
|
+
* Lists events from a calendar within a date range.
|
|
392
|
+
*/
|
|
393
|
+
export function listEvents(calendarId, startDate, endDate, limit) {
|
|
394
|
+
const calendarClause = calendarId != null ? `of calendar id ${calendarId}` : '';
|
|
395
|
+
return `
|
|
396
|
+
tell application "Microsoft Outlook"
|
|
397
|
+
set output to ""
|
|
398
|
+
set allEvents to calendar events ${calendarClause}
|
|
399
|
+
set eventCount to count of allEvents
|
|
400
|
+
set maxEvents to ${limit}
|
|
401
|
+
if eventCount < maxEvents then set maxEvents to eventCount
|
|
402
|
+
|
|
403
|
+
repeat with i from 1 to maxEvents
|
|
404
|
+
try
|
|
405
|
+
set e to item i of allEvents
|
|
406
|
+
set eId to id of e
|
|
407
|
+
set eSubject to subject of e
|
|
408
|
+
set eStart to ""
|
|
409
|
+
try
|
|
410
|
+
set eStart to start time of e as «class isot» as string
|
|
411
|
+
end try
|
|
412
|
+
set eEnd to ""
|
|
413
|
+
try
|
|
414
|
+
set eEnd to end time of e as «class isot» as string
|
|
415
|
+
end try
|
|
416
|
+
set eLocation to ""
|
|
417
|
+
try
|
|
418
|
+
set eLocation to location of e
|
|
419
|
+
end try
|
|
420
|
+
set eAllDay to all day flag of e
|
|
421
|
+
set eRecurring to is recurring of e
|
|
422
|
+
|
|
423
|
+
set output to output & "{{RECORD}}id{{=}}" & eId & "{{FIELD}}subject{{=}}" & eSubject & "{{FIELD}}startTime{{=}}" & eStart & "{{FIELD}}endTime{{=}}" & eEnd & "{{FIELD}}location{{=}}" & eLocation & "{{FIELD}}isAllDay{{=}}" & eAllDay & "{{FIELD}}isRecurring{{=}}" & eRecurring
|
|
424
|
+
end try
|
|
425
|
+
end repeat
|
|
426
|
+
return output
|
|
427
|
+
end tell
|
|
428
|
+
`;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Gets a single event by ID.
|
|
432
|
+
*/
|
|
433
|
+
export function getEvent(eventId) {
|
|
434
|
+
return `
|
|
435
|
+
tell application "Microsoft Outlook"
|
|
436
|
+
set e to calendar event id ${eventId}
|
|
437
|
+
set eId to id of e
|
|
438
|
+
set eSubject to subject of e
|
|
439
|
+
set eStart to ""
|
|
440
|
+
try
|
|
441
|
+
set eStart to start time of e as «class isot» as string
|
|
442
|
+
end try
|
|
443
|
+
set eEnd to ""
|
|
444
|
+
try
|
|
445
|
+
set eEnd to end time of e as «class isot» as string
|
|
446
|
+
end try
|
|
447
|
+
set eLocation to ""
|
|
448
|
+
try
|
|
449
|
+
set eLocation to location of e
|
|
450
|
+
end try
|
|
451
|
+
set eContent to ""
|
|
452
|
+
try
|
|
453
|
+
set eContent to content of e
|
|
454
|
+
end try
|
|
455
|
+
set ePlain to ""
|
|
456
|
+
try
|
|
457
|
+
set ePlain to plain text content of e
|
|
458
|
+
end try
|
|
459
|
+
set eAllDay to all day flag of e
|
|
460
|
+
set eRecurring to is recurring of e
|
|
461
|
+
set eOrganizer to ""
|
|
462
|
+
try
|
|
463
|
+
set eOrganizer to organizer of e
|
|
464
|
+
end try
|
|
465
|
+
set eCalId to ""
|
|
466
|
+
try
|
|
467
|
+
set eCalId to id of calendar of e
|
|
468
|
+
end try
|
|
469
|
+
|
|
470
|
+
-- Get attendees
|
|
471
|
+
set attendeeList to ""
|
|
472
|
+
try
|
|
473
|
+
repeat with a in attendees of e
|
|
474
|
+
set aEmail to email address of a
|
|
475
|
+
set aName to name of a
|
|
476
|
+
set attendeeList to attendeeList & aEmail & "|" & aName & ","
|
|
477
|
+
end repeat
|
|
478
|
+
end try
|
|
479
|
+
|
|
480
|
+
return "{{RECORD}}id{{=}}" & eId & "{{FIELD}}subject{{=}}" & eSubject & "{{FIELD}}startTime{{=}}" & eStart & "{{FIELD}}endTime{{=}}" & eEnd & "{{FIELD}}location{{=}}" & eLocation & "{{FIELD}}htmlContent{{=}}" & eContent & "{{FIELD}}plainContent{{=}}" & ePlain & "{{FIELD}}isAllDay{{=}}" & eAllDay & "{{FIELD}}isRecurring{{=}}" & eRecurring & "{{FIELD}}organizer{{=}}" & eOrganizer & "{{FIELD}}calendarId{{=}}" & eCalId & "{{FIELD}}attendees{{=}}" & attendeeList
|
|
481
|
+
end tell
|
|
482
|
+
`;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Searches events by query and/or date range.
|
|
486
|
+
* At least one of query or date range must be provided.
|
|
487
|
+
*/
|
|
488
|
+
export function searchEvents(query, startDate, endDate, limit) {
|
|
489
|
+
// Build date variable declarations
|
|
490
|
+
let dateSetup = '';
|
|
491
|
+
if (startDate != null) {
|
|
492
|
+
dateSetup += `
|
|
493
|
+
set theStartDate to current date
|
|
494
|
+
set day of theStartDate to 1
|
|
495
|
+
set year of theStartDate to ${startDate.year}
|
|
496
|
+
set month of theStartDate to ${startDate.month}
|
|
497
|
+
set day of theStartDate to ${startDate.day}
|
|
498
|
+
set hours of theStartDate to ${startDate.hours}
|
|
499
|
+
set minutes of theStartDate to ${startDate.minutes}
|
|
500
|
+
set seconds of theStartDate to 0
|
|
501
|
+
`;
|
|
502
|
+
}
|
|
503
|
+
if (endDate != null) {
|
|
504
|
+
dateSetup += `
|
|
505
|
+
set theEndDate to current date
|
|
506
|
+
set day of theEndDate to 1
|
|
507
|
+
set year of theEndDate to ${endDate.year}
|
|
508
|
+
set month of theEndDate to ${endDate.month}
|
|
509
|
+
set day of theEndDate to ${endDate.day}
|
|
510
|
+
set hours of theEndDate to ${endDate.hours}
|
|
511
|
+
set minutes of theEndDate to ${endDate.minutes}
|
|
512
|
+
set seconds of theEndDate to 0
|
|
513
|
+
`;
|
|
514
|
+
}
|
|
515
|
+
// Build whose clause conditions
|
|
516
|
+
const conditions = [];
|
|
517
|
+
if (query != null) {
|
|
518
|
+
const escapedQuery = escapeForAppleScript(query);
|
|
519
|
+
conditions.push(`subject contains "${escapedQuery}"`);
|
|
520
|
+
}
|
|
521
|
+
if (startDate != null) {
|
|
522
|
+
conditions.push('start time ≥ theStartDate');
|
|
523
|
+
}
|
|
524
|
+
if (endDate != null) {
|
|
525
|
+
conditions.push('end time ≤ theEndDate');
|
|
526
|
+
}
|
|
527
|
+
const whoseClause = conditions.length > 0
|
|
528
|
+
? ` whose ${conditions.join(' and ')}`
|
|
529
|
+
: '';
|
|
530
|
+
return `
|
|
531
|
+
tell application "Microsoft Outlook"
|
|
532
|
+
set output to ""
|
|
533
|
+
${dateSetup}
|
|
534
|
+
set searchResults to (calendar events${whoseClause})
|
|
535
|
+
set resultCount to count of searchResults
|
|
536
|
+
set maxResults to ${limit}
|
|
537
|
+
if resultCount < maxResults then set maxResults to resultCount
|
|
538
|
+
|
|
539
|
+
repeat with i from 1 to maxResults
|
|
540
|
+
try
|
|
541
|
+
set e to item i of searchResults
|
|
542
|
+
set eId to id of e
|
|
543
|
+
set eSubject to subject of e
|
|
544
|
+
set eStart to ""
|
|
545
|
+
try
|
|
546
|
+
set eStart to start time of e as «class isot» as string
|
|
547
|
+
end try
|
|
548
|
+
set eEnd to ""
|
|
549
|
+
try
|
|
550
|
+
set eEnd to end time of e as «class isot» as string
|
|
551
|
+
end try
|
|
552
|
+
set eLocation to ""
|
|
553
|
+
try
|
|
554
|
+
set eLocation to location of e
|
|
555
|
+
end try
|
|
556
|
+
|
|
557
|
+
set output to output & "{{RECORD}}id{{=}}" & eId & "{{FIELD}}subject{{=}}" & eSubject & "{{FIELD}}startTime{{=}}" & eStart & "{{FIELD}}endTime{{=}}" & eEnd & "{{FIELD}}location{{=}}" & eLocation
|
|
558
|
+
end try
|
|
559
|
+
end repeat
|
|
560
|
+
return output
|
|
561
|
+
end tell
|
|
562
|
+
`;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Builds AppleScript to set recurrence on a newly created event.
|
|
566
|
+
* Assumes `newEvent` variable is already in scope from createEvent.
|
|
567
|
+
*/
|
|
568
|
+
function buildRecurrenceScript(params) {
|
|
569
|
+
const isOrdinalMonthly = params.frequency === 'monthly' && params.weekOfMonth != null;
|
|
570
|
+
const frequencyMap = {
|
|
571
|
+
daily: 'daily recurrence',
|
|
572
|
+
weekly: 'weekly recurrence',
|
|
573
|
+
monthly: isOrdinalMonthly ? 'month nth recurrence' : 'monthly recurrence',
|
|
574
|
+
yearly: 'yearly recurrence',
|
|
575
|
+
};
|
|
576
|
+
const recurrenceType = frequencyMap[params.frequency];
|
|
577
|
+
const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
578
|
+
let script = `
|
|
579
|
+
set is recurring of newEvent to true
|
|
580
|
+
set theRecurrence to recurrence of newEvent
|
|
581
|
+
set recurrence type of theRecurrence to ${recurrenceType}
|
|
582
|
+
set occurrence interval of theRecurrence to ${params.interval}`;
|
|
583
|
+
// Weekly: days of week mask
|
|
584
|
+
if (params.frequency === 'weekly' && params.daysOfWeek != null) {
|
|
585
|
+
const daysList = params.daysOfWeek.map(capitalize).join(', ');
|
|
586
|
+
script += `\n set day of week mask of theRecurrence to {${daysList}}`;
|
|
587
|
+
}
|
|
588
|
+
// Monthly by date
|
|
589
|
+
if (params.frequency === 'monthly' && params.dayOfMonth != null && params.weekOfMonth == null) {
|
|
590
|
+
script += `\n set day of month of theRecurrence to ${params.dayOfMonth}`;
|
|
591
|
+
}
|
|
592
|
+
// Monthly ordinal (e.g., 3rd Thursday)
|
|
593
|
+
if (params.frequency === 'monthly' && params.weekOfMonth != null && params.dayOfWeekMonthly != null) {
|
|
594
|
+
const instanceMap = { first: 1, second: 2, third: 3, fourth: 4, last: 5 };
|
|
595
|
+
const instance = instanceMap[params.weekOfMonth] ?? 1;
|
|
596
|
+
script += `\n set day of week mask of theRecurrence to {${capitalize(params.dayOfWeekMonthly)}}`;
|
|
597
|
+
script += `\n set instance of theRecurrence to ${instance}`;
|
|
598
|
+
}
|
|
599
|
+
// End after count
|
|
600
|
+
if (params.endAfterCount != null) {
|
|
601
|
+
script += `\n set occurrences of theRecurrence to ${params.endAfterCount}`;
|
|
602
|
+
}
|
|
603
|
+
// End by date (component-based for locale safety)
|
|
604
|
+
if (params.endDate != null) {
|
|
605
|
+
script += `
|
|
606
|
+
set theEndRecurrenceDate to current date
|
|
607
|
+
set day of theEndRecurrenceDate to 1
|
|
608
|
+
set year of theEndRecurrenceDate to ${params.endDate.year}
|
|
609
|
+
set month of theEndRecurrenceDate to ${params.endDate.month}
|
|
610
|
+
set day of theEndRecurrenceDate to ${params.endDate.day}
|
|
611
|
+
set hours of theEndRecurrenceDate to ${params.endDate.hours}
|
|
612
|
+
set minutes of theEndRecurrenceDate to ${params.endDate.minutes}
|
|
613
|
+
set seconds of theEndRecurrenceDate to 0
|
|
614
|
+
set pattern end date of theRecurrence to theEndRecurrenceDate`;
|
|
615
|
+
}
|
|
616
|
+
return script;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Responds to an event invitation (RSVP).
|
|
620
|
+
*/
|
|
621
|
+
export function respondToEvent(params) {
|
|
622
|
+
const { eventId, response, comment } = params;
|
|
623
|
+
// Map response to AppleScript status value
|
|
624
|
+
const statusMap = {
|
|
625
|
+
accept: 'accept',
|
|
626
|
+
decline: 'decline',
|
|
627
|
+
tentative: 'tentative accept',
|
|
628
|
+
};
|
|
629
|
+
const status = statusMap[response];
|
|
630
|
+
// Escape comment if provided
|
|
631
|
+
const commentLine = comment != null
|
|
632
|
+
? `set comment of myEvent to "${escapeForAppleScript(comment)}"`
|
|
633
|
+
: '';
|
|
634
|
+
return `
|
|
635
|
+
tell application "Microsoft Outlook"
|
|
636
|
+
try
|
|
637
|
+
set myEvent to calendar event id ${eventId}
|
|
638
|
+
set response status of myEvent to ${status}
|
|
639
|
+
${commentLine}
|
|
640
|
+
|
|
641
|
+
-- Return success
|
|
642
|
+
set output to "{{RECORD}}success{{=}}true{{FIELD}}eventId{{=}}" & ${eventId}
|
|
643
|
+
return output
|
|
644
|
+
on error errMsg
|
|
645
|
+
-- Return failure
|
|
646
|
+
set output to "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}" & errMsg
|
|
647
|
+
return output
|
|
648
|
+
end try
|
|
649
|
+
end tell
|
|
650
|
+
`;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Deletes an event. For recurring events, can delete single instance or entire series.
|
|
654
|
+
*/
|
|
655
|
+
export function deleteEvent(params) {
|
|
656
|
+
const { eventId, applyTo } = params;
|
|
657
|
+
const comment = applyTo === 'all_in_series'
|
|
658
|
+
? '-- Deleting entire series'
|
|
659
|
+
: '-- Deleting single instance';
|
|
660
|
+
return `
|
|
661
|
+
tell application "Microsoft Outlook"
|
|
662
|
+
try
|
|
663
|
+
${comment}
|
|
664
|
+
set myEvent to calendar event id ${eventId}
|
|
665
|
+
delete myEvent
|
|
666
|
+
|
|
667
|
+
-- Return success
|
|
668
|
+
set output to "{{RECORD}}success{{=}}true{{FIELD}}eventId{{=}}" & ${eventId}
|
|
669
|
+
return output
|
|
670
|
+
on error errMsg
|
|
671
|
+
-- Return failure
|
|
672
|
+
set output to "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}" & errMsg
|
|
673
|
+
return output
|
|
674
|
+
end try
|
|
675
|
+
end tell
|
|
676
|
+
`;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Converts an ISO 8601 date string into individual UTC date components.
|
|
680
|
+
*/
|
|
681
|
+
function isoToDateComponents(isoString) {
|
|
682
|
+
const date = new Date(isoString);
|
|
683
|
+
return {
|
|
684
|
+
year: date.getUTCFullYear(),
|
|
685
|
+
month: date.getUTCMonth() + 1,
|
|
686
|
+
day: date.getUTCDate(),
|
|
687
|
+
hours: date.getUTCHours(),
|
|
688
|
+
minutes: date.getUTCMinutes(),
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Updates an event. For recurring events, can update single instance or entire series.
|
|
693
|
+
* All update fields are optional - only specified fields will be updated.
|
|
694
|
+
*/
|
|
695
|
+
export function updateEvent(params) {
|
|
696
|
+
const { eventId, applyTo, updates } = params;
|
|
697
|
+
const updatedFields = [];
|
|
698
|
+
let updateStatements = '';
|
|
699
|
+
if (updates.title != null) {
|
|
700
|
+
updateStatements += ` set subject of myEvent to "${escapeForAppleScript(updates.title)}"\n`;
|
|
701
|
+
updatedFields.push('title');
|
|
702
|
+
}
|
|
703
|
+
if (updates.location != null) {
|
|
704
|
+
updateStatements += ` set location of myEvent to "${escapeForAppleScript(updates.location)}"\n`;
|
|
705
|
+
updatedFields.push('location');
|
|
706
|
+
}
|
|
707
|
+
if (updates.description != null) {
|
|
708
|
+
updateStatements += ` set content of myEvent to "${escapeForAppleScript(updates.description)}"\n`;
|
|
709
|
+
updatedFields.push('description');
|
|
710
|
+
}
|
|
711
|
+
if (updates.startDate != null) {
|
|
712
|
+
const start = isoToDateComponents(updates.startDate);
|
|
713
|
+
updateStatements += ` set start time of myEvent to date "${start.year}-${start.month}-${start.day} ${start.hours}:${start.minutes}:00"\n`;
|
|
714
|
+
updatedFields.push('startDate');
|
|
715
|
+
}
|
|
716
|
+
if (updates.endDate != null) {
|
|
717
|
+
const end = isoToDateComponents(updates.endDate);
|
|
718
|
+
updateStatements += ` set end time of myEvent to date "${end.year}-${end.month}-${end.day} ${end.hours}:${end.minutes}:00"\n`;
|
|
719
|
+
updatedFields.push('endDate');
|
|
720
|
+
}
|
|
721
|
+
if (updates.isAllDay != null) {
|
|
722
|
+
updateStatements += ` set all day flag of myEvent to ${updates.isAllDay}\n`;
|
|
723
|
+
updatedFields.push('isAllDay');
|
|
724
|
+
}
|
|
725
|
+
const comment = applyTo === 'all_in_series'
|
|
726
|
+
? '-- Updating entire series'
|
|
727
|
+
: '-- Updating single instance';
|
|
728
|
+
const fieldsOutput = updatedFields.join(',');
|
|
729
|
+
return `
|
|
730
|
+
tell application "Microsoft Outlook"
|
|
731
|
+
try
|
|
732
|
+
${comment}
|
|
733
|
+
set myEvent to calendar event id ${eventId}
|
|
734
|
+
|
|
735
|
+
${updateStatements}
|
|
736
|
+
-- Return success
|
|
737
|
+
set output to "{{RECORD}}success{{=}}true{{FIELD}}eventId{{=}}" & ${eventId} & "{{FIELD}}updatedFields{{=}}${fieldsOutput}"
|
|
738
|
+
return output
|
|
739
|
+
on error errMsg
|
|
740
|
+
-- Return failure
|
|
741
|
+
set output to "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}" & errMsg
|
|
742
|
+
return output
|
|
743
|
+
end try
|
|
744
|
+
end tell
|
|
745
|
+
`;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Creates a new calendar event.
|
|
749
|
+
* Uses component-based date construction for locale safety.
|
|
750
|
+
*/
|
|
751
|
+
export function createEvent(params) {
|
|
752
|
+
const escapedTitle = escapeForAppleScript(params.title);
|
|
753
|
+
const escapedLocation = params.location != null ? escapeForAppleScript(params.location) : '';
|
|
754
|
+
const escapedDescription = params.description != null ? escapeForAppleScript(params.description) : '';
|
|
755
|
+
// Build properties list
|
|
756
|
+
let properties = `subject:"${escapedTitle}", start time:theStartDate, end time:theEndDate`;
|
|
757
|
+
if (params.location != null) {
|
|
758
|
+
properties += `, location:"${escapedLocation}"`;
|
|
759
|
+
}
|
|
760
|
+
if (params.isAllDay === true) {
|
|
761
|
+
properties += ', all day flag:true';
|
|
762
|
+
}
|
|
763
|
+
// Build the target clause for calendar
|
|
764
|
+
const targetClause = params.calendarId != null
|
|
765
|
+
? `at calendar id ${params.calendarId} `
|
|
766
|
+
: '';
|
|
767
|
+
return `
|
|
768
|
+
tell application "Microsoft Outlook"
|
|
769
|
+
set theStartDate to current date
|
|
770
|
+
set day of theStartDate to 1
|
|
771
|
+
set year of theStartDate to ${params.startYear}
|
|
772
|
+
set month of theStartDate to ${params.startMonth}
|
|
773
|
+
set day of theStartDate to ${params.startDay}
|
|
774
|
+
set hours of theStartDate to ${params.startHours}
|
|
775
|
+
set minutes of theStartDate to ${params.startMinutes}
|
|
776
|
+
set seconds of theStartDate to 0
|
|
777
|
+
|
|
778
|
+
set theEndDate to current date
|
|
779
|
+
set day of theEndDate to 1
|
|
780
|
+
set year of theEndDate to ${params.endYear}
|
|
781
|
+
set month of theEndDate to ${params.endMonth}
|
|
782
|
+
set day of theEndDate to ${params.endDay}
|
|
783
|
+
set hours of theEndDate to ${params.endHours}
|
|
784
|
+
set minutes of theEndDate to ${params.endMinutes}
|
|
785
|
+
set seconds of theEndDate to 0
|
|
786
|
+
|
|
787
|
+
set newEvent to make new calendar event ${targetClause}with properties {${properties}}
|
|
788
|
+
${escapedDescription ? `set plain text content of newEvent to "${escapedDescription}"` : ''}${params.recurrence != null ? buildRecurrenceScript(params.recurrence) : ''}
|
|
789
|
+
set eId to id of newEvent
|
|
790
|
+
set eCalId to ""
|
|
791
|
+
try
|
|
792
|
+
set eCalId to id of calendar of newEvent
|
|
793
|
+
end try
|
|
794
|
+
return "{{RECORD}}id{{=}}" & eId & "{{FIELD}}calendarId{{=}}" & eCalId
|
|
795
|
+
end tell
|
|
796
|
+
`;
|
|
797
|
+
}
|
|
798
|
+
// =============================================================================
|
|
799
|
+
// Contact Scripts
|
|
800
|
+
// =============================================================================
|
|
801
|
+
/**
|
|
802
|
+
* Lists all contacts.
|
|
803
|
+
*/
|
|
804
|
+
export function listContacts(limit, offset) {
|
|
805
|
+
const totalToFetch = limit + offset;
|
|
806
|
+
return `
|
|
807
|
+
tell application "Microsoft Outlook"
|
|
808
|
+
set output to ""
|
|
809
|
+
set allContacts to contacts
|
|
810
|
+
set contactCount to count of allContacts
|
|
811
|
+
set startIdx to ${offset + 1}
|
|
812
|
+
set endIdx to ${totalToFetch}
|
|
813
|
+
if endIdx > contactCount then set endIdx to contactCount
|
|
814
|
+
if startIdx > contactCount then return ""
|
|
815
|
+
|
|
816
|
+
repeat with i from startIdx to endIdx
|
|
817
|
+
try
|
|
818
|
+
set c to item i of allContacts
|
|
819
|
+
set cId to id of c
|
|
820
|
+
set cDisplay to display name of c
|
|
821
|
+
set cFirst to ""
|
|
822
|
+
try
|
|
823
|
+
set cFirst to first name of c
|
|
824
|
+
end try
|
|
825
|
+
set cLast to ""
|
|
826
|
+
try
|
|
827
|
+
set cLast to last name of c
|
|
828
|
+
end try
|
|
829
|
+
set cCompany to ""
|
|
830
|
+
try
|
|
831
|
+
set cCompany to company of c
|
|
832
|
+
end try
|
|
833
|
+
set cEmail to ""
|
|
834
|
+
try
|
|
835
|
+
set emailAddrs to email addresses of c
|
|
836
|
+
if (count of emailAddrs) > 0 then
|
|
837
|
+
set cEmail to address of item 1 of emailAddrs
|
|
838
|
+
end if
|
|
839
|
+
end try
|
|
840
|
+
|
|
841
|
+
set output to output & "{{RECORD}}id{{=}}" & cId & "{{FIELD}}displayName{{=}}" & cDisplay & "{{FIELD}}firstName{{=}}" & cFirst & "{{FIELD}}lastName{{=}}" & cLast & "{{FIELD}}company{{=}}" & cCompany & "{{FIELD}}email{{=}}" & cEmail
|
|
842
|
+
end try
|
|
843
|
+
end repeat
|
|
844
|
+
return output
|
|
845
|
+
end tell
|
|
846
|
+
`;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Searches contacts by name.
|
|
850
|
+
*/
|
|
851
|
+
export function searchContacts(query, limit) {
|
|
852
|
+
const escapedQuery = escapeForAppleScript(query);
|
|
853
|
+
return `
|
|
854
|
+
tell application "Microsoft Outlook"
|
|
855
|
+
set output to ""
|
|
856
|
+
set searchResults to (contacts whose display name contains "${escapedQuery}")
|
|
857
|
+
set resultCount to count of searchResults
|
|
858
|
+
set maxResults to ${limit}
|
|
859
|
+
if resultCount < maxResults then set maxResults to resultCount
|
|
860
|
+
|
|
861
|
+
repeat with i from 1 to maxResults
|
|
862
|
+
try
|
|
863
|
+
set c to item i of searchResults
|
|
864
|
+
set cId to id of c
|
|
865
|
+
set cDisplay to display name of c
|
|
866
|
+
set cFirst to ""
|
|
867
|
+
try
|
|
868
|
+
set cFirst to first name of c
|
|
869
|
+
end try
|
|
870
|
+
set cLast to ""
|
|
871
|
+
try
|
|
872
|
+
set cLast to last name of c
|
|
873
|
+
end try
|
|
874
|
+
set cCompany to ""
|
|
875
|
+
try
|
|
876
|
+
set cCompany to company of c
|
|
877
|
+
end try
|
|
878
|
+
set cEmail to ""
|
|
879
|
+
try
|
|
880
|
+
set emailAddrs to email addresses of c
|
|
881
|
+
if (count of emailAddrs) > 0 then
|
|
882
|
+
set cEmail to address of item 1 of emailAddrs
|
|
883
|
+
end if
|
|
884
|
+
end try
|
|
885
|
+
|
|
886
|
+
set output to output & "{{RECORD}}id{{=}}" & cId & "{{FIELD}}displayName{{=}}" & cDisplay & "{{FIELD}}firstName{{=}}" & cFirst & "{{FIELD}}lastName{{=}}" & cLast & "{{FIELD}}company{{=}}" & cCompany & "{{FIELD}}email{{=}}" & cEmail
|
|
887
|
+
end try
|
|
888
|
+
end repeat
|
|
889
|
+
return output
|
|
890
|
+
end tell
|
|
891
|
+
`;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Gets a single contact by ID with full details.
|
|
895
|
+
*/
|
|
896
|
+
export function getContact(contactId) {
|
|
897
|
+
return `
|
|
898
|
+
tell application "Microsoft Outlook"
|
|
899
|
+
set c to contact id ${contactId}
|
|
900
|
+
set cId to id of c
|
|
901
|
+
set cDisplay to display name of c
|
|
902
|
+
set cFirst to ""
|
|
903
|
+
try
|
|
904
|
+
set cFirst to first name of c
|
|
905
|
+
end try
|
|
906
|
+
set cLast to ""
|
|
907
|
+
try
|
|
908
|
+
set cLast to last name of c
|
|
909
|
+
end try
|
|
910
|
+
set cMiddle to ""
|
|
911
|
+
try
|
|
912
|
+
set cMiddle to middle name of c
|
|
913
|
+
end try
|
|
914
|
+
set cNickname to ""
|
|
915
|
+
try
|
|
916
|
+
set cNickname to nickname of c
|
|
917
|
+
end try
|
|
918
|
+
set cCompany to ""
|
|
919
|
+
try
|
|
920
|
+
set cCompany to company of c
|
|
921
|
+
end try
|
|
922
|
+
set cTitle to ""
|
|
923
|
+
try
|
|
924
|
+
set cTitle to job title of c
|
|
925
|
+
end try
|
|
926
|
+
set cDept to ""
|
|
927
|
+
try
|
|
928
|
+
set cDept to department of c
|
|
929
|
+
end try
|
|
930
|
+
set cNotes to ""
|
|
931
|
+
try
|
|
932
|
+
set cNotes to description of c
|
|
933
|
+
end try
|
|
934
|
+
|
|
935
|
+
-- Phones
|
|
936
|
+
set cHomePhone to ""
|
|
937
|
+
try
|
|
938
|
+
set cHomePhone to home phone number of c
|
|
939
|
+
end try
|
|
940
|
+
set cWorkPhone to ""
|
|
941
|
+
try
|
|
942
|
+
set cWorkPhone to business phone number of c
|
|
943
|
+
end try
|
|
944
|
+
set cMobile to ""
|
|
945
|
+
try
|
|
946
|
+
set cMobile to mobile number of c
|
|
947
|
+
end try
|
|
948
|
+
|
|
949
|
+
-- Emails
|
|
950
|
+
set emailList to ""
|
|
951
|
+
try
|
|
952
|
+
repeat with e in email addresses of c
|
|
953
|
+
set emailList to emailList & (address of e) & ","
|
|
954
|
+
end repeat
|
|
955
|
+
end try
|
|
956
|
+
|
|
957
|
+
-- Address
|
|
958
|
+
set cHomeStreet to ""
|
|
959
|
+
try
|
|
960
|
+
set cHomeStreet to home street address of c
|
|
961
|
+
end try
|
|
962
|
+
set cHomeCity to ""
|
|
963
|
+
try
|
|
964
|
+
set cHomeCity to home city of c
|
|
965
|
+
end try
|
|
966
|
+
set cHomeState to ""
|
|
967
|
+
try
|
|
968
|
+
set cHomeState to home state of c
|
|
969
|
+
end try
|
|
970
|
+
set cHomeZip to ""
|
|
971
|
+
try
|
|
972
|
+
set cHomeZip to home zip of c
|
|
973
|
+
end try
|
|
974
|
+
set cHomeCountry to ""
|
|
975
|
+
try
|
|
976
|
+
set cHomeCountry to home country of c
|
|
977
|
+
end try
|
|
978
|
+
|
|
979
|
+
return "{{RECORD}}id{{=}}" & cId & "{{FIELD}}displayName{{=}}" & cDisplay & "{{FIELD}}firstName{{=}}" & cFirst & "{{FIELD}}lastName{{=}}" & cLast & "{{FIELD}}middleName{{=}}" & cMiddle & "{{FIELD}}nickname{{=}}" & cNickname & "{{FIELD}}company{{=}}" & cCompany & "{{FIELD}}jobTitle{{=}}" & cTitle & "{{FIELD}}department{{=}}" & cDept & "{{FIELD}}notes{{=}}" & cNotes & "{{FIELD}}homePhone{{=}}" & cHomePhone & "{{FIELD}}workPhone{{=}}" & cWorkPhone & "{{FIELD}}mobilePhone{{=}}" & cMobile & "{{FIELD}}emails{{=}}" & emailList & "{{FIELD}}homeStreet{{=}}" & cHomeStreet & "{{FIELD}}homeCity{{=}}" & cHomeCity & "{{FIELD}}homeState{{=}}" & cHomeState & "{{FIELD}}homeZip{{=}}" & cHomeZip & "{{FIELD}}homeCountry{{=}}" & cHomeCountry
|
|
980
|
+
end tell
|
|
981
|
+
`;
|
|
982
|
+
}
|
|
983
|
+
// =============================================================================
|
|
984
|
+
// Task Scripts
|
|
985
|
+
// =============================================================================
|
|
986
|
+
/**
|
|
987
|
+
* Lists all tasks.
|
|
988
|
+
*/
|
|
989
|
+
export function listTasks(limit, offset, includeCompleted) {
|
|
990
|
+
const totalToFetch = limit + offset;
|
|
991
|
+
const completedFilter = includeCompleted ? '' : ' whose is completed is false';
|
|
992
|
+
return `
|
|
993
|
+
tell application "Microsoft Outlook"
|
|
994
|
+
set output to ""
|
|
995
|
+
set allTasks to (tasks${completedFilter})
|
|
996
|
+
set taskCount to count of allTasks
|
|
997
|
+
set startIdx to ${offset + 1}
|
|
998
|
+
set endIdx to ${totalToFetch}
|
|
999
|
+
if endIdx > taskCount then set endIdx to taskCount
|
|
1000
|
+
if startIdx > taskCount then return ""
|
|
1001
|
+
|
|
1002
|
+
repeat with i from startIdx to endIdx
|
|
1003
|
+
try
|
|
1004
|
+
set t to item i of allTasks
|
|
1005
|
+
set tId to id of t
|
|
1006
|
+
set tName to name of t
|
|
1007
|
+
set tDue to ""
|
|
1008
|
+
try
|
|
1009
|
+
set tDue to due date of t as «class isot» as string
|
|
1010
|
+
end try
|
|
1011
|
+
set tCompleted to is completed of t
|
|
1012
|
+
set tPriority to "normal"
|
|
1013
|
+
try
|
|
1014
|
+
set p to priority of t
|
|
1015
|
+
if p is priority high then
|
|
1016
|
+
set tPriority to "high"
|
|
1017
|
+
else if p is priority low then
|
|
1018
|
+
set tPriority to "low"
|
|
1019
|
+
end if
|
|
1020
|
+
end try
|
|
1021
|
+
|
|
1022
|
+
set output to output & "{{RECORD}}id{{=}}" & tId & "{{FIELD}}name{{=}}" & tName & "{{FIELD}}dueDate{{=}}" & tDue & "{{FIELD}}isCompleted{{=}}" & tCompleted & "{{FIELD}}priority{{=}}" & tPriority
|
|
1023
|
+
end try
|
|
1024
|
+
end repeat
|
|
1025
|
+
return output
|
|
1026
|
+
end tell
|
|
1027
|
+
`;
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Searches tasks by name.
|
|
1031
|
+
*/
|
|
1032
|
+
export function searchTasks(query, limit) {
|
|
1033
|
+
const escapedQuery = escapeForAppleScript(query);
|
|
1034
|
+
return `
|
|
1035
|
+
tell application "Microsoft Outlook"
|
|
1036
|
+
set output to ""
|
|
1037
|
+
set searchResults to (tasks whose name contains "${escapedQuery}")
|
|
1038
|
+
set resultCount to count of searchResults
|
|
1039
|
+
set maxResults to ${limit}
|
|
1040
|
+
if resultCount < maxResults then set maxResults to resultCount
|
|
1041
|
+
|
|
1042
|
+
repeat with i from 1 to maxResults
|
|
1043
|
+
try
|
|
1044
|
+
set t to item i of searchResults
|
|
1045
|
+
set tId to id of t
|
|
1046
|
+
set tName to name of t
|
|
1047
|
+
set tDue to ""
|
|
1048
|
+
try
|
|
1049
|
+
set tDue to due date of t as «class isot» as string
|
|
1050
|
+
end try
|
|
1051
|
+
set tCompleted to is completed of t
|
|
1052
|
+
|
|
1053
|
+
set output to output & "{{RECORD}}id{{=}}" & tId & "{{FIELD}}name{{=}}" & tName & "{{FIELD}}dueDate{{=}}" & tDue & "{{FIELD}}isCompleted{{=}}" & tCompleted
|
|
1054
|
+
end try
|
|
1055
|
+
end repeat
|
|
1056
|
+
return output
|
|
1057
|
+
end tell
|
|
1058
|
+
`;
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Gets a single task by ID.
|
|
1062
|
+
*/
|
|
1063
|
+
export function getTask(taskId) {
|
|
1064
|
+
return `
|
|
1065
|
+
tell application "Microsoft Outlook"
|
|
1066
|
+
set t to task id ${taskId}
|
|
1067
|
+
set tId to id of t
|
|
1068
|
+
set tName to name of t
|
|
1069
|
+
set tContent to ""
|
|
1070
|
+
try
|
|
1071
|
+
set tContent to content of t
|
|
1072
|
+
end try
|
|
1073
|
+
set tPlain to ""
|
|
1074
|
+
try
|
|
1075
|
+
set tPlain to plain text content of t
|
|
1076
|
+
end try
|
|
1077
|
+
set tDue to ""
|
|
1078
|
+
try
|
|
1079
|
+
set tDue to due date of t as «class isot» as string
|
|
1080
|
+
end try
|
|
1081
|
+
set tStart to ""
|
|
1082
|
+
try
|
|
1083
|
+
set tStart to start date of t as «class isot» as string
|
|
1084
|
+
end try
|
|
1085
|
+
set tCompletedDate to ""
|
|
1086
|
+
try
|
|
1087
|
+
set tCompletedDate to completed date of t as «class isot» as string
|
|
1088
|
+
end try
|
|
1089
|
+
set tCompleted to is completed of t
|
|
1090
|
+
set tPriority to "normal"
|
|
1091
|
+
try
|
|
1092
|
+
set p to priority of t
|
|
1093
|
+
if p is priority high then
|
|
1094
|
+
set tPriority to "high"
|
|
1095
|
+
else if p is priority low then
|
|
1096
|
+
set tPriority to "low"
|
|
1097
|
+
end if
|
|
1098
|
+
end try
|
|
1099
|
+
set tFolderId to ""
|
|
1100
|
+
try
|
|
1101
|
+
set tFolderId to id of folder of t
|
|
1102
|
+
end try
|
|
1103
|
+
|
|
1104
|
+
return "{{RECORD}}id{{=}}" & tId & "{{FIELD}}name{{=}}" & tName & "{{FIELD}}htmlContent{{=}}" & tContent & "{{FIELD}}plainContent{{=}}" & tPlain & "{{FIELD}}dueDate{{=}}" & tDue & "{{FIELD}}startDate{{=}}" & tStart & "{{FIELD}}completedDate{{=}}" & tCompletedDate & "{{FIELD}}isCompleted{{=}}" & tCompleted & "{{FIELD}}priority{{=}}" & tPriority & "{{FIELD}}folderId{{=}}" & tFolderId
|
|
1105
|
+
end tell
|
|
1106
|
+
`;
|
|
1107
|
+
}
|
|
1108
|
+
// =============================================================================
|
|
1109
|
+
// Note Scripts
|
|
1110
|
+
// =============================================================================
|
|
1111
|
+
/**
|
|
1112
|
+
* Lists all notes.
|
|
1113
|
+
*/
|
|
1114
|
+
export function listNotes(limit, offset) {
|
|
1115
|
+
const totalToFetch = limit + offset;
|
|
1116
|
+
return `
|
|
1117
|
+
tell application "Microsoft Outlook"
|
|
1118
|
+
set output to ""
|
|
1119
|
+
set allNotes to notes
|
|
1120
|
+
set noteCount to count of allNotes
|
|
1121
|
+
set startIdx to ${offset + 1}
|
|
1122
|
+
set endIdx to ${totalToFetch}
|
|
1123
|
+
if endIdx > noteCount then set endIdx to noteCount
|
|
1124
|
+
if startIdx > noteCount then return ""
|
|
1125
|
+
|
|
1126
|
+
repeat with i from startIdx to endIdx
|
|
1127
|
+
try
|
|
1128
|
+
set n to item i of allNotes
|
|
1129
|
+
set nId to id of n
|
|
1130
|
+
set nName to name of n
|
|
1131
|
+
set nCreated to ""
|
|
1132
|
+
try
|
|
1133
|
+
set nCreated to creation date of n as «class isot» as string
|
|
1134
|
+
end try
|
|
1135
|
+
set nModified to ""
|
|
1136
|
+
try
|
|
1137
|
+
set nModified to modification date of n as «class isot» as string
|
|
1138
|
+
end try
|
|
1139
|
+
set nPreview to ""
|
|
1140
|
+
try
|
|
1141
|
+
set nPreview to text 1 thru 200 of plain text content of n
|
|
1142
|
+
on error
|
|
1143
|
+
try
|
|
1144
|
+
set nPreview to plain text content of n
|
|
1145
|
+
end try
|
|
1146
|
+
end try
|
|
1147
|
+
|
|
1148
|
+
set output to output & "{{RECORD}}id{{=}}" & nId & "{{FIELD}}name{{=}}" & nName & "{{FIELD}}createdDate{{=}}" & nCreated & "{{FIELD}}modifiedDate{{=}}" & nModified & "{{FIELD}}preview{{=}}" & nPreview
|
|
1149
|
+
end try
|
|
1150
|
+
end repeat
|
|
1151
|
+
return output
|
|
1152
|
+
end tell
|
|
1153
|
+
`;
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Searches notes by name.
|
|
1157
|
+
*/
|
|
1158
|
+
export function searchNotes(query, limit) {
|
|
1159
|
+
const escapedQuery = escapeForAppleScript(query);
|
|
1160
|
+
return `
|
|
1161
|
+
tell application "Microsoft Outlook"
|
|
1162
|
+
set output to ""
|
|
1163
|
+
set searchResults to (notes whose name contains "${escapedQuery}")
|
|
1164
|
+
set resultCount to count of searchResults
|
|
1165
|
+
set maxResults to ${limit}
|
|
1166
|
+
if resultCount < maxResults then set maxResults to resultCount
|
|
1167
|
+
|
|
1168
|
+
repeat with i from 1 to maxResults
|
|
1169
|
+
try
|
|
1170
|
+
set n to item i of searchResults
|
|
1171
|
+
set nId to id of n
|
|
1172
|
+
set nName to name of n
|
|
1173
|
+
set nCreated to ""
|
|
1174
|
+
try
|
|
1175
|
+
set nCreated to creation date of n as «class isot» as string
|
|
1176
|
+
end try
|
|
1177
|
+
set nPreview to ""
|
|
1178
|
+
try
|
|
1179
|
+
set nPreview to text 1 thru 200 of plain text content of n
|
|
1180
|
+
on error
|
|
1181
|
+
try
|
|
1182
|
+
set nPreview to plain text content of n
|
|
1183
|
+
end try
|
|
1184
|
+
end try
|
|
1185
|
+
|
|
1186
|
+
set output to output & "{{RECORD}}id{{=}}" & nId & "{{FIELD}}name{{=}}" & nName & "{{FIELD}}createdDate{{=}}" & nCreated & "{{FIELD}}preview{{=}}" & nPreview
|
|
1187
|
+
end try
|
|
1188
|
+
end repeat
|
|
1189
|
+
return output
|
|
1190
|
+
end tell
|
|
1191
|
+
`;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Gets a single note by ID.
|
|
1195
|
+
*/
|
|
1196
|
+
export function getNote(noteId) {
|
|
1197
|
+
return `
|
|
1198
|
+
tell application "Microsoft Outlook"
|
|
1199
|
+
set n to note id ${noteId}
|
|
1200
|
+
set nId to id of n
|
|
1201
|
+
set nName to name of n
|
|
1202
|
+
set nContent to ""
|
|
1203
|
+
try
|
|
1204
|
+
set nContent to content of n
|
|
1205
|
+
end try
|
|
1206
|
+
set nPlain to ""
|
|
1207
|
+
try
|
|
1208
|
+
set nPlain to plain text content of n
|
|
1209
|
+
end try
|
|
1210
|
+
set nCreated to ""
|
|
1211
|
+
try
|
|
1212
|
+
set nCreated to creation date of n as «class isot» as string
|
|
1213
|
+
end try
|
|
1214
|
+
set nModified to ""
|
|
1215
|
+
try
|
|
1216
|
+
set nModified to modification date of n as «class isot» as string
|
|
1217
|
+
end try
|
|
1218
|
+
set nFolderId to ""
|
|
1219
|
+
try
|
|
1220
|
+
set nFolderId to id of folder of n
|
|
1221
|
+
end try
|
|
1222
|
+
|
|
1223
|
+
return "{{RECORD}}id{{=}}" & nId & "{{FIELD}}name{{=}}" & nName & "{{FIELD}}htmlContent{{=}}" & nContent & "{{FIELD}}plainContent{{=}}" & nPlain & "{{FIELD}}createdDate{{=}}" & nCreated & "{{FIELD}}modifiedDate{{=}}" & nModified & "{{FIELD}}folderId{{=}}" & nFolderId
|
|
1224
|
+
end tell
|
|
1225
|
+
`;
|
|
1226
|
+
}
|
|
1227
|
+
// Write Operation Scripts
|
|
1228
|
+
// =============================================================================
|
|
1229
|
+
/**
|
|
1230
|
+
* Moves a message to a different folder.
|
|
1231
|
+
*/
|
|
1232
|
+
export function moveMessage(messageId, destinationFolderId) {
|
|
1233
|
+
return `
|
|
1234
|
+
tell application "Microsoft Outlook"
|
|
1235
|
+
set m to message id ${messageId}
|
|
1236
|
+
set targetFolder to mail folder id ${destinationFolderId}
|
|
1237
|
+
move m to targetFolder
|
|
1238
|
+
return "ok"
|
|
1239
|
+
end tell
|
|
1240
|
+
`;
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Moves a message to the Deleted Items folder.
|
|
1244
|
+
*/
|
|
1245
|
+
export function deleteMessage(messageId) {
|
|
1246
|
+
return `
|
|
1247
|
+
tell application "Microsoft Outlook"
|
|
1248
|
+
set m to message id ${messageId}
|
|
1249
|
+
set deletedFolder to deleted items
|
|
1250
|
+
move m to deletedFolder
|
|
1251
|
+
return "ok"
|
|
1252
|
+
end tell
|
|
1253
|
+
`;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Moves a message to the Archive folder.
|
|
1257
|
+
* Falls back to an "Archive" named folder if the well-known folder isn't available.
|
|
1258
|
+
*/
|
|
1259
|
+
export function archiveMessage(messageId) {
|
|
1260
|
+
return `
|
|
1261
|
+
tell application "Microsoft Outlook"
|
|
1262
|
+
set m to message id ${messageId}
|
|
1263
|
+
try
|
|
1264
|
+
set archiveFolder to mail folder "Archive"
|
|
1265
|
+
move m to archiveFolder
|
|
1266
|
+
on error
|
|
1267
|
+
-- Try finding by name
|
|
1268
|
+
set allFolders to mail folders
|
|
1269
|
+
repeat with f in allFolders
|
|
1270
|
+
if name of f is "Archive" then
|
|
1271
|
+
move m to f
|
|
1272
|
+
return "ok"
|
|
1273
|
+
end if
|
|
1274
|
+
end repeat
|
|
1275
|
+
error "Archive folder not found"
|
|
1276
|
+
end try
|
|
1277
|
+
return "ok"
|
|
1278
|
+
end tell
|
|
1279
|
+
`;
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Moves a message to the Junk folder.
|
|
1283
|
+
*/
|
|
1284
|
+
export function junkMessage(messageId) {
|
|
1285
|
+
return `
|
|
1286
|
+
tell application "Microsoft Outlook"
|
|
1287
|
+
set m to message id ${messageId}
|
|
1288
|
+
set junkFolder to junk mail
|
|
1289
|
+
move m to junkFolder
|
|
1290
|
+
return "ok"
|
|
1291
|
+
end tell
|
|
1292
|
+
`;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Sets the read status of a message.
|
|
1296
|
+
*/
|
|
1297
|
+
export function setMessageReadStatus(messageId, isRead) {
|
|
1298
|
+
return `
|
|
1299
|
+
tell application "Microsoft Outlook"
|
|
1300
|
+
set m to message id ${messageId}
|
|
1301
|
+
set is read of m to ${isRead}
|
|
1302
|
+
return "ok"
|
|
1303
|
+
end tell
|
|
1304
|
+
`;
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* Sets the flag status of a message.
|
|
1308
|
+
* flagStatus: 0 = none, 1 = flagged, 2 = completed
|
|
1309
|
+
*/
|
|
1310
|
+
export function setMessageFlag(messageId, flagStatus) {
|
|
1311
|
+
let flagValue;
|
|
1312
|
+
switch (flagStatus) {
|
|
1313
|
+
case 1:
|
|
1314
|
+
flagValue = 'flag marked';
|
|
1315
|
+
break;
|
|
1316
|
+
case 2:
|
|
1317
|
+
flagValue = 'flag complete';
|
|
1318
|
+
break;
|
|
1319
|
+
default:
|
|
1320
|
+
flagValue = 'flag not flagged';
|
|
1321
|
+
}
|
|
1322
|
+
return `
|
|
1323
|
+
tell application "Microsoft Outlook"
|
|
1324
|
+
set m to message id ${messageId}
|
|
1325
|
+
set todo flag of m to ${flagValue}
|
|
1326
|
+
return "ok"
|
|
1327
|
+
end tell
|
|
1328
|
+
`;
|
|
1329
|
+
}
|
|
1330
|
+
/**
|
|
1331
|
+
* Sets categories on a message.
|
|
1332
|
+
*/
|
|
1333
|
+
export function setMessageCategories(messageId, categories) {
|
|
1334
|
+
const categoryList = categories.map(c => `"${escapeForAppleScript(c)}"`).join(', ');
|
|
1335
|
+
return `
|
|
1336
|
+
tell application "Microsoft Outlook"
|
|
1337
|
+
set m to message id ${messageId}
|
|
1338
|
+
set category of m to {${categoryList}}
|
|
1339
|
+
return "ok"
|
|
1340
|
+
end tell
|
|
1341
|
+
`;
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Creates a new mail folder.
|
|
1345
|
+
*/
|
|
1346
|
+
export function createMailFolder(name, parentFolderId) {
|
|
1347
|
+
const escapedName = escapeForAppleScript(name);
|
|
1348
|
+
if (parentFolderId != null) {
|
|
1349
|
+
return `
|
|
1350
|
+
tell application "Microsoft Outlook"
|
|
1351
|
+
set parentFolder to mail folder id ${parentFolderId}
|
|
1352
|
+
set newFolder to make new mail folder at parentFolder with properties {name:"${escapedName}"}
|
|
1353
|
+
return id of newFolder
|
|
1354
|
+
end tell
|
|
1355
|
+
`;
|
|
1356
|
+
}
|
|
1357
|
+
return `
|
|
1358
|
+
tell application "Microsoft Outlook"
|
|
1359
|
+
set newFolder to make new mail folder with properties {name:"${escapedName}"}
|
|
1360
|
+
return id of newFolder
|
|
1361
|
+
end tell
|
|
1362
|
+
`;
|
|
1363
|
+
}
|
|
1364
|
+
/**
|
|
1365
|
+
* Deletes a mail folder.
|
|
1366
|
+
*/
|
|
1367
|
+
export function deleteMailFolder(folderId) {
|
|
1368
|
+
return `
|
|
1369
|
+
tell application "Microsoft Outlook"
|
|
1370
|
+
set f to mail folder id ${folderId}
|
|
1371
|
+
delete f
|
|
1372
|
+
return "ok"
|
|
1373
|
+
end tell
|
|
1374
|
+
`;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Renames a mail folder.
|
|
1378
|
+
*/
|
|
1379
|
+
export function renameMailFolder(folderId, newName) {
|
|
1380
|
+
const escapedName = escapeForAppleScript(newName);
|
|
1381
|
+
return `
|
|
1382
|
+
tell application "Microsoft Outlook"
|
|
1383
|
+
set f to mail folder id ${folderId}
|
|
1384
|
+
set name of f to "${escapedName}"
|
|
1385
|
+
return "ok"
|
|
1386
|
+
end tell
|
|
1387
|
+
`;
|
|
1388
|
+
}
|
|
1389
|
+
/**
|
|
1390
|
+
* Moves a mail folder to a new parent.
|
|
1391
|
+
*/
|
|
1392
|
+
export function moveMailFolder(folderId, destinationParentId) {
|
|
1393
|
+
return `
|
|
1394
|
+
tell application "Microsoft Outlook"
|
|
1395
|
+
set f to mail folder id ${folderId}
|
|
1396
|
+
set targetParent to mail folder id ${destinationParentId}
|
|
1397
|
+
move f to targetParent
|
|
1398
|
+
return "ok"
|
|
1399
|
+
end tell
|
|
1400
|
+
`;
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Deletes all messages in a folder (empties the folder).
|
|
1404
|
+
*/
|
|
1405
|
+
export function emptyMailFolder(folderId) {
|
|
1406
|
+
return `
|
|
1407
|
+
tell application "Microsoft Outlook"
|
|
1408
|
+
set targetFolder to mail folder id ${folderId}
|
|
1409
|
+
set msgs to messages of targetFolder
|
|
1410
|
+
set deletedFolder to deleted items
|
|
1411
|
+
repeat with m in msgs
|
|
1412
|
+
try
|
|
1413
|
+
move m to deletedFolder
|
|
1414
|
+
end try
|
|
1415
|
+
end repeat
|
|
1416
|
+
return "ok"
|
|
1417
|
+
end tell
|
|
1418
|
+
`;
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Sends an email with optional CC, BCC, attachments, and account selection.
|
|
1422
|
+
*/
|
|
1423
|
+
export function sendEmail(params) {
|
|
1424
|
+
const { to, subject, body, bodyType, cc, bcc, replyTo, attachments, inlineImages, accountId } = params;
|
|
1425
|
+
const escapedSubject = escapeForAppleScript(subject);
|
|
1426
|
+
const escapedBody = escapeForAppleScript(body);
|
|
1427
|
+
const toRecipients = to.map(email => ` make new recipient at newMessage with properties {email address:{address:"${email}"}}`).join('\n');
|
|
1428
|
+
const ccRecipients = cc != null && cc.length > 0
|
|
1429
|
+
? cc.map(email => ` make new recipient at newMessage with properties {email address:{address:"${email}"}, recipient type:recipient cc}`).join('\n')
|
|
1430
|
+
: '';
|
|
1431
|
+
const bccRecipients = bcc != null && bcc.length > 0
|
|
1432
|
+
? bcc.map(email => ` make new recipient at newMessage with properties {email address:{address:"${email}"}, recipient type:recipient bcc}`).join('\n')
|
|
1433
|
+
: '';
|
|
1434
|
+
const contentProperty = bodyType === 'html'
|
|
1435
|
+
? `html content:"${escapedBody}"`
|
|
1436
|
+
: `plain text content:"${escapedBody}"`;
|
|
1437
|
+
const replyToStatement = replyTo != null
|
|
1438
|
+
? ` set reply to of newMessage to "${replyTo}"`
|
|
1439
|
+
: '';
|
|
1440
|
+
const attachmentStatements = attachments != null && attachments.length > 0
|
|
1441
|
+
? attachments.map(att => ` make new attachment at newMessage with properties {file:(POSIX file "${att.path}")}`).join('\n')
|
|
1442
|
+
: '';
|
|
1443
|
+
const inlineImageStatements = inlineImages != null && inlineImages.length > 0
|
|
1444
|
+
? inlineImages.map((img, i) => ` set inlineAttach${i} to make new attachment at newMessage with properties {file:(POSIX file "${img.path}")}\n` +
|
|
1445
|
+
` try\n` +
|
|
1446
|
+
` set content id of inlineAttach${i} to "${img.contentId}"\n` +
|
|
1447
|
+
` end try`).join('\n')
|
|
1448
|
+
: '';
|
|
1449
|
+
const accountStatement = accountId != null
|
|
1450
|
+
? ` set sending account of newMessage to account id ${accountId}`
|
|
1451
|
+
: '';
|
|
1452
|
+
return `
|
|
1453
|
+
tell application "Microsoft Outlook"
|
|
1454
|
+
try
|
|
1455
|
+
set newMessage to make new outgoing message with properties {subject:"${escapedSubject}", ${contentProperty}}
|
|
1456
|
+
|
|
1457
|
+
${toRecipients}
|
|
1458
|
+
${ccRecipients}
|
|
1459
|
+
${bccRecipients}
|
|
1460
|
+
${replyToStatement}
|
|
1461
|
+
${accountStatement}
|
|
1462
|
+
${attachmentStatements}
|
|
1463
|
+
${inlineImageStatements}
|
|
1464
|
+
|
|
1465
|
+
send newMessage
|
|
1466
|
+
|
|
1467
|
+
-- Get message ID and timestamp
|
|
1468
|
+
set msgId to id of newMessage as string
|
|
1469
|
+
set sentTime to current date
|
|
1470
|
+
set sentISO to sentTime as «class isot» as string
|
|
1471
|
+
|
|
1472
|
+
-- Return success
|
|
1473
|
+
set output to "{{RECORD}}success{{=}}true{{FIELD}}messageId{{=}}" & msgId & "{{FIELD}}sentAt{{=}}" & sentISO
|
|
1474
|
+
return output
|
|
1475
|
+
on error errMsg
|
|
1476
|
+
-- Return failure
|
|
1477
|
+
set output to "{{RECORD}}success{{=}}false{{FIELD}}error{{=}}" & errMsg
|
|
1478
|
+
return output
|
|
1479
|
+
end try
|
|
1480
|
+
end tell
|
|
1481
|
+
`;
|
|
1482
|
+
}
|
|
1483
|
+
//# sourceMappingURL=scripts.js.map
|