@dawnlit/outlook-bridge 1.1.1 → 2.1.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 (142) hide show
  1. package/README.md +152 -183
  2. package/dist/backend.d.ts +151 -0
  3. package/dist/backend.js +3 -0
  4. package/dist/backend.js.map +1 -0
  5. package/dist/bridge.d.ts +56 -0
  6. package/dist/bridge.js +507 -0
  7. package/dist/bridge.js.map +1 -0
  8. package/dist/errors.d.ts +79 -43
  9. package/dist/errors.js +93 -52
  10. package/dist/errors.js.map +1 -1
  11. package/dist/index.d.ts +10 -10
  12. package/dist/index.js +25 -52
  13. package/dist/index.js.map +1 -1
  14. package/dist/mac/accounts.d.ts +7 -2
  15. package/dist/mac/accounts.js +23 -6
  16. package/dist/mac/accounts.js.map +1 -1
  17. package/dist/mac/attachments.d.ts +5 -25
  18. package/dist/mac/attachments.js +40 -99
  19. package/dist/mac/attachments.js.map +1 -1
  20. package/dist/mac/bounces.d.ts +12 -27
  21. package/dist/mac/bounces.js +96 -117
  22. package/dist/mac/bounces.js.map +1 -1
  23. package/dist/mac/cleanup.d.ts +11 -25
  24. package/dist/mac/cleanup.js +44 -107
  25. package/dist/mac/cleanup.js.map +1 -1
  26. package/dist/mac/drafts.d.ts +15 -34
  27. package/dist/mac/drafts.js +113 -186
  28. package/dist/mac/drafts.js.map +1 -1
  29. package/dist/mac/folders.d.ts +12 -21
  30. package/dist/mac/folders.js +44 -59
  31. package/dist/mac/folders.js.map +1 -1
  32. package/dist/mac/index.d.ts +2 -22
  33. package/dist/mac/index.js +19 -81
  34. package/dist/mac/index.js.map +1 -1
  35. package/dist/mac/profile.d.ts +13 -0
  36. package/dist/mac/profile.js +149 -0
  37. package/dist/mac/profile.js.map +1 -0
  38. package/dist/mac/read.d.ts +21 -37
  39. package/dist/mac/read.js +198 -216
  40. package/dist/mac/read.js.map +1 -1
  41. package/dist/mac/run.d.ts +51 -38
  42. package/dist/mac/run.js +138 -103
  43. package/dist/mac/run.js.map +1 -1
  44. package/dist/mac/scripts.d.ts +90 -91
  45. package/dist/mac/scripts.js +167 -126
  46. package/dist/mac/scripts.js.map +1 -1
  47. package/dist/mac/send.d.ts +10 -20
  48. package/dist/mac/send.js +99 -89
  49. package/dist/mac/send.js.map +1 -1
  50. package/dist/mac/signatures.d.ts +2 -2
  51. package/dist/mac/signatures.js +9 -11
  52. package/dist/mac/signatures.js.map +1 -1
  53. package/dist/mac/templates.d.ts +14 -26
  54. package/dist/mac/templates.js +79 -120
  55. package/dist/mac/templates.js.map +1 -1
  56. package/dist/mail.d.ts +80 -46
  57. package/dist/mail.js +179 -73
  58. package/dist/mail.js.map +1 -1
  59. package/dist/runtime.d.ts +76 -43
  60. package/dist/runtime.js +103 -48
  61. package/dist/runtime.js.map +1 -1
  62. package/dist/shared/args.d.ts +48 -0
  63. package/dist/shared/args.js +216 -0
  64. package/dist/shared/args.js.map +1 -0
  65. package/dist/shared/attachmentMatch.d.ts +26 -20
  66. package/dist/shared/attachmentMatch.js +60 -23
  67. package/dist/shared/attachmentMatch.js.map +1 -1
  68. package/dist/shared/bounceReport.d.ts +11 -0
  69. package/dist/shared/bounceReport.js +45 -0
  70. package/dist/shared/bounceReport.js.map +1 -0
  71. package/dist/shared/bounceRules.d.ts +38 -10
  72. package/dist/shared/bounceRules.js +50 -32
  73. package/dist/shared/bounceRules.js.map +1 -1
  74. package/dist/shared/exec.d.ts +21 -0
  75. package/dist/shared/exec.js +47 -0
  76. package/dist/shared/exec.js.map +1 -0
  77. package/dist/shared/json.d.ts +17 -6
  78. package/dist/shared/json.js +35 -24
  79. package/dist/shared/json.js.map +1 -1
  80. package/dist/shared/locate.d.ts +31 -0
  81. package/dist/shared/locate.js +128 -0
  82. package/dist/shared/locate.js.map +1 -0
  83. package/dist/shared/replyBody.d.ts +31 -36
  84. package/dist/shared/replyBody.js +83 -72
  85. package/dist/shared/replyBody.js.map +1 -1
  86. package/dist/shared/templateLimits.d.ts +14 -0
  87. package/dist/shared/templateLimits.js +21 -0
  88. package/dist/shared/templateLimits.js.map +1 -0
  89. package/dist/templateBody.d.ts +69 -0
  90. package/dist/{outlookTemplateSections.js → templateBody.js} +80 -73
  91. package/dist/templateBody.js.map +1 -0
  92. package/dist/types.d.ts +381 -168
  93. package/dist/types.js +8 -9
  94. package/dist/types.js.map +1 -1
  95. package/dist/windows/accounts.d.ts +7 -12
  96. package/dist/windows/accounts.js +19 -34
  97. package/dist/windows/accounts.js.map +1 -1
  98. package/dist/windows/attachments.d.ts +9 -24
  99. package/dist/windows/attachments.js +94 -119
  100. package/dist/windows/attachments.js.map +1 -1
  101. package/dist/windows/bounces.d.ts +13 -26
  102. package/dist/windows/bounces.js +168 -200
  103. package/dist/windows/bounces.js.map +1 -1
  104. package/dist/windows/cleanup.d.ts +23 -23
  105. package/dist/windows/cleanup.js +99 -113
  106. package/dist/windows/cleanup.js.map +1 -1
  107. package/dist/windows/drafts.d.ts +16 -35
  108. package/dist/windows/drafts.js +156 -253
  109. package/dist/windows/drafts.js.map +1 -1
  110. package/dist/windows/folders.d.ts +8 -13
  111. package/dist/windows/folders.js +44 -52
  112. package/dist/windows/folders.js.map +1 -1
  113. package/dist/windows/index.d.ts +2 -27
  114. package/dist/windows/index.js +11 -66
  115. package/dist/windows/index.js.map +1 -1
  116. package/dist/windows/read.d.ts +24 -60
  117. package/dist/windows/read.js +265 -306
  118. package/dist/windows/read.js.map +1 -1
  119. package/dist/windows/run.d.ts +38 -40
  120. package/dist/windows/run.js +151 -112
  121. package/dist/windows/run.js.map +1 -1
  122. package/dist/windows/scripts.d.ts +65 -55
  123. package/dist/windows/scripts.js +109 -85
  124. package/dist/windows/scripts.js.map +1 -1
  125. package/dist/windows/send.d.ts +9 -9
  126. package/dist/windows/send.js +76 -88
  127. package/dist/windows/send.js.map +1 -1
  128. package/dist/windows/signatures.d.ts +4 -10
  129. package/dist/windows/signatures.js +30 -37
  130. package/dist/windows/signatures.js.map +1 -1
  131. package/dist/windows/templates.d.ts +12 -18
  132. package/dist/windows/templates.js +117 -150
  133. package/dist/windows/templates.js.map +1 -1
  134. package/package.json +5 -4
  135. package/dist/OutlookService.d.ts +0 -43
  136. package/dist/OutlookService.js +0 -137
  137. package/dist/OutlookService.js.map +0 -1
  138. package/dist/outlookTemplateSections.d.ts +0 -62
  139. package/dist/outlookTemplateSections.js.map +0 -1
  140. package/dist/shared/capabilities.d.ts +0 -3
  141. package/dist/shared/capabilities.js +0 -9
  142. package/dist/shared/capabilities.js.map +0 -1
@@ -7,61 +7,13 @@ const run_1 = require("./run");
7
7
  const scripts_1 = require("./scripts");
8
8
  const mail_1 = require("../mail");
9
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.
10
+ * Delete mail by message id from anywhere in the account, into Deleted Items.
11
+ * Inbox and Sent Items (and their subfolders) are refused unless
12
+ * `allowProtected`; `dryRun` reports without deleting; every outcome names the
13
+ * subject and folder of the item that actually resolved.
17
14
  */
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);
15
+ async function deleteOutlookEmails(request) {
16
+ const { valid, invalid } = (0, scripts_1.partitionMessageIds)(request.entryIds);
65
17
  const items = invalid.map(bad => ({
66
18
  entryId: bad.entryId,
67
19
  subject: '',
@@ -70,12 +22,15 @@ async function deleteOutlookEmails(emailAccount, entryIds, options = {}) {
70
22
  reason: bad.error,
71
23
  }));
72
24
  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
25
+ const acct = await (0, scripts_1.resolveMacAccount)(request.account);
26
+ const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
27
+ ${(0, scripts_1.accountLookupSnippet)(acct)}
28
+ ${(0, scripts_1.rootFolderSnippet)(acct, 'inbox', 'inboxFolder')}
29
+ ${(0, scripts_1.rootFolderSnippet)(acct, 'sent items', 'sentFolder')}
30
+ set inboxName to (name of inboxFolder) as string
31
+ set sentName to (name of sentFolder) as string
77
32
  set out to ""
78
- repeat with theId in {${valid.join(', ')}}
33
+ repeat with theId in ${(0, run_1.asIdList)(valid)}
79
34
  set subj to ""
80
35
  set pathText to ""
81
36
  try
@@ -92,19 +47,14 @@ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
92
47
  set theFolder to folder of theMsg
93
48
  end try
94
49
  if theFolder is missing value then error "item has no parent folder - refusing to delete"
95
- ${folderChainSnippet(' ')}
50
+ ${(0, scripts_1.folderChainSnippet)(' ')}
96
51
  set pathText to my sanitizeList(my reverseList(chainNames))
52
+ -- The chain's top is what extends the refusal to Inbox and Sent Items SUBFOLDERS.
97
53
  set rootName to item (count of chainNames) of chainNames
98
54
  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
55
+ if isProtected and not ${(0, run_1.asBool)(request.allowProtected)} then
56
+ set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'pathText', '"refused"', (0, run_1.asString)(mail_1.PROTECTED_MAIL_REASON)])}
57
+ else if ${(0, run_1.asBool)(request.dryRun)} then
108
58
  set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'pathText', '"would-delete"', '""'])}
109
59
  else
110
60
  delete theMsg
@@ -123,75 +73,63 @@ on reverseList(lst)
123
73
  set end of out to item i of lst
124
74
  end repeat
125
75
  return out
126
- end reverseList`;
127
- for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000))) {
76
+ end reverseList`, 'scan');
77
+ for (const record of (0, run_1.splitRecords)(raw)) {
128
78
  const parts = (0, run_1.splitFields)(record);
129
79
  const segments = (0, run_1.splitList)((0, run_1.field)(parts, 2));
130
80
  items.push({
131
81
  entryId: (0, run_1.field)(parts, 0),
132
82
  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'),
83
+ folderPath: segments.length ? (0, scripts_1.macFolderPath)(request.account, segments[0], segments.slice(1)) : '',
84
+ status: (0, mail_1.deleteStatus)((0, run_1.field)(parts, 3)),
137
85
  reason: (0, run_1.field)(parts, 4),
138
86
  });
139
87
  }
140
88
  }
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
- };
89
+ return (0, mail_1.deleteMailResult)(request.dryRun, items);
148
90
  }
149
91
  /**
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.
92
+ * Permanently remove items from the account's Deleted Items. The folder is
93
+ * indexed first and items destroyed by id afterwards, so deleting can't shift
94
+ * the collection out from under the walk.
158
95
  */
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
96
+ async function purgeDeletedItems(request) {
97
+ const folderPath = (0, scripts_1.macFolderPath)(request.account, 'Deleted Items', []);
98
+ const acct = await (0, scripts_1.resolveMacAccount)(request.account);
99
+ const index = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
100
+ ${(0, scripts_1.accountLookupSnippet)(acct)}
101
+ ${(0, scripts_1.rootFolderSnippet)(acct, 'deleted items', 'trashFolder')}
165
102
  set idList to id of every message of trashFolder
166
103
  try
167
104
  set timeList to time received of every message of trashFolder
168
105
  on error
169
106
  set timeList to {}
170
107
  end try
171
- set cutoff to (current date) - (${days} * days)
108
+ set olderThanDays to ${(0, run_1.asInt)(request.olderThanDays)}
109
+ set cutoff to (current date) - (olderThanDays * days)
172
110
  set out to ""
173
111
  repeat with i from 1 to (count of idList)
174
112
  set stamp to missing value
175
113
  if (count of timeList) is (count of idList) then set stamp to item i of timeList
176
114
  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
115
+ if olderThanDays > 0 and stamp is not missing value and stamp is greater than cutoff then set keepIt to true
178
116
  set out to out & ${(0, run_1.asRow)(['(item i of idList as string)', '(keepIt as string)'])}
179
117
  end repeat
180
118
  return out
181
- end tell`;
182
- const rows = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(indexScript, 300000)).map(record => {
119
+ end tell`, 'scan');
120
+ const rows = (0, run_1.splitRecords)(index).map(record => {
183
121
  const parts = (0, run_1.splitFields)(record);
184
122
  return { id: (0, run_1.field)(parts, 0), keep: (0, run_1.boolField)(parts, 1) };
185
123
  });
186
124
  const doomed = rows.filter(row => !row.keep);
187
125
  const kept = rows.length - doomed.length;
188
- if (dryRun || doomed.length === 0) {
189
- return { folderPath, dryRun, matched: doomed.length, purged: 0, kept, failed: 0 };
126
+ if (request.dryRun || doomed.length === 0) {
127
+ return { folderPath, dryRun: request.dryRun, matched: doomed.length, purged: 0, kept, failed: 0 };
190
128
  }
191
- const purgeScript = `tell application "Microsoft Outlook"
129
+ const summary = (0, run_1.summaryFields)(await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
192
130
  set purgedCount to 0
193
131
  set failedCount to 0
194
- repeat with theId in {${doomed.map(row => row.id).join(', ')}}
132
+ repeat with theId in ${(0, run_1.asIdList)(doomed.map(row => row.id))}
195
133
  try
196
134
  set theMsg to missing value
197
135
  try
@@ -205,11 +143,10 @@ end tell`;
205
143
  end try
206
144
  end repeat
207
145
  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));
146
+ end tell`, 'purge'));
210
147
  return {
211
148
  folderPath,
212
- dryRun,
149
+ dryRun: request.dryRun,
213
150
  matched: doomed.length,
214
151
  purged: (0, run_1.intField)(summary, 0),
215
152
  kept,
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/mac/cleanup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/mac/cleanup.ts"],"names":[],"mappings":"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","sourcesContent":["// Deleting mail, and emptying what was already deleted.\nimport {\n asBool,\n asIdList,\n asInt,\n asRow,\n asString,\n boolField,\n field,\n intField,\n runOsaScript,\n splitFields,\n splitList,\n splitRecords,\n summaryFields,\n} from './run';\nimport {\n accountLookupSnippet,\n folderChainSnippet,\n macFolderPath,\n partitionMessageIds,\n resolveMacAccount,\n rootFolderSnippet,\n} from './scripts';\nimport { deleteMailResult, deleteStatus, PROTECTED_MAIL_REASON } from '../mail';\nimport type { DeleteEmailsRequest, PurgeRequest } from '../backend';\nimport type { DeleteMailOutcome, DeleteMailResult, PurgeDeletedItemsResult } from '../types';\n\n/**\n * Delete mail by message id from anywhere in the account, into Deleted Items.\n * Inbox and Sent Items (and their subfolders) are refused unless\n * `allowProtected`; `dryRun` reports without deleting; every outcome names the\n * subject and folder of the item that actually resolved.\n */\nexport async function deleteOutlookEmails(request: DeleteEmailsRequest): Promise<DeleteMailResult> {\n const { valid, invalid } = partitionMessageIds(request.entryIds);\n const items: DeleteMailOutcome[] = invalid.map(bad => ({\n entryId: bad.entryId,\n subject: '',\n folderPath: '',\n status: 'failed',\n reason: bad.error,\n }));\n if (valid.length > 0) {\n const acct = await resolveMacAccount(request.account);\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct)}\n${rootFolderSnippet(acct, 'inbox', 'inboxFolder')}\n${rootFolderSnippet(acct, 'sent items', 'sentFolder')}\n set inboxName to (name of inboxFolder) as string\n set sentName to (name of sentFolder) as string\n set out to \"\"\n repeat with theId in ${asIdList(valid)}\n set subj to \"\"\n set pathText to \"\"\n try\n set theMsg to missing value\n try\n set theMsg to message id theId\n end try\n if theMsg is missing value then error \"no item with that message id in this Outlook\"\n try\n set subj to (subject of theMsg) as string\n end try\n set theFolder to missing value\n try\n set theFolder to folder of theMsg\n end try\n if theFolder is missing value then error \"item has no parent folder - refusing to delete\"\n${folderChainSnippet(' ')}\n set pathText to my sanitizeList(my reverseList(chainNames))\n -- The chain's top is what extends the refusal to Inbox and Sent Items SUBFOLDERS.\n set rootName to item (count of chainNames) of chainNames\n set isProtected to (rootName is inboxName) or (rootName is sentName)\n if isProtected and not ${asBool(request.allowProtected)} then\n set out to out & ${asRow(['(theId as string)', 'subj', 'pathText', '\"refused\"', asString(PROTECTED_MAIL_REASON)])}\n else if ${asBool(request.dryRun)} then\n set out to out & ${asRow(['(theId as string)', 'subj', 'pathText', '\"would-delete\"', '\"\"'])}\n else\n delete theMsg\n set out to out & ${asRow(['(theId as string)', 'subj', 'pathText', '\"deleted\"', '\"\"'])}\n end if\n on error errText\n set out to out & ${asRow(['(theId as string)', 'subj', 'pathText', '\"failed\"', 'errText'])}\n end try\n end repeat\n return out\nend tell\n\non reverseList(lst)\n set out to {}\n repeat with i from (count of lst) to 1 by -1\n set end of out to item i of lst\n end repeat\n return out\nend reverseList`, 'scan');\n\n for (const record of splitRecords(raw)) {\n const parts = splitFields(record);\n const segments = splitList(field(parts, 2));\n items.push({\n entryId: field(parts, 0),\n subject: field(parts, 1).trim(),\n folderPath: segments.length ? macFolderPath(request.account, segments[0], segments.slice(1)) : '',\n status: deleteStatus(field(parts, 3)),\n reason: field(parts, 4),\n });\n }\n }\n return deleteMailResult(request.dryRun, items);\n}\n\n/**\n * Permanently remove items from the account's Deleted Items. The folder is\n * indexed first and items destroyed by id afterwards, so deleting can't shift\n * the collection out from under the walk.\n */\nexport async function purgeDeletedItems(request: PurgeRequest): Promise<PurgeDeletedItemsResult> {\n const folderPath = macFolderPath(request.account, 'Deleted Items', []);\n const acct = await resolveMacAccount(request.account);\n const index = await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct)}\n${rootFolderSnippet(acct, 'deleted items', 'trashFolder')}\n set idList to id of every message of trashFolder\n try\n set timeList to time received of every message of trashFolder\n on error\n set timeList to {}\n end try\n set olderThanDays to ${asInt(request.olderThanDays)}\n set cutoff to (current date) - (olderThanDays * days)\n set out to \"\"\n repeat with i from 1 to (count of idList)\n set stamp to missing value\n if (count of timeList) is (count of idList) then set stamp to item i of timeList\n set keepIt to false\n if olderThanDays > 0 and stamp is not missing value and stamp is greater than cutoff then set keepIt to true\n set out to out & ${asRow(['(item i of idList as string)', '(keepIt as string)'])}\n end repeat\n return out\nend tell`, 'scan');\n\n const rows = splitRecords(index).map(record => {\n const parts = splitFields(record);\n return { id: field(parts, 0), keep: boolField(parts, 1) };\n });\n const doomed = rows.filter(row => !row.keep);\n const kept = rows.length - doomed.length;\n if (request.dryRun || doomed.length === 0) {\n return { folderPath, dryRun: request.dryRun, matched: doomed.length, purged: 0, kept, failed: 0 };\n }\n\n const summary = summaryFields(await runOsaScript(`tell application \"Microsoft Outlook\"\n set purgedCount to 0\n set failedCount to 0\n repeat with theId in ${asIdList(doomed.map(row => row.id))}\n try\n set theMsg to missing value\n try\n set theMsg to message id theId\n end try\n if theMsg is missing value then error \"gone\"\n permanently delete theMsg\n set purgedCount to purgedCount + 1\n on error\n set failedCount to failedCount + 1\n end try\n end repeat\n return ${asRow(['(purgedCount as string)', '(failedCount as string)'])}\nend tell`, 'purge'));\n return {\n folderPath,\n dryRun: request.dryRun,\n matched: doomed.length,\n purged: intField(summary, 0),\n kept,\n failed: intField(summary, 1),\n };\n}\n"]}
@@ -1,38 +1,19 @@
1
- import type { DeleteDraftsResult, ListDraftsResult, SendAllDraftsResult, SendDraftsResult } from '../types';
1
+ import type { AccountRequest, EntryIdsRequest, ListDraftsRequest } from '../backend';
2
+ import type { DeleteDraftsResult, ListDraftsResult, SendDraftsResult } from '../types';
3
+ /** The account's drafts, newest first. Bodies are previewed, never returned whole. */
4
+ export declare function listOutlookDrafts(request: ListDraftsRequest): Promise<ListDraftsResult>;
5
+ /** Send the named drafts. */
6
+ export declare function sendDrafts(request: EntryIdsRequest): Promise<SendDraftsResult>;
2
7
  /**
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.
8
+ * Delete the named drafts. `delete` files an item in Deleted Items, so a
9
+ * mistaken call stays recoverable.
7
10
  */
8
- export declare function listOutlookDrafts(emailAccount: string, limit?: number, previewChars?: number): Promise<ListDraftsResult>;
11
+ export declare function deleteOutlookDrafts(request: EntryIdsRequest): Promise<DeleteDraftsResult>;
9
12
  /**
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.
13
+ * Send every draft belonging to the account. The ids are snapshotted before the
14
+ * first send: sending moves an item out of Drafts, and mutating the collection
15
+ * mid-enumeration would skip every other one. A draft in the folder that is set
16
+ * to send from another account is not this account's, so it is skipped, as on
17
+ * Windows, rather than sent from that account.
15
18
  */
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>;
28
- /**
29
- * Send a chosen subset of `emailAccount`'s drafts by message id — e.g. after
30
- * `listOutlookDrafts` and a user review pass — instead of `sendAllDrafts`'s
31
- * account-wide sweep.
32
- *
33
- * Same ownership gate as `deleteOutlookDrafts`: every id must resolve to a
34
- * message sitting in THIS account's Drafts folder before anything is sent. An
35
- * id pointing at ordinary mail, or at another account's draft, is refused and
36
- * reported rather than sent.
37
- */
38
- export declare function sendDrafts(emailAccount: string, entryIds: string[]): Promise<SendDraftsResult>;
19
+ export declare function sendAllDrafts(request: AccountRequest): Promise<SendDraftsResult>;