@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/mac/bounces.js
CHANGED
|
@@ -3,30 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.cleanUndeliverableEmails = cleanUndeliverableEmails;
|
|
4
4
|
exports.collectBouncedRecipients = collectBouncedRecipients;
|
|
5
5
|
exports.readSentRecipientGroups = readSentRecipientGroups;
|
|
6
|
-
// Bounce-backs: finding them,
|
|
6
|
+
// Bounce-backs: finding them, clearing them away, and mining them for the
|
|
7
7
|
// addresses that failed.
|
|
8
8
|
//
|
|
9
|
-
// Windows classifies inside
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// have their bodies read, which is the property that keeps either version
|
|
14
|
-
// affordable on a real inbox.
|
|
9
|
+
// Windows classifies inside PowerShell, after Restrict has narrowed the set.
|
|
10
|
+
// AppleScript has no Restrict, so a folder is indexed with bulk property reads
|
|
11
|
+
// and the SAME rules (shared/bounceRules) run here in TypeScript. Only matches
|
|
12
|
+
// have their bodies read, which keeps either version affordable.
|
|
15
13
|
const run_1 = require("./run");
|
|
16
14
|
const scripts_1 = require("./scripts");
|
|
17
15
|
const bounceRules_1 = require("../shared/bounceRules");
|
|
18
|
-
const mail_1 = require("../mail");
|
|
19
16
|
/**
|
|
20
17
|
* Index one well-known folder's messages within the window: everything the
|
|
21
|
-
*
|
|
18
|
+
* classifier needs, in bulk reads — `sender of every message` hands back a list
|
|
19
|
+
* of records AppleScript reads locally, so the whole index is five Apple events.
|
|
20
|
+
*
|
|
21
|
+
* The fifth is the header block, which carries the structural bounce signal (see
|
|
22
|
+
* DSN_HEADER_MARKERS). Headers are bulkier than the other properties, so they
|
|
23
|
+
* are tested in AppleScript and cross the boundary as one flag per message
|
|
24
|
+
* rather than as text.
|
|
22
25
|
*/
|
|
23
|
-
async function indexFolder(emailAccount, folderTerm,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
${(0, scripts_1.accountLookupSnippet)(emailAccount)}
|
|
29
|
-
set scanFolder to ${folderTerm} of targetAcct
|
|
26
|
+
async function indexFolder(emailAccount, folderTerm, daysBack) {
|
|
27
|
+
const acct = await (0, scripts_1.resolveMacAccount)(emailAccount);
|
|
28
|
+
const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
|
|
29
|
+
${(0, scripts_1.accountLookupSnippet)(acct)}
|
|
30
|
+
${(0, scripts_1.rootFolderSnippet)(acct, folderTerm, 'scanFolder')}
|
|
30
31
|
set idList to id of every message of scanFolder
|
|
31
32
|
set subjList to subject of every message of scanFolder
|
|
32
33
|
try
|
|
@@ -39,7 +40,18 @@ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
|
|
|
39
40
|
on error
|
|
40
41
|
set sndList to {}
|
|
41
42
|
end try
|
|
42
|
-
|
|
43
|
+
-- Outlook for Mac publishes no MessageClass, so the delivery-status headers
|
|
44
|
+
-- the report arrived with are the structural signal instead. A folder whose
|
|
45
|
+
-- headers can't be read leaves the list empty and every flag false, which
|
|
46
|
+
-- classifies on the sender and subject rules alone — the behaviour before
|
|
47
|
+
-- this read existed, never an error.
|
|
48
|
+
try
|
|
49
|
+
set hdrList to headers of every message of scanFolder
|
|
50
|
+
on error
|
|
51
|
+
set hdrList to {}
|
|
52
|
+
end try
|
|
53
|
+
set hasHeaders to ((count of hdrList) is (count of idList))
|
|
54
|
+
set cutoff to (current date) - (${(0, run_1.asInt)(daysBack)} * days)
|
|
43
55
|
set out to ""
|
|
44
56
|
repeat with i from 1 to (count of idList)
|
|
45
57
|
set stamp to missing value
|
|
@@ -56,18 +68,19 @@ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
|
|
|
56
68
|
set sndName to (name of snd) as string
|
|
57
69
|
end try
|
|
58
70
|
end if
|
|
59
|
-
set
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
set isNdr to false
|
|
72
|
+
if hasHeaders then
|
|
73
|
+
try
|
|
74
|
+
set hdrText to (item i of hdrList) as string
|
|
75
|
+
if ${bounceRules_1.DSN_HEADER_MARKERS.map(marker => `hdrText contains ${(0, run_1.asString)(marker)}`).join(' and ')} then set isNdr to true
|
|
76
|
+
end try
|
|
77
|
+
end if
|
|
78
|
+
set out to out & ${(0, run_1.asRow)(['(item i of idList as string)', '(item i of subjList)', 'sndName', 'sndAddr', 'my isoDate(stamp)', '(isNdr as string)'])}
|
|
66
79
|
end if
|
|
67
80
|
end repeat
|
|
68
81
|
return out
|
|
69
|
-
end tell
|
|
70
|
-
return (0, run_1.splitRecords)(
|
|
82
|
+
end tell`, 'scan');
|
|
83
|
+
return (0, run_1.splitRecords)(raw).map(record => {
|
|
71
84
|
const parts = (0, run_1.splitFields)(record);
|
|
72
85
|
return {
|
|
73
86
|
id: (0, run_1.field)(parts, 0),
|
|
@@ -75,16 +88,18 @@ end tell`;
|
|
|
75
88
|
senderName: (0, run_1.field)(parts, 2),
|
|
76
89
|
senderEmail: (0, run_1.field)(parts, 3),
|
|
77
90
|
receivedTime: (0, run_1.field)(parts, 4),
|
|
91
|
+
isNonDeliveryReport: (0, run_1.boolField)(parts, 5),
|
|
78
92
|
};
|
|
79
93
|
});
|
|
80
94
|
}
|
|
81
|
-
/**
|
|
95
|
+
/** The plain-text bodies of the given messages, by id. */
|
|
82
96
|
async function readBodies(ids) {
|
|
97
|
+
const bodies = new Map();
|
|
83
98
|
if (ids.length === 0)
|
|
84
|
-
return
|
|
85
|
-
const
|
|
99
|
+
return bodies;
|
|
100
|
+
const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
|
|
86
101
|
set out to ""
|
|
87
|
-
repeat with theId in
|
|
102
|
+
repeat with theId in ${(0, run_1.asIdList)(ids)}
|
|
88
103
|
set theMsg to missing value
|
|
89
104
|
try
|
|
90
105
|
set theMsg to message id theId
|
|
@@ -98,9 +113,8 @@ async function readBodies(ids) {
|
|
|
98
113
|
end if
|
|
99
114
|
end repeat
|
|
100
115
|
return out
|
|
101
|
-
end tell
|
|
102
|
-
const
|
|
103
|
-
for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(script, 300000))) {
|
|
116
|
+
end tell`, 'scan');
|
|
117
|
+
for (const record of (0, run_1.splitRecords)(raw)) {
|
|
104
118
|
const parts = (0, run_1.splitFields)(record);
|
|
105
119
|
bodies.set((0, run_1.field)(parts, 0), (0, run_1.field)(parts, 1));
|
|
106
120
|
}
|
|
@@ -125,28 +139,20 @@ async function collectBounces(indexed, accountAddress) {
|
|
|
125
139
|
}));
|
|
126
140
|
}
|
|
127
141
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
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.
|
|
142
|
+
* Find bounce-backs in the Inbox and, unless dry-running, move each to Deleted
|
|
143
|
+
* Items. The same three signals Windows uses apply, in the same order: a report
|
|
144
|
+
* that declares itself one in its headers, then the sender fingerprint, then the
|
|
145
|
+
* subject phrases.
|
|
138
146
|
*/
|
|
139
|
-
async function cleanUndeliverableEmails(
|
|
140
|
-
const
|
|
141
|
-
const indexed = await indexFolder(emailAccount, 'inbox', days);
|
|
142
|
-
const matched = await collectBounces(indexed, emailAccount);
|
|
147
|
+
async function cleanUndeliverableEmails(request) {
|
|
148
|
+
const matched = await collectBounces(await indexFolder(request.account, 'inbox', request.daysBack), request.account);
|
|
143
149
|
let deletedCount = 0;
|
|
144
150
|
const failed = [];
|
|
145
|
-
if (!dryRun && matched.length > 0) {
|
|
146
|
-
const
|
|
151
|
+
if (!request.dryRun && matched.length > 0) {
|
|
152
|
+
const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
|
|
147
153
|
set deletedCount to 0
|
|
148
154
|
set out to ""
|
|
149
|
-
repeat with theId in
|
|
155
|
+
repeat with theId in ${(0, run_1.asIdList)(matched.map(m => m.entryId))}
|
|
150
156
|
set subj to ""
|
|
151
157
|
try
|
|
152
158
|
set theMsg to missing value
|
|
@@ -160,43 +166,34 @@ async function cleanUndeliverableEmails(emailAccount, daysBack = 30, dryRun = tr
|
|
|
160
166
|
delete theMsg
|
|
161
167
|
set deletedCount to deletedCount + 1
|
|
162
168
|
on error errText
|
|
163
|
-
set out to out & ${(0, run_1.asRow)(['subj', 'errText'])}
|
|
169
|
+
set out to out & ${(0, run_1.asRow)(['(theId as string)', 'subj', 'errText'])}
|
|
164
170
|
end try
|
|
165
171
|
end repeat
|
|
166
172
|
return ${(0, run_1.asRow)(['(deletedCount as string)'])} & out
|
|
167
|
-
end tell
|
|
168
|
-
const records = (0, run_1.splitRecords)(
|
|
169
|
-
deletedCount = (0, run_1.intField)((0, run_1.splitFields)(records[0]
|
|
173
|
+
end tell`, 'scan');
|
|
174
|
+
const records = (0, run_1.splitRecords)(raw);
|
|
175
|
+
deletedCount = (0, run_1.intField)((0, run_1.splitFields)(records[0] ?? ''), 0);
|
|
170
176
|
for (const record of records.slice(1)) {
|
|
171
177
|
const parts = (0, run_1.splitFields)(record);
|
|
172
|
-
failed.push({
|
|
178
|
+
failed.push({ entryId: (0, run_1.field)(parts, 0), subject: (0, run_1.field)(parts, 1), error: (0, run_1.field)(parts, 2) });
|
|
173
179
|
}
|
|
174
180
|
}
|
|
175
181
|
return {
|
|
176
|
-
account:
|
|
177
|
-
scannedDays:
|
|
178
|
-
dryRun,
|
|
182
|
+
account: request.account,
|
|
183
|
+
scannedDays: request.daysBack,
|
|
184
|
+
dryRun: request.dryRun,
|
|
179
185
|
matchedCount: matched.length,
|
|
180
186
|
deletedCount,
|
|
181
187
|
matched,
|
|
182
188
|
failed,
|
|
183
189
|
};
|
|
184
190
|
}
|
|
185
|
-
/**
|
|
186
|
-
|
|
187
|
-
|
|
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'];
|
|
191
|
+
/** The deduplicated addresses bounce-backs report as failed. Never deletes anything. */
|
|
192
|
+
async function collectBouncedRecipients(request) {
|
|
193
|
+
const terms = request.includeDeletedItems ? ['inbox', 'deleted items'] : ['inbox'];
|
|
197
194
|
const found = new Set();
|
|
198
195
|
for (const term of terms) {
|
|
199
|
-
const bounces = await collectBounces(await indexFolder(
|
|
196
|
+
const bounces = await collectBounces(await indexFolder(request.account, term, request.daysBack), request.account);
|
|
200
197
|
for (const bounce of bounces) {
|
|
201
198
|
for (const address of bounce.failedRecipients)
|
|
202
199
|
found.add(address);
|
|
@@ -205,21 +202,15 @@ async function collectBouncedRecipients(emailAccount, daysBack = 30, scanDeleted
|
|
|
205
202
|
return [...found];
|
|
206
203
|
}
|
|
207
204
|
/**
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
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.
|
|
205
|
+
* Sent Items within the window, each message with every address it went to,
|
|
206
|
+
* newest first. Indexed on `time sent` — outgoing mail's own stamp; indexing on
|
|
207
|
+
* `time received` yields an empty set that looks exactly like an empty folder.
|
|
213
208
|
*/
|
|
214
|
-
async function readSentRecipientGroups(
|
|
215
|
-
const
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
209
|
+
async function readSentRecipientGroups(request) {
|
|
210
|
+
const acct = await (0, scripts_1.resolveMacAccount)(request.account);
|
|
211
|
+
const indexed = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
|
|
212
|
+
${(0, scripts_1.accountLookupSnippet)(acct)}
|
|
213
|
+
${(0, scripts_1.rootFolderSnippet)(acct, 'sent items', 'sentFolder')}
|
|
223
214
|
set idList to id of every message of sentFolder
|
|
224
215
|
try
|
|
225
216
|
set timeList to time sent of every message of sentFolder
|
|
@@ -227,59 +218,51 @@ ${(0, scripts_1.accountLookupSnippet)(emailAccount)}
|
|
|
227
218
|
set timeList to {}
|
|
228
219
|
end try
|
|
229
220
|
set subjList to subject of every message of sentFolder
|
|
230
|
-
set cutoff to (current date) - (${
|
|
221
|
+
set cutoff to (current date) - (${(0, run_1.asInt)(request.daysBack)} * days)
|
|
231
222
|
set out to ""
|
|
232
223
|
repeat with i from 1 to (count of idList)
|
|
233
224
|
set stamp to missing value
|
|
234
225
|
if (count of timeList) is (count of idList) then set stamp to item i of timeList
|
|
235
226
|
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
|
-
])}
|
|
227
|
+
set out to out & ${(0, run_1.asRow)(['(item i of idList as string)', '(item i of subjList)', 'my isoDate(stamp)'])}
|
|
241
228
|
end if
|
|
242
229
|
end repeat
|
|
243
230
|
return out
|
|
244
|
-
end tell
|
|
245
|
-
const indexed = (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(indexScript, 300000)).map(record => {
|
|
231
|
+
end tell`, 'scan')).map(record => {
|
|
246
232
|
const parts = (0, run_1.splitFields)(record);
|
|
247
233
|
return { id: (0, run_1.field)(parts, 0), subject: (0, run_1.field)(parts, 1).trim(), sentOn: (0, run_1.field)(parts, 2) };
|
|
248
234
|
});
|
|
249
235
|
indexed.sort((a, b) => b.sentOn.localeCompare(a.sentOn));
|
|
250
|
-
const chosen = indexed.slice(0,
|
|
236
|
+
const chosen = indexed.slice(0, request.limit);
|
|
251
237
|
if (chosen.length === 0)
|
|
252
238
|
return [];
|
|
253
|
-
// Pass 2 — recipients, which can only be read
|
|
254
|
-
const
|
|
239
|
+
// Pass 2 — recipients, which can only be read message by message.
|
|
240
|
+
const recipientsById = new Map();
|
|
241
|
+
const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
|
|
255
242
|
set out to ""
|
|
256
|
-
repeat with theId in
|
|
243
|
+
repeat with theId in ${(0, run_1.asIdList)(chosen.map(row => row.id))}
|
|
257
244
|
set theMsg to missing value
|
|
258
245
|
try
|
|
259
246
|
set theMsg to message id theId
|
|
260
247
|
end try
|
|
261
248
|
if theMsg is not missing value then
|
|
262
249
|
${(0, scripts_1.allRecipientsSnippet)('theMsg', ' ')}
|
|
263
|
-
set out to out & ${(0, run_1.asRow)([
|
|
264
|
-
'(theId as string)',
|
|
265
|
-
'my sanitizeList(addrList)',
|
|
266
|
-
])}
|
|
250
|
+
set out to out & ${(0, run_1.asRow)(['(theId as string)', 'my sanitizeList(addrList)'])}
|
|
267
251
|
end if
|
|
268
252
|
end repeat
|
|
269
253
|
return out
|
|
270
|
-
end tell
|
|
271
|
-
const
|
|
272
|
-
for (const record of (0, run_1.splitRecords)(await (0, run_1.runOsaScript)(detailScript, 300000))) {
|
|
254
|
+
end tell`, 'scan');
|
|
255
|
+
for (const record of (0, run_1.splitRecords)(raw)) {
|
|
273
256
|
const parts = (0, run_1.splitFields)(record);
|
|
274
257
|
recipientsById.set((0, run_1.field)(parts, 0), (0, run_1.splitList)((0, run_1.field)(parts, 1)).map(address => address.toLowerCase()));
|
|
275
258
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
259
|
+
return chosen
|
|
260
|
+
.map(row => ({
|
|
261
|
+
entryId: row.id,
|
|
262
|
+
subject: row.subject,
|
|
263
|
+
sentOn: row.sentOn,
|
|
264
|
+
recipients: recipientsById.get(row.id) ?? []
|
|
265
|
+
}))
|
|
266
|
+
.filter(group => group.recipients.length > 0);
|
|
284
267
|
}
|
|
285
268
|
//# sourceMappingURL=bounces.js.map
|
package/dist/mac/bounces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bounces.js","sourceRoot":"","sources":["../../src/mac/bounces.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bounces.js","sourceRoot":"","sources":["../../src/mac/bounces.ts"],"names":[],"mappings":"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","sourcesContent":["// Bounce-backs: finding them, clearing them away, and mining them for the\n// addresses that failed.\n//\n// Windows classifies inside PowerShell, after Restrict has narrowed the set.\n// AppleScript has no Restrict, so a folder is indexed with bulk property reads\n// and the SAME rules (shared/bounceRules) run here in TypeScript. Only matches\n// have their bodies read, which keeps either version affordable.\nimport {\n asIdList,\n asInt,\n asRow,\n asString,\n boolField,\n field,\n intField,\n runOsaScript,\n splitFields,\n splitList,\n splitRecords\n} from './run';\nimport { accountLookupSnippet, allRecipientsSnippet, resolveMacAccount, rootFolderSnippet } from './scripts';\nimport { bounceReason, DSN_HEADER_MARKERS, failedRecipients } from '../shared/bounceRules';\nimport type { CleanUndeliverableRequest, CollectBouncesRequest, SentGroupsRequest } from '../backend';\nimport type { CleanUndeliverableResult, ItemFailure, SentRecipientGroup, UndeliverableEmail } from '../types';\n\ninterface IndexedMessage {\n id: string;\n subject: string;\n senderName: string;\n senderEmail: string;\n receivedTime: string;\n /** Whether the message's own headers declare it a delivery-status notification. */\n isNonDeliveryReport: boolean;\n}\n\n/**\n * Index one well-known folder's messages within the window: everything the\n * classifier needs, in bulk reads — `sender of every message` hands back a list\n * of records AppleScript reads locally, so the whole index is five Apple events.\n *\n * The fifth is the header block, which carries the structural bounce signal (see\n * DSN_HEADER_MARKERS). Headers are bulkier than the other properties, so they\n * are tested in AppleScript and cross the boundary as one flag per message\n * rather than as text.\n */\nasync function indexFolder(emailAccount: string, folderTerm: string, daysBack: number): Promise<IndexedMessage[]> {\n const acct = await resolveMacAccount(emailAccount);\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct)}\n${rootFolderSnippet(acct, folderTerm, 'scanFolder')}\n set idList to id of every message of scanFolder\n set subjList to subject of every message of scanFolder\n try\n set timeList to time received of every message of scanFolder\n on error\n set timeList to {}\n end try\n try\n set sndList to sender of every message of scanFolder\n on error\n set sndList to {}\n end try\n -- Outlook for Mac publishes no MessageClass, so the delivery-status headers\n -- the report arrived with are the structural signal instead. A folder whose\n -- headers can't be read leaves the list empty and every flag false, which\n -- classifies on the sender and subject rules alone — the behaviour before\n -- this read existed, never an error.\n try\n set hdrList to headers of every message of scanFolder\n on error\n set hdrList to {}\n end try\n set hasHeaders to ((count of hdrList) is (count of idList))\n set cutoff to (current date) - (${asInt(daysBack)} * 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 if stamp is missing value or stamp is greater than or equal to cutoff then\n set sndName to \"\"\n set sndAddr to \"\"\n if (count of sndList) is (count of idList) then\n set snd to item i of sndList\n try\n set sndAddr to (address of snd) as string\n end try\n try\n set sndName to (name of snd) as string\n end try\n end if\n set isNdr to false\n if hasHeaders then\n try\n set hdrText to (item i of hdrList) as string\n if ${DSN_HEADER_MARKERS.map(marker => `hdrText contains ${asString(marker)}`).join(' and ')} then set isNdr to true\n end try\n end if\n set out to out & ${asRow(['(item i of idList as string)', '(item i of subjList)', 'sndName', 'sndAddr', 'my isoDate(stamp)', '(isNdr as string)'])}\n end if\n end repeat\n return out\nend tell`, 'scan');\n return splitRecords(raw).map(record => {\n const parts = splitFields(record);\n return {\n id: field(parts, 0),\n subject: field(parts, 1).trim(),\n senderName: field(parts, 2),\n senderEmail: field(parts, 3),\n receivedTime: field(parts, 4),\n isNonDeliveryReport: boolField(parts, 5),\n };\n });\n}\n\n/** The plain-text bodies of the given messages, by id. */\nasync function readBodies(ids: readonly string[]): Promise<Map<string, string>> {\n const bodies = new Map<string, string>();\n if (ids.length === 0) return bodies;\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n set out to \"\"\n repeat with theId in ${asIdList(ids)}\n set theMsg to missing value\n try\n set theMsg to message id theId\n end try\n if theMsg is not missing value then\n set bodyText to \"\"\n try\n set bodyText to (plain text content of theMsg) as string\n end try\n set out to out & ${asRow(['(theId as string)', 'bodyText'])}\n end if\n end repeat\n return out\nend tell`, 'scan');\n for (const record of splitRecords(raw)) {\n const parts = splitFields(record);\n bodies.set(field(parts, 0), field(parts, 1));\n }\n return bodies;\n}\n\n/** Classify an index, then fill each match's failed recipients from its body. */\nasync function collectBounces(indexed: readonly IndexedMessage[], accountAddress: string): Promise<UndeliverableEmail[]> {\n const matched = indexed\n .map(message => ({message, reason: bounceReason(message)}))\n .filter(entry => entry.reason !== '');\n if (matched.length === 0) return [];\n const bodies = await readBodies(matched.map(entry => entry.message.id));\n return matched.map(({message, reason}) => ({\n entryId: message.id,\n subject: message.subject,\n senderName: message.senderName,\n senderEmail: message.senderEmail,\n receivedTime: message.receivedTime,\n matchedReason: reason,\n failedRecipients: failedRecipients(bodies.get(message.id) || '', accountAddress),\n }));\n}\n\n/**\n * Find bounce-backs in the Inbox and, unless dry-running, move each to Deleted\n * Items. The same three signals Windows uses apply, in the same order: a report\n * that declares itself one in its headers, then the sender fingerprint, then the\n * subject phrases.\n */\nexport async function cleanUndeliverableEmails(request: CleanUndeliverableRequest): Promise<CleanUndeliverableResult> {\n const matched = await collectBounces(await indexFolder(request.account, 'inbox', request.daysBack), request.account);\n let deletedCount = 0;\n const failed: ItemFailure[] = [];\n if (!request.dryRun && matched.length > 0) {\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n set deletedCount to 0\n set out to \"\"\n repeat with theId in ${asIdList(matched.map(m => m.entryId))}\n set subj 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 \"message is no longer in the mailbox\"\n try\n set subj to (subject of theMsg) as string\n end try\n delete theMsg\n set deletedCount to deletedCount + 1\n on error errText\n set out to out & ${asRow(['(theId as string)', 'subj', 'errText'])}\n end try\n end repeat\n return ${asRow(['(deletedCount as string)'])} & out\nend tell`, 'scan');\n const records = splitRecords(raw);\n deletedCount = intField(splitFields(records[0] ?? ''), 0);\n for (const record of records.slice(1)) {\n const parts = splitFields(record);\n failed.push({entryId: field(parts, 0), subject: field(parts, 1), error: field(parts, 2)});\n }\n }\n return {\n account: request.account,\n scannedDays: request.daysBack,\n dryRun: request.dryRun,\n matchedCount: matched.length,\n deletedCount,\n matched,\n failed,\n };\n}\n\n/** The deduplicated addresses bounce-backs report as failed. Never deletes anything. */\nexport async function collectBouncedRecipients(request: CollectBouncesRequest): Promise<string[]> {\n const terms = request.includeDeletedItems ? ['inbox', 'deleted items'] : ['inbox'];\n const found = new Set<string>();\n for (const term of terms) {\n const bounces = await collectBounces(await indexFolder(request.account, term, request.daysBack), request.account);\n for (const bounce of bounces) {\n for (const address of bounce.failedRecipients) found.add(address);\n }\n }\n return [...found];\n}\n\n/**\n * Sent Items within the window, each message with every address it went to,\n * newest first. Indexed on `time sent` — outgoing mail's own stamp; indexing on\n * `time received` yields an empty set that looks exactly like an empty folder.\n */\nexport async function readSentRecipientGroups(request: SentGroupsRequest): Promise<SentRecipientGroup[]> {\n const acct = await resolveMacAccount(request.account);\n const indexed = splitRecords(await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct)}\n${rootFolderSnippet(acct, 'sent items', 'sentFolder')}\n set idList to id of every message of sentFolder\n try\n set timeList to time sent of every message of sentFolder\n on error\n set timeList to {}\n end try\n set subjList to subject of every message of sentFolder\n set cutoff to (current date) - (${asInt(request.daysBack)} * 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 if stamp is missing value or stamp is greater than or equal to cutoff then\n set out to out & ${asRow(['(item i of idList as string)', '(item i of subjList)', 'my isoDate(stamp)'])}\n end if\n end repeat\n return out\nend tell`, 'scan')).map(record => {\n const parts = splitFields(record);\n return {id: field(parts, 0), subject: field(parts, 1).trim(), sentOn: field(parts, 2)};\n });\n indexed.sort((a, b) => b.sentOn.localeCompare(a.sentOn));\n const chosen = indexed.slice(0, request.limit);\n if (chosen.length === 0) return [];\n\n // Pass 2 — recipients, which can only be read message by message.\n const recipientsById = new Map<string, string[]>();\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n set out to \"\"\n repeat with theId in ${asIdList(chosen.map(row => row.id))}\n set theMsg to missing value\n try\n set theMsg to message id theId\n end try\n if theMsg is not missing value then\n${allRecipientsSnippet('theMsg', ' ')}\n set out to out & ${asRow(['(theId as string)', 'my sanitizeList(addrList)'])}\n end if\n end repeat\n return out\nend tell`, 'scan');\n for (const record of splitRecords(raw)) {\n const parts = splitFields(record);\n recipientsById.set(field(parts, 0), splitList(field(parts, 1)).map(address => address.toLowerCase()));\n }\n return chosen\n .map(row => ({\n entryId: row.id,\n subject: row.subject,\n sentOn: row.sentOn,\n recipients: recipientsById.get(row.id) ?? []\n }))\n .filter(group => group.recipients.length > 0);\n}\n"]}
|
package/dist/mac/cleanup.d.ts
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DeleteEmailsRequest, PurgeRequest } from '../backend';
|
|
2
|
+
import type { DeleteMailResult, PurgeDeletedItemsResult } from '../types';
|
|
2
3
|
/**
|
|
3
|
-
* Delete mail by message id from anywhere in the account
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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.
|
|
4
|
+
* Delete mail by message id from anywhere in the account, into Deleted Items.
|
|
5
|
+
* Inbox and Sent Items (and their subfolders) are refused unless
|
|
6
|
+
* `allowProtected`; `dryRun` reports without deleting; every outcome names the
|
|
7
|
+
* subject and folder of the item that actually resolved.
|
|
17
8
|
*/
|
|
18
|
-
export declare function deleteOutlookEmails(
|
|
9
|
+
export declare function deleteOutlookEmails(request: DeleteEmailsRequest): Promise<DeleteMailResult>;
|
|
19
10
|
/**
|
|
20
|
-
* Permanently remove items from the account's Deleted Items folder
|
|
21
|
-
*
|
|
22
|
-
*
|
|
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.
|
|
11
|
+
* Permanently remove items from the account's Deleted Items. The folder is
|
|
12
|
+
* indexed first and items destroyed by id afterwards, so deleting can't shift
|
|
13
|
+
* the collection out from under the walk.
|
|
28
14
|
*/
|
|
29
|
-
export declare function purgeDeletedItems(
|
|
15
|
+
export declare function purgeDeletedItems(request: PurgeRequest): Promise<PurgeDeletedItemsResult>;
|