@dawnlit/outlook-bridge 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -183
- package/dist/backend.d.ts +151 -0
- package/dist/backend.js +3 -0
- package/dist/backend.js.map +1 -0
- package/dist/bridge.d.ts +56 -0
- package/dist/bridge.js +507 -0
- package/dist/bridge.js.map +1 -0
- package/dist/errors.d.ts +81 -43
- package/dist/errors.js +98 -52
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +25 -52
- package/dist/index.js.map +1 -1
- package/dist/mac/accounts.d.ts +7 -2
- package/dist/mac/accounts.js +23 -6
- package/dist/mac/accounts.js.map +1 -1
- package/dist/mac/attachments.d.ts +5 -25
- package/dist/mac/attachments.js +40 -99
- package/dist/mac/attachments.js.map +1 -1
- package/dist/mac/bounces.d.ts +12 -27
- package/dist/mac/bounces.js +95 -112
- package/dist/mac/bounces.js.map +1 -1
- package/dist/mac/cleanup.d.ts +11 -25
- package/dist/mac/cleanup.js +50 -76
- package/dist/mac/cleanup.js.map +1 -1
- package/dist/mac/drafts.d.ts +13 -34
- package/dist/mac/drafts.js +95 -169
- package/dist/mac/drafts.js.map +1 -1
- package/dist/mac/folders.d.ts +10 -21
- package/dist/mac/folders.js +33 -47
- package/dist/mac/folders.js.map +1 -1
- package/dist/mac/index.d.ts +2 -22
- package/dist/mac/index.js +19 -81
- package/dist/mac/index.js.map +1 -1
- package/dist/mac/profile.d.ts +13 -0
- package/dist/mac/profile.js +149 -0
- package/dist/mac/profile.js.map +1 -0
- package/dist/mac/read.d.ts +18 -38
- package/dist/mac/read.js +154 -210
- package/dist/mac/read.js.map +1 -1
- package/dist/mac/run.d.ts +35 -39
- package/dist/mac/run.js +97 -102
- package/dist/mac/run.js.map +1 -1
- package/dist/mac/scripts.d.ts +78 -86
- package/dist/mac/scripts.js +125 -115
- package/dist/mac/scripts.js.map +1 -1
- package/dist/mac/send.d.ts +10 -20
- package/dist/mac/send.js +64 -86
- package/dist/mac/send.js.map +1 -1
- package/dist/mac/signatures.d.ts +2 -2
- package/dist/mac/signatures.js +9 -11
- package/dist/mac/signatures.js.map +1 -1
- package/dist/mac/templates.d.ts +14 -26
- package/dist/mac/templates.js +75 -113
- package/dist/mac/templates.js.map +1 -1
- package/dist/mail.d.ts +77 -45
- package/dist/mail.js +166 -73
- package/dist/mail.js.map +1 -1
- package/dist/runtime.d.ts +76 -43
- package/dist/runtime.js +103 -48
- package/dist/runtime.js.map +1 -1
- package/dist/shared/args.d.ts +48 -0
- package/dist/shared/args.js +216 -0
- package/dist/shared/args.js.map +1 -0
- package/dist/shared/attachmentMatch.d.ts +28 -16
- package/dist/shared/attachmentMatch.js +60 -22
- package/dist/shared/attachmentMatch.js.map +1 -1
- package/dist/shared/bounceReport.d.ts +11 -0
- package/dist/shared/bounceReport.js +45 -0
- package/dist/shared/bounceReport.js.map +1 -0
- package/dist/shared/bounceRules.d.ts +38 -10
- package/dist/shared/bounceRules.js +50 -32
- package/dist/shared/bounceRules.js.map +1 -1
- package/dist/shared/exec.d.ts +21 -0
- package/dist/shared/exec.js +47 -0
- package/dist/shared/exec.js.map +1 -0
- package/dist/shared/json.d.ts +12 -6
- package/dist/shared/json.js +29 -23
- package/dist/shared/json.js.map +1 -1
- package/dist/shared/locate.d.ts +39 -0
- package/dist/shared/locate.js +129 -0
- package/dist/shared/locate.js.map +1 -0
- package/dist/shared/replyBody.d.ts +42 -32
- package/dist/shared/replyBody.js +84 -71
- package/dist/shared/replyBody.js.map +1 -1
- package/dist/templateBody.d.ts +63 -0
- package/dist/{outlookTemplateSections.js → templateBody.js} +72 -72
- package/dist/templateBody.js.map +1 -0
- package/dist/types.d.ts +360 -167
- package/dist/types.js +8 -9
- package/dist/types.js.map +1 -1
- package/dist/windows/accounts.d.ts +7 -12
- package/dist/windows/accounts.js +19 -34
- package/dist/windows/accounts.js.map +1 -1
- package/dist/windows/attachments.d.ts +9 -24
- package/dist/windows/attachments.js +94 -119
- package/dist/windows/attachments.js.map +1 -1
- package/dist/windows/bounces.d.ts +13 -26
- package/dist/windows/bounces.js +168 -200
- package/dist/windows/bounces.js.map +1 -1
- package/dist/windows/cleanup.d.ts +19 -23
- package/dist/windows/cleanup.js +92 -111
- package/dist/windows/cleanup.js.map +1 -1
- package/dist/windows/drafts.d.ts +16 -35
- package/dist/windows/drafts.js +167 -253
- package/dist/windows/drafts.js.map +1 -1
- package/dist/windows/folders.d.ts +8 -13
- package/dist/windows/folders.js +44 -52
- package/dist/windows/folders.js.map +1 -1
- package/dist/windows/index.d.ts +2 -27
- package/dist/windows/index.js +11 -66
- package/dist/windows/index.js.map +1 -1
- package/dist/windows/read.d.ts +24 -60
- package/dist/windows/read.js +261 -306
- package/dist/windows/read.js.map +1 -1
- package/dist/windows/run.d.ts +39 -39
- package/dist/windows/run.js +151 -111
- package/dist/windows/run.js.map +1 -1
- package/dist/windows/scripts.d.ts +65 -55
- package/dist/windows/scripts.js +109 -85
- package/dist/windows/scripts.js.map +1 -1
- package/dist/windows/send.d.ts +6 -11
- package/dist/windows/send.js +68 -88
- package/dist/windows/send.js.map +1 -1
- package/dist/windows/signatures.d.ts +4 -10
- package/dist/windows/signatures.js +30 -37
- package/dist/windows/signatures.js.map +1 -1
- package/dist/windows/templates.d.ts +12 -18
- package/dist/windows/templates.js +122 -149
- package/dist/windows/templates.js.map +1 -1
- package/package.json +4 -3
- package/dist/OutlookService.d.ts +0 -43
- package/dist/OutlookService.js +0 -137
- package/dist/OutlookService.js.map +0 -1
- package/dist/outlookTemplateSections.d.ts +0 -62
- package/dist/outlookTemplateSections.js.map +0 -1
- package/dist/shared/capabilities.d.ts +0 -3
- package/dist/shared/capabilities.js +0 -9
- package/dist/shared/capabilities.js.map +0 -1
package/dist/windows/cleanup.js
CHANGED
|
@@ -7,160 +7,141 @@ const run_1 = require("./run");
|
|
|
7
7
|
const scripts_1 = require("./scripts");
|
|
8
8
|
const json_1 = require("../shared/json");
|
|
9
9
|
const mail_1 = require("../mail");
|
|
10
|
-
/** Folders whose contents are received or
|
|
11
|
-
const PROTECTED_FOLDER_IDS = [
|
|
12
|
-
|
|
13
|
-
const FOLDER_CHAIN_PS = `
|
|
14
|
-
function Get-FolderChainIds($folder) {
|
|
15
|
-
$ids = @()
|
|
16
|
-
$cur = $folder
|
|
17
|
-
$guard = 0
|
|
18
|
-
while ($cur -ne $null -and $guard -lt 25) {
|
|
19
|
-
$cid = $null
|
|
20
|
-
try { $cid = $cur.EntryID } catch { $cid = $null }
|
|
21
|
-
if (-not $cid) { break }
|
|
22
|
-
$ids += $cid
|
|
23
|
-
$parent = $null
|
|
24
|
-
try { $parent = $cur.Parent } catch { $parent = $null }
|
|
25
|
-
if ($parent -eq $null) { break }
|
|
26
|
-
$cur = $parent
|
|
27
|
-
$guard++
|
|
28
|
-
}
|
|
29
|
-
return $ids
|
|
30
|
-
}
|
|
31
|
-
`;
|
|
10
|
+
/** Folders whose contents are received or sent mail rather than working state. */
|
|
11
|
+
const PROTECTED_FOLDER_IDS = [mail_1.FolderId.Inbox, mail_1.FolderId.SentMail];
|
|
12
|
+
const OUTCOME_STATUSES = ['deleted', 'would-delete', 'refused', 'failed'];
|
|
32
13
|
/**
|
|
33
|
-
* Delete mail by
|
|
34
|
-
* Deleted Items, so this is recoverable — purgeDeletedItems is what destroys.
|
|
14
|
+
* Delete mail by entry id from anywhere in the account. Delete() moves each item
|
|
15
|
+
* to Deleted Items, so this is recoverable — purgeDeletedItems is what destroys.
|
|
35
16
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* -
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* - **`dryRun` resolves and reports without deleting**, so the exact subjects and
|
|
45
|
-
* folders can be shown to the user before anything happens. Use it first.
|
|
46
|
-
* - **Every outcome echoes the subject and folderPath** of the item actually
|
|
47
|
-
* resolved, so a wrong id is visible after the fact rather than silent.
|
|
17
|
+
* This is the one operation that can reach received mail, and an entry id is an
|
|
18
|
+
* unsafe key for it: a stale or wrong id can resolve to a DIFFERENT message.
|
|
19
|
+
* Three things hold the line:
|
|
20
|
+
* - Inbox and Sent Items are refused, INCLUDING their subfolders (a filed
|
|
21
|
+
* folder is still received mail), unless `allowProtected`.
|
|
22
|
+
* - `dryRun` resolves and reports without deleting, so the exact subjects and
|
|
23
|
+
* folders can be checked before anything happens.
|
|
24
|
+
* - Every outcome echoes the subject and folder of the item actually resolved.
|
|
48
25
|
*/
|
|
49
|
-
async function deleteOutlookEmails(
|
|
50
|
-
(0, run_1.
|
|
51
|
-
const { allowProtected = false, dryRun = false } = options;
|
|
52
|
-
if (entryIds.length === 0) {
|
|
53
|
-
return { dryRun, deleted: 0, refused: 0, failed: 0, items: [] };
|
|
54
|
-
}
|
|
55
|
-
const script = `${(0, scripts_1.accountScript)(emailAccount)}
|
|
26
|
+
async function deleteOutlookEmails(request) {
|
|
27
|
+
const output = await (0, run_1.runPowerShellJson)(`${(0, scripts_1.accountScript)(request.account)}
|
|
56
28
|
${scripts_1.DELIVERY_STORE_PS}
|
|
57
|
-
${
|
|
29
|
+
$allowProtected = ${(0, run_1.psBool)(request.allowProtected)}
|
|
30
|
+
$dryRun = ${(0, run_1.psBool)(request.dryRun)}
|
|
31
|
+
$protectedReason = ${(0, run_1.psString)(mail_1.PROTECTED_MAIL_REASON)}
|
|
58
32
|
$protectedIds = @{}
|
|
59
|
-
foreach ($
|
|
60
|
-
try { $protectedIds[$store.GetDefaultFolder($
|
|
33
|
+
foreach ($role in @(${PROTECTED_FOLDER_IDS.map(run_1.psInt).join(', ')})) {
|
|
34
|
+
try { $protectedIds[[string]$store.GetDefaultFolder($role).EntryID] = $true } catch {}
|
|
35
|
+
}
|
|
36
|
+
function Test-UnderProtectedFolder($folder) {
|
|
37
|
+
$current = $folder
|
|
38
|
+
for ($guard = 0; $current -ne $null -and $guard -lt 25; $guard++) {
|
|
39
|
+
$folderId = $null
|
|
40
|
+
try { $folderId = [string]$current.EntryID } catch {}
|
|
41
|
+
if (-not $folderId) { return $false }
|
|
42
|
+
if ($protectedIds.ContainsKey($folderId)) { return $true }
|
|
43
|
+
$parent = $null
|
|
44
|
+
try { $parent = $current.Parent } catch {}
|
|
45
|
+
$current = $parent
|
|
46
|
+
}
|
|
47
|
+
return $false
|
|
61
48
|
}
|
|
62
|
-
|
|
63
49
|
$items = @()
|
|
64
|
-
$
|
|
65
|
-
$refused = 0
|
|
66
|
-
$failed = 0
|
|
67
|
-
foreach ($id in @(${(0, run_1.psList)(entryIds)})) {
|
|
50
|
+
foreach ($id in ${(0, run_1.psArray)(request.entryIds)}) {
|
|
68
51
|
$subject = ''
|
|
69
52
|
$folderPath = ''
|
|
70
53
|
try {
|
|
71
54
|
$it = $null
|
|
72
55
|
try { $it = $ns.GetItemFromID($id, $store.StoreID) } catch { $it = $null }
|
|
73
56
|
if ($it -eq $null) { try { $it = $ns.GetItemFromID($id) } catch { $it = $null } }
|
|
74
|
-
if ($it -eq $null) { throw "no item with that
|
|
75
|
-
try { $subject = $it.Subject } catch {}
|
|
57
|
+
if ($it -eq $null) { throw "no item with that entry id in this account" }
|
|
58
|
+
try { $subject = [string]$it.Subject } catch {}
|
|
76
59
|
$parent = $null
|
|
77
60
|
try { $parent = $it.Parent } catch {}
|
|
78
61
|
if ($parent -eq $null) { throw "item has no parent folder - refusing to delete" }
|
|
79
|
-
try { $folderPath = $parent.FolderPath } catch {}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if ($isProtected -and -not ${(0, run_1.psBool)(allowProtected)}) {
|
|
86
|
-
$refused++
|
|
87
|
-
$items += [pscustomobject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'refused'; reason = '${(0, run_1.psEscape)(mail_1.PROTECTED_MAIL_REASON)}' }
|
|
88
|
-
} elseif (${(0, run_1.psBool)(dryRun)}) {
|
|
89
|
-
$items += [pscustomobject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'would-delete'; reason = '' }
|
|
62
|
+
try { $folderPath = [string]$parent.FolderPath } catch {}
|
|
63
|
+
if ((Test-UnderProtectedFolder $parent) -and -not $allowProtected) {
|
|
64
|
+
$items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'refused'; reason = $protectedReason }
|
|
65
|
+
} elseif ($dryRun) {
|
|
66
|
+
$items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'would-delete'; reason = '' }
|
|
90
67
|
} else {
|
|
91
68
|
$it.Delete()
|
|
92
|
-
$deleted
|
|
93
|
-
$items += [pscustomobject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'deleted'; reason = '' }
|
|
69
|
+
$items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'deleted'; reason = '' }
|
|
94
70
|
}
|
|
95
71
|
} catch {
|
|
96
|
-
$failed
|
|
97
|
-
$items += [pscustomobject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'failed'; reason = $_.Exception.Message }
|
|
72
|
+
$items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'failed'; reason = $_.Exception.Message }
|
|
98
73
|
}
|
|
99
74
|
}
|
|
100
|
-
ConvertTo-Json
|
|
101
|
-
|
|
102
|
-
const
|
|
75
|
+
ConvertTo-Json -Depth 3 -InputObject @($items)
|
|
76
|
+
`, 'scan');
|
|
77
|
+
const items = (0, json_1.toArray)(output).map(row => {
|
|
78
|
+
const e = (0, json_1.record)(row);
|
|
79
|
+
const status = OUTCOME_STATUSES.find(s => s === (0, json_1.str)(e.status)) ?? 'failed';
|
|
80
|
+
return {
|
|
81
|
+
entryId: (0, json_1.str)(e.entryId),
|
|
82
|
+
subject: (0, json_1.str)(e.subject),
|
|
83
|
+
folderPath: (0, json_1.str)(e.folderPath),
|
|
84
|
+
status,
|
|
85
|
+
reason: (0, json_1.str)(e.reason),
|
|
86
|
+
};
|
|
87
|
+
});
|
|
103
88
|
return {
|
|
104
|
-
dryRun,
|
|
105
|
-
deleted: (
|
|
106
|
-
refused: (
|
|
107
|
-
failed: (
|
|
108
|
-
items
|
|
109
|
-
const e = (0, json_1.record)(i);
|
|
110
|
-
return {
|
|
111
|
-
entryId: (0, json_1.str)(e.entryId),
|
|
112
|
-
subject: (0, json_1.str)(e.subject),
|
|
113
|
-
folderPath: (0, json_1.str)(e.folderPath),
|
|
114
|
-
status: ((0, json_1.str)(e.status) || 'failed'),
|
|
115
|
-
reason: (0, json_1.str)(e.reason),
|
|
116
|
-
};
|
|
117
|
-
}),
|
|
89
|
+
dryRun: request.dryRun,
|
|
90
|
+
deleted: items.filter(i => i.status === 'deleted').length,
|
|
91
|
+
refused: items.filter(i => i.status === 'refused').length,
|
|
92
|
+
failed: items.filter(i => i.status === 'failed').length,
|
|
93
|
+
items,
|
|
118
94
|
};
|
|
119
95
|
}
|
|
120
96
|
/**
|
|
121
|
-
* Permanently remove items from the account's Deleted Items
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* user already threw away.
|
|
97
|
+
* Permanently remove items from the account's Deleted Items. The ONE irreversible
|
|
98
|
+
* operation here, which is why it is folder-scoped rather than keyed on ids: it
|
|
99
|
+
* can only ever destroy what was already thrown away.
|
|
125
100
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
101
|
+
* Walks backwards, since deleting shifts the collection and a forward walk would
|
|
102
|
+
* skip every other item.
|
|
128
103
|
*/
|
|
129
|
-
async function purgeDeletedItems(
|
|
130
|
-
(0, run_1.
|
|
131
|
-
const script = `${(0, scripts_1.accountScript)(emailAccount)}
|
|
104
|
+
async function purgeDeletedItems(request) {
|
|
105
|
+
const output = await (0, run_1.runPowerShellJson)(`${(0, scripts_1.accountScript)(request.account)}
|
|
132
106
|
${scripts_1.DELIVERY_STORE_PS}
|
|
133
|
-
$folder = $store.GetDefaultFolder(
|
|
134
|
-
$
|
|
107
|
+
$folder = $store.GetDefaultFolder(${(0, run_1.psInt)(mail_1.FolderId.DeletedItems)})
|
|
108
|
+
$olderThanDays = ${(0, run_1.psInt)(request.olderThanDays)}
|
|
109
|
+
$dryRun = ${(0, run_1.psBool)(request.dryRun)}
|
|
110
|
+
${(0, scripts_1.cutoffScript)(request.olderThanDays)}
|
|
135
111
|
$matched = 0
|
|
136
112
|
$purged = 0
|
|
137
113
|
$kept = 0
|
|
138
114
|
$failed = 0
|
|
139
|
-
# Bound once:
|
|
140
|
-
# fresh collection object, and this loop runs once per message in Deleted Items.
|
|
115
|
+
# Bound once: each $folder.Items is a COM call that builds a fresh collection.
|
|
141
116
|
$folderItems = $folder.Items
|
|
142
117
|
for ($i = $folderItems.Count; $i -ge 1; $i--) {
|
|
143
118
|
$it = $null
|
|
144
119
|
try { $it = $folderItems.Item($i) } catch { continue }
|
|
145
120
|
$stamp = $null
|
|
146
|
-
foreach ($
|
|
147
|
-
try { $stamp = $it.$
|
|
121
|
+
foreach ($property in @('ReceivedTime', 'LastModificationTime', 'CreationTime')) {
|
|
122
|
+
try { $stamp = $it.$property; if ($stamp -ne $null) { break } } catch {}
|
|
148
123
|
}
|
|
149
|
-
if ($
|
|
124
|
+
if ($olderThanDays -gt 0 -and $stamp -ne $null -and $stamp -gt $cutoff) { $kept++; continue }
|
|
150
125
|
$matched++
|
|
151
|
-
if ($
|
|
126
|
+
if ($dryRun) { continue }
|
|
152
127
|
try { $it.Delete(); $purged++ } catch { $failed++ }
|
|
153
128
|
}
|
|
154
|
-
ConvertTo-Json
|
|
155
|
-
|
|
156
|
-
|
|
129
|
+
ConvertTo-Json -Compress -InputObject ([PSCustomObject]@{
|
|
130
|
+
folderPath = [string]$folder.FolderPath
|
|
131
|
+
matched = $matched
|
|
132
|
+
purged = $purged
|
|
133
|
+
kept = $kept
|
|
134
|
+
failed = $failed
|
|
135
|
+
})
|
|
136
|
+
`, 'purge');
|
|
137
|
+
const e = (0, json_1.record)(output);
|
|
157
138
|
return {
|
|
158
|
-
folderPath: (0, json_1.str)(
|
|
159
|
-
dryRun,
|
|
160
|
-
matched: (0, json_1.num)(
|
|
161
|
-
purged: (0, json_1.num)(
|
|
162
|
-
kept: (0, json_1.num)(
|
|
163
|
-
failed: (0, json_1.num)(
|
|
139
|
+
folderPath: (0, json_1.str)(e.folderPath),
|
|
140
|
+
dryRun: request.dryRun,
|
|
141
|
+
matched: (0, json_1.num)(e.matched),
|
|
142
|
+
purged: (0, json_1.num)(e.purged),
|
|
143
|
+
kept: (0, json_1.num)(e.kept),
|
|
144
|
+
failed: (0, json_1.num)(e.failed),
|
|
164
145
|
};
|
|
165
146
|
}
|
|
166
147
|
//# sourceMappingURL=cleanup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/windows/cleanup.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/windows/cleanup.ts"],"names":[],"mappings":";;AA0BA,kDAqEC;AAUD,8CA0CC;AAnJD,wDAAwD;AACxD,+BAA4E;AAC5E,uCAA2E;AAC3E,yCAA2D;AAC3D,kCAA0D;AAI1D,kFAAkF;AAClF,MAAM,oBAAoB,GAAG,CAAC,eAAQ,CAAC,KAAK,EAAE,eAAQ,CAAC,QAAQ,CAAC,CAAC;AAEjE,MAAM,gBAAgB,GAA2C,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAElH;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,mBAAmB,CAAC,OAA4B;IAClE,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAiB,EAAC,GAAG,IAAA,uBAAa,EAAC,OAAO,CAAC,OAAO,CAAC;EAC1E,2BAAiB;oBACC,IAAA,YAAM,EAAC,OAAO,CAAC,cAAc,CAAC;YACtC,IAAA,YAAM,EAAC,OAAO,CAAC,MAAM,CAAC;qBACb,IAAA,cAAQ,EAAC,4BAAqB,CAAC;;sBAE9B,oBAAoB,CAAC,GAAG,CAAC,WAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;kBAiB9C,IAAA,aAAO,EAAC,OAAO,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B1C,EAAE,MAAM,CAAC,CAAC;IACP,MAAM,KAAK,GAAwB,IAAA,cAAO,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QACzD,MAAM,CAAC,GAAG,IAAA,aAAM,EAAC,GAAG,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAA,UAAG,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,QAAQ,CAAC;QAC3E,OAAO;YACH,OAAO,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,OAAO,CAAC;YACvB,OAAO,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,OAAO,CAAC;YACvB,UAAU,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,UAAU,CAAC;YAC7B,MAAM;YACN,MAAM,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,MAAM,CAAC;SACxB,CAAC;IACN,CAAC,CAAC,CAAC;IACH,OAAO;QACH,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;QACzD,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;QACzD,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;QACvD,KAAK;KACR,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,iBAAiB,CAAC,OAAqB;IACzD,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAiB,EAAC,GAAG,IAAA,uBAAa,EAAC,OAAO,CAAC,OAAO,CAAC;EAC1E,2BAAiB;oCACiB,IAAA,WAAK,EAAC,eAAQ,CAAC,YAAY,CAAC;mBAC7C,IAAA,WAAK,EAAC,OAAO,CAAC,aAAa,CAAC;YACnC,IAAA,YAAM,EAAC,OAAO,CAAC,MAAM,CAAC;EAChC,IAAA,sBAAY,EAAC,OAAO,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BpC,EAAE,OAAO,CAAC,CAAC;IACR,MAAM,CAAC,GAAG,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC;IACzB,OAAO;QACH,UAAU,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,UAAU,CAAC;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,OAAO,CAAC;QACvB,MAAM,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,IAAI,CAAC;QACjB,MAAM,EAAE,IAAA,UAAG,EAAC,CAAC,CAAC,MAAM,CAAC;KACxB,CAAC;AACN,CAAC","sourcesContent":["// Deleting mail, and emptying what was already deleted.\nimport { psArray, psBool, psInt, psString, runPowerShellJson } from './run';\nimport { accountScript, cutoffScript, DELIVERY_STORE_PS } from './scripts';\nimport { num, record, str, toArray } from '../shared/json';\nimport { FolderId, PROTECTED_MAIL_REASON } from '../mail';\nimport type { DeleteEmailsRequest, PurgeRequest } from '../backend';\nimport type { DeleteMailOutcome, DeleteMailResult, PurgeDeletedItemsResult } from '../types';\n\n/** Folders whose contents are received or sent mail rather than working state. */\nconst PROTECTED_FOLDER_IDS = [FolderId.Inbox, FolderId.SentMail];\n\nconst OUTCOME_STATUSES: readonly DeleteMailOutcome['status'][] = ['deleted', 'would-delete', 'refused', 'failed'];\n\n/**\n * Delete mail by entry id from anywhere in the account. Delete() moves each item\n * to Deleted Items, so this is recoverable — purgeDeletedItems is what destroys.\n *\n * This is the one operation that can reach received mail, and an entry id is an\n * unsafe key for it: a stale or wrong id can resolve to a DIFFERENT message.\n * Three things hold the line:\n * - Inbox and Sent Items are refused, INCLUDING their subfolders (a filed\n * folder is still received mail), unless `allowProtected`.\n * - `dryRun` resolves and reports without deleting, so the exact subjects and\n * folders can be checked before anything happens.\n * - Every outcome echoes the subject and folder of the item actually resolved.\n */\nexport async function deleteOutlookEmails(request: DeleteEmailsRequest): Promise<DeleteMailResult> {\n const output = await runPowerShellJson(`${accountScript(request.account)}\n${DELIVERY_STORE_PS}\n$allowProtected = ${psBool(request.allowProtected)}\n$dryRun = ${psBool(request.dryRun)}\n$protectedReason = ${psString(PROTECTED_MAIL_REASON)}\n$protectedIds = @{}\nforeach ($role in @(${PROTECTED_FOLDER_IDS.map(psInt).join(', ')})) {\n try { $protectedIds[[string]$store.GetDefaultFolder($role).EntryID] = $true } catch {}\n}\nfunction Test-UnderProtectedFolder($folder) {\n $current = $folder\n for ($guard = 0; $current -ne $null -and $guard -lt 25; $guard++) {\n $folderId = $null\n try { $folderId = [string]$current.EntryID } catch {}\n if (-not $folderId) { return $false }\n if ($protectedIds.ContainsKey($folderId)) { return $true }\n $parent = $null\n try { $parent = $current.Parent } catch {}\n $current = $parent\n }\n return $false\n}\n$items = @()\nforeach ($id in ${psArray(request.entryIds)}) {\n $subject = ''\n $folderPath = ''\n try {\n $it = $null\n try { $it = $ns.GetItemFromID($id, $store.StoreID) } catch { $it = $null }\n if ($it -eq $null) { try { $it = $ns.GetItemFromID($id) } catch { $it = $null } }\n if ($it -eq $null) { throw \"no item with that entry id in this account\" }\n try { $subject = [string]$it.Subject } catch {}\n $parent = $null\n try { $parent = $it.Parent } catch {}\n if ($parent -eq $null) { throw \"item has no parent folder - refusing to delete\" }\n try { $folderPath = [string]$parent.FolderPath } catch {}\n if ((Test-UnderProtectedFolder $parent) -and -not $allowProtected) {\n $items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'refused'; reason = $protectedReason }\n } elseif ($dryRun) {\n $items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'would-delete'; reason = '' }\n } else {\n $it.Delete()\n $items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'deleted'; reason = '' }\n }\n } catch {\n $items += [PSCustomObject]@{ entryId = $id; subject = $subject; folderPath = $folderPath; status = 'failed'; reason = $_.Exception.Message }\n }\n}\nConvertTo-Json -Depth 3 -InputObject @($items)\n`, 'scan');\n const items: DeleteMailOutcome[] = toArray(output).map(row => {\n const e = record(row);\n const status = OUTCOME_STATUSES.find(s => s === str(e.status)) ?? 'failed';\n return {\n entryId: str(e.entryId),\n subject: str(e.subject),\n folderPath: str(e.folderPath),\n status,\n reason: str(e.reason),\n };\n });\n return {\n dryRun: request.dryRun,\n deleted: items.filter(i => i.status === 'deleted').length,\n refused: items.filter(i => i.status === 'refused').length,\n failed: items.filter(i => i.status === 'failed').length,\n items,\n };\n}\n\n/**\n * Permanently remove items from the account's Deleted Items. The ONE irreversible\n * operation here, which is why it is folder-scoped rather than keyed on ids: it\n * can only ever destroy what was already thrown away.\n *\n * Walks backwards, since deleting shifts the collection and a forward walk would\n * skip every other item.\n */\nexport async function purgeDeletedItems(request: PurgeRequest): Promise<PurgeDeletedItemsResult> {\n const output = await runPowerShellJson(`${accountScript(request.account)}\n${DELIVERY_STORE_PS}\n$folder = $store.GetDefaultFolder(${psInt(FolderId.DeletedItems)})\n$olderThanDays = ${psInt(request.olderThanDays)}\n$dryRun = ${psBool(request.dryRun)}\n${cutoffScript(request.olderThanDays)}\n$matched = 0\n$purged = 0\n$kept = 0\n$failed = 0\n# Bound once: each $folder.Items is a COM call that builds a fresh collection.\n$folderItems = $folder.Items\nfor ($i = $folderItems.Count; $i -ge 1; $i--) {\n $it = $null\n try { $it = $folderItems.Item($i) } catch { continue }\n $stamp = $null\n foreach ($property in @('ReceivedTime', 'LastModificationTime', 'CreationTime')) {\n try { $stamp = $it.$property; if ($stamp -ne $null) { break } } catch {}\n }\n if ($olderThanDays -gt 0 -and $stamp -ne $null -and $stamp -gt $cutoff) { $kept++; continue }\n $matched++\n if ($dryRun) { continue }\n try { $it.Delete(); $purged++ } catch { $failed++ }\n}\nConvertTo-Json -Compress -InputObject ([PSCustomObject]@{\n folderPath = [string]$folder.FolderPath\n matched = $matched\n purged = $purged\n kept = $kept\n failed = $failed\n})\n`, 'purge');\n const e = record(output);\n return {\n folderPath: str(e.folderPath),\n dryRun: request.dryRun,\n matched: num(e.matched),\n purged: num(e.purged),\n kept: num(e.kept),\n failed: num(e.failed),\n };\n}\n"]}
|
package/dist/windows/drafts.d.ts
CHANGED
|
@@ -1,40 +1,21 @@
|
|
|
1
|
-
import type {
|
|
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, each proved to be this account's first. */
|
|
6
|
+
export declare function sendDrafts(request: EntryIdsRequest): Promise<SendDraftsResult>;
|
|
2
7
|
/**
|
|
3
|
-
* Send
|
|
4
|
-
* Which drafts those are is DRAFTS_SCAN_PS's rule, not this function's.
|
|
8
|
+
* Send every draft belonging to the account.
|
|
5
9
|
*
|
|
6
|
-
*
|
|
7
|
-
* of Drafts, and
|
|
10
|
+
* The matching items are snapshotted before the first send: sending moves an
|
|
11
|
+
* item out of Drafts, and sending during a live enumeration would skip every
|
|
12
|
+
* other one.
|
|
8
13
|
*/
|
|
9
|
-
export declare function sendAllDrafts(
|
|
14
|
+
export declare function sendAllDrafts(request: AccountRequest): Promise<SendDraftsResult>;
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* against the same folders, so repeating a ~700-char store id on every row would be
|
|
16
|
-
* pure payload. Bodies are previewed, never returned whole — a templated reply body
|
|
17
|
-
* runs to tens of thousands of characters and a folder's worth would blow the cap.
|
|
18
|
-
*/
|
|
19
|
-
export declare function listOutlookDrafts(emailAccount: string, limit?: number, previewChars?: number): Promise<ListDraftsResult>;
|
|
20
|
-
/**
|
|
21
|
-
* Delete mail drafts by EntryID. Outlook's Delete() moves the item to Deleted Items
|
|
22
|
-
* rather than destroying it, so a mistaken call stays recoverable from there.
|
|
23
|
-
*
|
|
24
|
-
* Every id must resolve to a mail item sitting in one of THIS account's Drafts
|
|
25
|
-
* folders before anything is deleted; an id pointing at ordinary mail, or at another
|
|
26
|
-
* account's draft, is refused and reported. Without that gate this would be a
|
|
27
|
-
* general-purpose "delete any email by id" tool, which is not what it is for.
|
|
28
|
-
*/
|
|
29
|
-
export declare function deleteOutlookDrafts(emailAccount: string, entryIds: string[]): Promise<DeleteDraftsResult>;
|
|
30
|
-
/**
|
|
31
|
-
* Send a chosen subset of `emailAccount`'s drafts by EntryID — e.g. after
|
|
32
|
-
* `listOutlookDrafts` and a user review pass — instead of `sendAllDrafts`'s
|
|
33
|
-
* account-wide sweep.
|
|
34
|
-
*
|
|
35
|
-
* Same ownership gate as `deleteOutlookDrafts`: every id must resolve to a mail
|
|
36
|
-
* item sitting in one of THIS account's Drafts folders before anything is sent.
|
|
37
|
-
* An id pointing at ordinary inbox mail, or at another account's draft, is
|
|
38
|
-
* refused and reported rather than sent.
|
|
16
|
+
* Delete the named drafts, each proved to be this account's first. Outlook's
|
|
17
|
+
* Delete() moves an item to Deleted Items, so a mistake stays recoverable.
|
|
18
|
+
* Without the proof this would be a general "delete any email by id" call,
|
|
19
|
+
* which is not what it is for.
|
|
39
20
|
*/
|
|
40
|
-
export declare function
|
|
21
|
+
export declare function deleteOutlookDrafts(request: EntryIdsRequest): Promise<DeleteDraftsResult>;
|