@dawnlit/outlook-bridge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +253 -0
  3. package/dist/OutlookService.d.ts +43 -0
  4. package/dist/OutlookService.js +137 -0
  5. package/dist/OutlookService.js.map +1 -0
  6. package/dist/errors.d.ts +112 -0
  7. package/dist/errors.js +140 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.js +71 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/mac/accounts.d.ts +5 -0
  13. package/dist/mac/accounts.js +17 -0
  14. package/dist/mac/accounts.js.map +1 -0
  15. package/dist/mac/attachments.d.ts +28 -0
  16. package/dist/mac/attachments.js +120 -0
  17. package/dist/mac/attachments.js.map +1 -0
  18. package/dist/mac/bounces.d.ts +32 -0
  19. package/dist/mac/bounces.js +285 -0
  20. package/dist/mac/bounces.js.map +1 -0
  21. package/dist/mac/cleanup.d.ts +29 -0
  22. package/dist/mac/cleanup.js +219 -0
  23. package/dist/mac/cleanup.js.map +1 -0
  24. package/dist/mac/drafts.d.ts +27 -0
  25. package/dist/mac/drafts.js +214 -0
  26. package/dist/mac/drafts.js.map +1 -0
  27. package/dist/mac/folders.d.ts +28 -0
  28. package/dist/mac/folders.js +127 -0
  29. package/dist/mac/folders.js.map +1 -0
  30. package/dist/mac/index.d.ts +22 -0
  31. package/dist/mac/index.js +119 -0
  32. package/dist/mac/index.js.map +1 -0
  33. package/dist/mac/read.d.ts +46 -0
  34. package/dist/mac/read.js +406 -0
  35. package/dist/mac/read.js.map +1 -0
  36. package/dist/mac/run.d.ts +64 -0
  37. package/dist/mac/run.js +250 -0
  38. package/dist/mac/run.js.map +1 -0
  39. package/dist/mac/scripts.d.ts +137 -0
  40. package/dist/mac/scripts.js +337 -0
  41. package/dist/mac/scripts.js.map +1 -0
  42. package/dist/mac/send.d.ts +23 -0
  43. package/dist/mac/send.js +135 -0
  44. package/dist/mac/send.js.map +1 -0
  45. package/dist/mac/signatures.d.ts +4 -0
  46. package/dist/mac/signatures.js +36 -0
  47. package/dist/mac/signatures.js.map +1 -0
  48. package/dist/mac/templates.d.ts +34 -0
  49. package/dist/mac/templates.js +266 -0
  50. package/dist/mac/templates.js.map +1 -0
  51. package/dist/mail.d.ts +72 -0
  52. package/dist/mail.js +131 -0
  53. package/dist/mail.js.map +1 -0
  54. package/dist/outlookTemplateSections.d.ts +62 -0
  55. package/dist/outlookTemplateSections.js +313 -0
  56. package/dist/outlookTemplateSections.js.map +1 -0
  57. package/dist/runtime.d.ts +76 -0
  58. package/dist/runtime.js +123 -0
  59. package/dist/runtime.js.map +1 -0
  60. package/dist/shared/attachmentMatch.d.ts +32 -0
  61. package/dist/shared/attachmentMatch.js +50 -0
  62. package/dist/shared/attachmentMatch.js.map +1 -0
  63. package/dist/shared/bounceRules.d.ts +33 -0
  64. package/dist/shared/bounceRules.js +104 -0
  65. package/dist/shared/bounceRules.js.map +1 -0
  66. package/dist/shared/capabilities.d.ts +3 -0
  67. package/dist/shared/capabilities.js +9 -0
  68. package/dist/shared/capabilities.js.map +1 -0
  69. package/dist/shared/json.d.ts +11 -0
  70. package/dist/shared/json.js +45 -0
  71. package/dist/shared/json.js.map +1 -0
  72. package/dist/shared/replyBody.d.ts +49 -0
  73. package/dist/shared/replyBody.js +113 -0
  74. package/dist/shared/replyBody.js.map +1 -0
  75. package/dist/types.d.ts +365 -0
  76. package/dist/types.js +13 -0
  77. package/dist/types.js.map +1 -0
  78. package/dist/windows/accounts.d.ts +2 -0
  79. package/dist/windows/accounts.js +22 -0
  80. package/dist/windows/accounts.js.map +1 -0
  81. package/dist/windows/attachments.d.ts +28 -0
  82. package/dist/windows/attachments.js +141 -0
  83. package/dist/windows/attachments.js.map +1 -0
  84. package/dist/windows/bounces.d.ts +34 -0
  85. package/dist/windows/bounces.js +267 -0
  86. package/dist/windows/bounces.js.map +1 -0
  87. package/dist/windows/cleanup.d.ts +29 -0
  88. package/dist/windows/cleanup.js +165 -0
  89. package/dist/windows/cleanup.js.map +1 -0
  90. package/dist/windows/drafts.d.ts +29 -0
  91. package/dist/windows/drafts.js +253 -0
  92. package/dist/windows/drafts.js.map +1 -0
  93. package/dist/windows/folders.d.ts +16 -0
  94. package/dist/windows/folders.js +88 -0
  95. package/dist/windows/folders.js.map +1 -0
  96. package/dist/windows/index.d.ts +27 -0
  97. package/dist/windows/index.js +100 -0
  98. package/dist/windows/index.js.map +1 -0
  99. package/dist/windows/read.d.ts +54 -0
  100. package/dist/windows/read.js +372 -0
  101. package/dist/windows/read.js.map +1 -0
  102. package/dist/windows/run.d.ts +54 -0
  103. package/dist/windows/run.js +161 -0
  104. package/dist/windows/run.js.map +1 -0
  105. package/dist/windows/scripts.d.ts +56 -0
  106. package/dist/windows/scripts.js +163 -0
  107. package/dist/windows/scripts.js.map +1 -0
  108. package/dist/windows/send.d.ts +11 -0
  109. package/dist/windows/send.js +114 -0
  110. package/dist/windows/send.js.map +1 -0
  111. package/dist/windows/signatures.d.ts +14 -0
  112. package/dist/windows/signatures.js +69 -0
  113. package/dist/windows/signatures.js.map +1 -0
  114. package/dist/windows/templates.d.ts +25 -0
  115. package/dist/windows/templates.js +246 -0
  116. package/dist/windows/templates.js.map +1 -0
  117. package/package.json +50 -0
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanUndeliverableEmails = cleanUndeliverableEmails;
4
+ exports.collectBouncedRecipients = collectBouncedRecipients;
5
+ exports.readSentRecipientGroups = readSentRecipientGroups;
6
+ // Bounce-backs: finding them, filing them away, and mining them for the
7
+ // addresses that failed.
8
+ //
9
+ // Windows classifies inside the generated PowerShell, where Restrict has already
10
+ // narrowed the set server-side. AppleScript has no Restrict, so the folder is
11
+ // indexed with bulk property reads and the SAME rules — imported from
12
+ // shared/bounceRules — are applied here in TypeScript. Only messages that match
13
+ // have their bodies read, which is the property that keeps either version
14
+ // affordable on a real inbox.
15
+ const run_1 = require("./run");
16
+ const scripts_1 = require("./scripts");
17
+ const bounceRules_1 = require("../shared/bounceRules");
18
+ const mail_1 = require("../mail");
19
+ /**
20
+ * Index one well-known folder's messages within the window: everything the
21
+ * bounce classifier needs, and nothing that costs a per-message event.
22
+ */
23
+ async function indexFolder(emailAccount, folderTerm, days) {
24
+ // Sender is a record, and a bulk `sender of every message` read hands back a
25
+ // list of them that AppleScript then reads locally — so the whole index costs
26
+ // four Apple events rather than one per message.
27
+ const script = `tell application "Microsoft Outlook"
28
+ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
29
+ set scanFolder to ${folderTerm} of targetAcct
30
+ set idList to id of every message of scanFolder
31
+ set subjList to subject of every message of scanFolder
32
+ try
33
+ set timeList to time received of every message of scanFolder
34
+ on error
35
+ set timeList to {}
36
+ end try
37
+ try
38
+ set sndList to sender of every message of scanFolder
39
+ on error
40
+ set sndList to {}
41
+ end try
42
+ set cutoff to (current date) - (${days} * days)
43
+ set out to ""
44
+ repeat with i from 1 to (count of idList)
45
+ set stamp to missing value
46
+ if (count of timeList) is (count of idList) then set stamp to item i of timeList
47
+ if stamp is missing value or stamp is greater than or equal to cutoff then
48
+ set sndName to ""
49
+ set sndAddr to ""
50
+ if (count of sndList) is (count of idList) then
51
+ set snd to item i of sndList
52
+ try
53
+ set sndAddr to (address of snd) as string
54
+ end try
55
+ try
56
+ set sndName to (name of snd) as string
57
+ end try
58
+ end if
59
+ set out to out & ${(0, run_1.asRow)([
60
+ '(item i of idList as string)',
61
+ '(item i of subjList)',
62
+ 'sndName',
63
+ 'sndAddr',
64
+ 'my isoDate(stamp)',
65
+ ])}
66
+ end if
67
+ end repeat
68
+ return out
69
+ end tell`;
70
+ return (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000)).map(record => {
71
+ const parts = (0, run_1.splitFields)(record);
72
+ return {
73
+ id: (0, run_1.field)(parts, 0),
74
+ subject: (0, run_1.field)(parts, 1).trim(),
75
+ senderName: (0, run_1.field)(parts, 2),
76
+ senderEmail: (0, run_1.field)(parts, 3),
77
+ receivedTime: (0, run_1.field)(parts, 4),
78
+ };
79
+ });
80
+ }
81
+ /** Read the plain-text bodies of the given messages, keyed by id. */
82
+ async function readBodies(ids) {
83
+ if (ids.length === 0)
84
+ return new Map();
85
+ const script = `tell application "Microsoft Outlook"
86
+ set out to ""
87
+ repeat with theId in {${ids.join(', ')}}
88
+ set theMsg to missing value
89
+ try
90
+ set theMsg to message id theId
91
+ end try
92
+ if theMsg is not missing value then
93
+ set bodyText to ""
94
+ try
95
+ set bodyText to (plain text content of theMsg) as string
96
+ end try
97
+ set out to out & ${(0, run_1.asRow)(['(theId as string)', 'bodyText'])}
98
+ end if
99
+ end repeat
100
+ return out
101
+ end tell`;
102
+ const bodies = new Map();
103
+ for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000))) {
104
+ const parts = (0, run_1.splitFields)(record);
105
+ bodies.set((0, run_1.field)(parts, 0), (0, run_1.field)(parts, 1));
106
+ }
107
+ return bodies;
108
+ }
109
+ /** Classify an index, then fill each match's failed recipients from its body. */
110
+ async function collectBounces(indexed, accountAddress) {
111
+ const matched = indexed
112
+ .map(message => ({ message, reason: (0, bounceRules_1.bounceReason)(message) }))
113
+ .filter(entry => entry.reason !== '');
114
+ if (matched.length === 0)
115
+ return [];
116
+ const bodies = await readBodies(matched.map(entry => entry.message.id));
117
+ return matched.map(({ message, reason }) => ({
118
+ entryId: message.id,
119
+ subject: message.subject,
120
+ senderName: message.senderName,
121
+ senderEmail: message.senderEmail,
122
+ receivedTime: message.receivedTime,
123
+ matchedReason: reason,
124
+ failedRecipients: (0, bounceRules_1.failedRecipients)(bodies.get(message.id) || '', accountAddress),
125
+ }));
126
+ }
127
+ /**
128
+ * Scan an account's inbox for bounce-back / non-delivery messages — mail-daemon
129
+ * and postmaster rejections, and "Message blocked"-style failure notices — and,
130
+ * unless previewing, move each to Deleted Items (recoverable).
131
+ *
132
+ * Classification is deliberately conservative so ordinary mail that merely
133
+ * mentions "delivery" is never caught: an item matches only when its sender
134
+ * fingerprints as a mail-delivery daemon/postmaster or its subject contains a
135
+ * specific bounce phrase. macOS has no MessageClass, so the NDR-report signal
136
+ * Windows can also use is unavailable here — an Exchange NDR still matches on
137
+ * its "Undeliverable:" subject, which is what it carries.
138
+ */
139
+ async function cleanUndeliverableEmails(emailAccount, daysBack = 30, dryRun = true) {
140
+ const days = (0, mail_1.clamp)(daysBack, 1, 365);
141
+ const indexed = await indexFolder(emailAccount, 'inbox', days);
142
+ const matched = await collectBounces(indexed, emailAccount);
143
+ let deletedCount = 0;
144
+ const failed = [];
145
+ if (!dryRun && matched.length > 0) {
146
+ const script = `tell application "Microsoft Outlook"
147
+ set deletedCount to 0
148
+ set out to ""
149
+ repeat with theId in {${matched.map(m => m.entryId).join(', ')}}
150
+ set subj to ""
151
+ try
152
+ set theMsg to missing value
153
+ try
154
+ set theMsg to message id theId
155
+ end try
156
+ if theMsg is missing value then error "message is no longer in the mailbox"
157
+ try
158
+ set subj to (subject of theMsg) as string
159
+ end try
160
+ delete theMsg
161
+ set deletedCount to deletedCount + 1
162
+ on error errText
163
+ set out to out & ${(0, run_1.asRow)(['subj', 'errText'])}
164
+ end try
165
+ end repeat
166
+ return ${(0, run_1.asRow)(['(deletedCount as string)'])} & out
167
+ end tell`;
168
+ const records = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000));
169
+ deletedCount = (0, run_1.intField)((0, run_1.splitFields)(records[0] || ''), 0);
170
+ for (const record of records.slice(1)) {
171
+ const parts = (0, run_1.splitFields)(record);
172
+ failed.push({ subject: (0, run_1.field)(parts, 0), error: (0, run_1.field)(parts, 1) });
173
+ }
174
+ }
175
+ return {
176
+ account: emailAccount,
177
+ scannedDays: days,
178
+ dryRun,
179
+ matchedCount: matched.length,
180
+ deletedCount,
181
+ matched,
182
+ failed,
183
+ };
184
+ }
185
+ /**
186
+ * Read-only scan of an account's Inbox (and, when scanDeleted, its Deleted Items)
187
+ * for bounce messages, returning just the deduped set of failed recipient
188
+ * addresses. Uses the same conservative classifier as cleanUndeliverableEmails.
189
+ *
190
+ * Deleted Items is included so this still works after cleanUndeliverableEmails has
191
+ * already filed the bounces there — the blacklist step doesn't depend on running
192
+ * before the cleanup. This never deletes anything.
193
+ */
194
+ async function collectBouncedRecipients(emailAccount, daysBack = 30, scanDeleted = true) {
195
+ const days = (0, mail_1.clamp)(daysBack, 1, 365);
196
+ const terms = scanDeleted ? ['inbox', 'deleted items'] : ['inbox'];
197
+ const found = new Set();
198
+ for (const term of terms) {
199
+ const bounces = await collectBounces(await indexFolder(emailAccount, term, days), emailAccount);
200
+ for (const bounce of bounces) {
201
+ for (const address of bounce.failedRecipients)
202
+ found.add(address);
203
+ }
204
+ }
205
+ return [...found];
206
+ }
207
+ /**
208
+ * Read the account's Sent Items within the window, returning each mail with the
209
+ * full SMTP address set it was sent to (To + CC + BCC), newest first. This is how
210
+ * the "was every address for this contact tried?" question gets answered: where a
211
+ * blast sends one email per organization addressed to all of its addresses, a sent
212
+ * message's recipient set IS that organization's full address set.
213
+ */
214
+ async function readSentRecipientGroups(emailAccount, daysBack = 30, limit = 3000) {
215
+ const days = (0, mail_1.clamp)(daysBack, 1, 365);
216
+ const cap = (0, mail_1.clamp)(limit, 1, 10000);
217
+ // Pass 1 — index Sent Items on `time sent`, which is the stamp outgoing mail
218
+ // actually carries; indexing it on `time received` yields an empty set that
219
+ // looks exactly like an empty folder.
220
+ const indexScript = `tell application "Microsoft Outlook"
221
+ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
222
+ set sentFolder to sent items of targetAcct
223
+ set idList to id of every message of sentFolder
224
+ try
225
+ set timeList to time sent of every message of sentFolder
226
+ on error
227
+ set timeList to {}
228
+ end try
229
+ set subjList to subject of every message of sentFolder
230
+ set cutoff to (current date) - (${days} * days)
231
+ set out to ""
232
+ repeat with i from 1 to (count of idList)
233
+ set stamp to missing value
234
+ if (count of timeList) is (count of idList) then set stamp to item i of timeList
235
+ if stamp is missing value or stamp is greater than or equal to cutoff then
236
+ set out to out & ${(0, run_1.asRow)([
237
+ '(item i of idList as string)',
238
+ '(item i of subjList)',
239
+ 'my isoDate(stamp)',
240
+ ])}
241
+ end if
242
+ end repeat
243
+ return out
244
+ end tell`;
245
+ const indexed = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(indexScript, 300000)).map(record => {
246
+ const parts = (0, run_1.splitFields)(record);
247
+ return { id: (0, run_1.field)(parts, 0), subject: (0, run_1.field)(parts, 1).trim(), sentOn: (0, run_1.field)(parts, 2) };
248
+ });
249
+ indexed.sort((a, b) => b.sentOn.localeCompare(a.sentOn));
250
+ const chosen = indexed.slice(0, cap);
251
+ if (chosen.length === 0)
252
+ return [];
253
+ // Pass 2 — recipients, which can only be read per message.
254
+ const detailScript = `tell application "Microsoft Outlook"
255
+ set out to ""
256
+ repeat with theId in {${chosen.map(row => row.id).join(', ')}}
257
+ set theMsg to missing value
258
+ try
259
+ set theMsg to message id theId
260
+ end try
261
+ if theMsg is not missing value then
262
+ ${(0, scripts_1.allRecipientsSnippet)('theMsg', ' ')}
263
+ set out to out & ${(0, run_1.asRow)([
264
+ '(theId as string)',
265
+ 'my sanitizeList(addrList)',
266
+ ])}
267
+ end if
268
+ end repeat
269
+ return out
270
+ end tell`;
271
+ const recipientsById = new Map();
272
+ for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(detailScript, 300000))) {
273
+ const parts = (0, run_1.splitFields)(record);
274
+ recipientsById.set((0, run_1.field)(parts, 0), (0, run_1.splitList)((0, run_1.field)(parts, 1)).map(address => address.toLowerCase()));
275
+ }
276
+ const groups = [];
277
+ for (const row of chosen) {
278
+ const recipients = recipientsById.get(row.id) || [];
279
+ if (recipients.length === 0)
280
+ continue;
281
+ groups.push({ entryId: row.id, subject: row.subject, sentOn: row.sentOn, recipients });
282
+ }
283
+ return groups;
284
+ }
285
+ //# sourceMappingURL=bounces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounces.js","sourceRoot":"","sources":["../../src/mac/bounces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { DeleteMailOptions, DeleteMailResult, PurgeDeletedItemsResult } from '../types';
2
+ /**
3
+ * Delete mail by message id from anywhere in the account. `delete` files each
4
+ * item in Deleted Items, so this is recoverable — purgeDeletedItems is what
5
+ * destroys.
6
+ *
7
+ * ⚠️ This is the one tool here that can reach received mail. Three things hold
8
+ * the line, exactly as on Windows:
9
+ *
10
+ * - **Inbox and Sent Items are refused by default, INCLUDING their subfolders** —
11
+ * a filed subfolder is still received mail. `allowProtected` lifts that, and is
12
+ * the caller explicitly taking responsibility.
13
+ * - **`dryRun` resolves and reports without deleting**, so the exact subjects and
14
+ * folders can be shown to the user before anything happens. Use it first.
15
+ * - **Every outcome echoes the subject and folderPath** of the item actually
16
+ * resolved, so a wrong id is visible after the fact rather than silent.
17
+ */
18
+ export declare function deleteOutlookEmails(emailAccount: string, entryIds: string[], options?: DeleteMailOptions): Promise<DeleteMailResult>;
19
+ /**
20
+ * Permanently remove items from the account's Deleted Items folder. This is the
21
+ * ONE genuinely irreversible operation here — nothing recovers from it — which
22
+ * is why it is folder-scoped rather than keyed on a message id: it can only ever
23
+ * destroy what the user already threw away.
24
+ *
25
+ * `olderThanDays` keeps recent items (0 = purge everything). The folder is
26
+ * indexed first and destroyed by id afterwards, so deleting can't shift the
27
+ * collection out from under the walk.
28
+ */
29
+ export declare function purgeDeletedItems(emailAccount: string, olderThanDays?: number, dryRun?: boolean): Promise<PurgeDeletedItemsResult>;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteOutlookEmails = deleteOutlookEmails;
4
+ exports.purgeDeletedItems = purgeDeletedItems;
5
+ // Deleting mail, and emptying what was already deleted.
6
+ const run_1 = require("./run");
7
+ const scripts_1 = require("./scripts");
8
+ const mail_1 = require("../mail");
9
+ /**
10
+ * Walk a folder's `container` chain to the top, as the list `chainNames`
11
+ * (nearest first). Requires `theFolder`.
12
+ *
13
+ * This is what makes the Inbox/Sent Items refusal cover their SUBFOLDERS too: a
14
+ * filed subfolder is still received mail. The chain's last element is the folder
15
+ * directly under the account, and an account cannot hold two top-level folders
16
+ * of one name, so comparing that name is exact rather than a guess.
17
+ */
18
+ function folderChainSnippet(indent) {
19
+ return `${indent}set chainNames to {}
20
+ ${indent}set cur to theFolder
21
+ ${indent}set guard to 0
22
+ ${indent}repeat while cur is not missing value and guard < 25
23
+ ${indent} -- The account's own root folder has a 'name' of missing value, and coercing
24
+ ${indent} -- that yields the STRING "missing value" — which sailed past an empty
25
+ ${indent} -- check and became the chain's root, so nothing was ever recognised as
26
+ ${indent} -- living under the Inbox. Test before coercing.
27
+ ${indent} set rawName to missing value
28
+ ${indent} try
29
+ ${indent} set rawName to name of cur
30
+ ${indent} end try
31
+ ${indent} if rawName is missing value then exit repeat
32
+ ${indent} set nm to rawName as string
33
+ ${indent} if nm is "" then exit repeat
34
+ ${indent} set end of chainNames to nm
35
+ ${indent} set nextUp to missing value
36
+ ${indent} try
37
+ ${indent} set nextUp to container of cur
38
+ ${indent} end try
39
+ ${indent} set cur to nextUp
40
+ ${indent} set guard to guard + 1
41
+ ${indent}end repeat`;
42
+ }
43
+ /**
44
+ * Delete mail by message id from anywhere in the account. `delete` files each
45
+ * item in Deleted Items, so this is recoverable — purgeDeletedItems is what
46
+ * destroys.
47
+ *
48
+ * ⚠️ This is the one tool here that can reach received mail. Three things hold
49
+ * the line, exactly as on Windows:
50
+ *
51
+ * - **Inbox and Sent Items are refused by default, INCLUDING their subfolders** —
52
+ * a filed subfolder is still received mail. `allowProtected` lifts that, and is
53
+ * the caller explicitly taking responsibility.
54
+ * - **`dryRun` resolves and reports without deleting**, so the exact subjects and
55
+ * folders can be shown to the user before anything happens. Use it first.
56
+ * - **Every outcome echoes the subject and folderPath** of the item actually
57
+ * resolved, so a wrong id is visible after the fact rather than silent.
58
+ */
59
+ async function deleteOutlookEmails(emailAccount, entryIds, options = {}) {
60
+ const { allowProtected = false, dryRun = false } = options;
61
+ if (entryIds.length === 0) {
62
+ return { dryRun, deleted: 0, refused: 0, failed: 0, items: [] };
63
+ }
64
+ const { valid, invalid } = (0, scripts_1.partitionMessageIds)(entryIds);
65
+ const items = invalid.map(bad => ({
66
+ entryId: bad.entryId,
67
+ subject: '',
68
+ folderPath: '',
69
+ status: 'failed',
70
+ reason: bad.error,
71
+ }));
72
+ if (valid.length > 0) {
73
+ const script = `tell application "Microsoft Outlook"
74
+ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
75
+ set inboxName to (name of (inbox of targetAcct)) as string
76
+ set sentName to (name of (sent items of targetAcct)) as string
77
+ set out to ""
78
+ repeat with theId in {${valid.join(', ')}}
79
+ set subj to ""
80
+ set pathText to ""
81
+ try
82
+ set theMsg to missing value
83
+ try
84
+ set theMsg to message id theId
85
+ end try
86
+ if theMsg is missing value then error "no item with that message id in this Outlook"
87
+ try
88
+ set subj to (subject of theMsg) as string
89
+ end try
90
+ set theFolder to missing value
91
+ try
92
+ set theFolder to folder of theMsg
93
+ end try
94
+ if theFolder is missing value then error "item has no parent folder - refusing to delete"
95
+ ${folderChainSnippet(' ')}
96
+ set pathText to my sanitizeList(my reverseList(chainNames))
97
+ set rootName to item (count of chainNames) of chainNames
98
+ set isProtected to (rootName is inboxName) or (rootName is sentName)
99
+ if isProtected and not ${allowProtected} then
100
+ set out to out & ${(0, run_1.asRow)([
101
+ '(theId as string)',
102
+ 'subj',
103
+ 'pathText',
104
+ '"refused"',
105
+ `"${(0, run_1.asEscape)(mail_1.PROTECTED_MAIL_REASON)}"`,
106
+ ])}
107
+ else if ${dryRun} then
108
+ set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'pathText', '"would-delete"', '""'])}
109
+ else
110
+ delete theMsg
111
+ set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'pathText', '"deleted"', '""'])}
112
+ end if
113
+ on error errText
114
+ set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'pathText', '"failed"', 'errText'])}
115
+ end try
116
+ end repeat
117
+ return out
118
+ end tell
119
+
120
+ on reverseList(lst)
121
+ set out to {}
122
+ repeat with i from (count of lst) to 1 by -1
123
+ set end of out to item i of lst
124
+ end repeat
125
+ return out
126
+ end reverseList`;
127
+ for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000))) {
128
+ const parts = (0, run_1.splitFields)(record);
129
+ const segments = (0, run_1.splitList)((0, run_1.field)(parts, 2));
130
+ items.push({
131
+ entryId: (0, run_1.field)(parts, 0),
132
+ subject: (0, run_1.field)(parts, 1).trim(),
133
+ folderPath: segments.length
134
+ ? (0, scripts_1.macFolderPath)(emailAccount, segments[0], segments.slice(1))
135
+ : '',
136
+ status: ((0, run_1.field)(parts, 3) || 'failed'),
137
+ reason: (0, run_1.field)(parts, 4),
138
+ });
139
+ }
140
+ }
141
+ return {
142
+ dryRun,
143
+ deleted: items.filter(i => i.status === 'deleted').length,
144
+ refused: items.filter(i => i.status === 'refused').length,
145
+ failed: items.filter(i => i.status === 'failed').length,
146
+ items,
147
+ };
148
+ }
149
+ /**
150
+ * Permanently remove items from the account's Deleted Items folder. This is the
151
+ * ONE genuinely irreversible operation here — nothing recovers from it — which
152
+ * is why it is folder-scoped rather than keyed on a message id: it can only ever
153
+ * destroy what the user already threw away.
154
+ *
155
+ * `olderThanDays` keeps recent items (0 = purge everything). The folder is
156
+ * indexed first and destroyed by id afterwards, so deleting can't shift the
157
+ * collection out from under the walk.
158
+ */
159
+ async function purgeDeletedItems(emailAccount, olderThanDays = 0, dryRun = false) {
160
+ const days = Math.max(0, Math.floor(olderThanDays));
161
+ const folderPath = (0, scripts_1.macFolderPath)(emailAccount, 'Deleted Items', []);
162
+ const indexScript = `tell application "Microsoft Outlook"
163
+ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
164
+ set trashFolder to deleted items of targetAcct
165
+ set idList to id of every message of trashFolder
166
+ try
167
+ set timeList to time received of every message of trashFolder
168
+ on error
169
+ set timeList to {}
170
+ end try
171
+ set cutoff to (current date) - (${days} * days)
172
+ set out to ""
173
+ repeat with i from 1 to (count of idList)
174
+ set stamp to missing value
175
+ if (count of timeList) is (count of idList) then set stamp to item i of timeList
176
+ set keepIt to false
177
+ if ${days} > 0 and stamp is not missing value and stamp is greater than cutoff then set keepIt to true
178
+ set out to out & ${(0, run_1.asRow)(['(item i of idList as string)', '(keepIt as string)'])}
179
+ end repeat
180
+ return out
181
+ end tell`;
182
+ const rows = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(indexScript, 300000)).map(record => {
183
+ const parts = (0, run_1.splitFields)(record);
184
+ return { id: (0, run_1.field)(parts, 0), keep: (0, run_1.boolField)(parts, 1) };
185
+ });
186
+ const doomed = rows.filter(row => !row.keep);
187
+ const kept = rows.length - doomed.length;
188
+ if (dryRun || doomed.length === 0) {
189
+ return { folderPath, dryRun, matched: doomed.length, purged: 0, kept, failed: 0 };
190
+ }
191
+ const purgeScript = `tell application "Microsoft Outlook"
192
+ set purgedCount to 0
193
+ set failedCount to 0
194
+ repeat with theId in {${doomed.map(row => row.id).join(', ')}}
195
+ try
196
+ set theMsg to missing value
197
+ try
198
+ set theMsg to message id theId
199
+ end try
200
+ if theMsg is missing value then error "gone"
201
+ permanently delete theMsg
202
+ set purgedCount to purgedCount + 1
203
+ on error
204
+ set failedCount to failedCount + 1
205
+ end try
206
+ end repeat
207
+ return ${(0, run_1.asRow)(['(purgedCount as string)', '(failedCount as string)'])}
208
+ end tell`;
209
+ const summary = (0, run_1.summaryFields)(await (0, run_1.runOsaScript)(purgeScript, 600000));
210
+ return {
211
+ folderPath,
212
+ dryRun,
213
+ matched: doomed.length,
214
+ purged: (0, run_1.intField)(summary, 0),
215
+ kept,
216
+ failed: (0, run_1.intField)(summary, 1),
217
+ };
218
+ }
219
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/mac/cleanup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { DeleteDraftsResult, ListDraftsResult, SendAllDraftsResult } from '../types';
2
+ /**
3
+ * List the mail drafts belonging to `emailAccount`, newest first.
4
+ *
5
+ * Bodies are previewed, never returned whole — a templated reply body runs to
6
+ * tens of thousands of characters and a folder's worth would blow the cap.
7
+ */
8
+ export declare function listOutlookDrafts(emailAccount: string, limit?: number, previewChars?: number): Promise<ListDraftsResult>;
9
+ /**
10
+ * Send the mail drafts that belong to `emailAccount`.
11
+ *
12
+ * The ids are snapshotted before the first send: sending moves an item out of
13
+ * Drafts, and mutating the collection mid-enumeration would skip every other one
14
+ * — the same trap the Windows implementation avoids by snapshotting item refs.
15
+ */
16
+ export declare function sendAllDrafts(emailAccount: string): Promise<SendAllDraftsResult>;
17
+ /**
18
+ * Delete mail drafts by message id. `delete` files the item in Deleted Items
19
+ * rather than destroying it, so a mistaken call stays recoverable from there —
20
+ * matching the Windows contract.
21
+ *
22
+ * Every id must resolve to a message sitting in THIS account's Drafts folder
23
+ * before anything is deleted; an id pointing at ordinary mail, or at another
24
+ * account's draft, is refused and reported. Without that gate this would be a
25
+ * general-purpose "delete any email by id" tool, which is not what it is for.
26
+ */
27
+ export declare function deleteOutlookDrafts(emailAccount: string, entryIds: string[]): Promise<DeleteDraftsResult>;