@dawnlit/outlook-bridge 2.0.0 → 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.
- package/README.md +6 -4
- package/dist/backend.d.ts +2 -2
- package/dist/backend.js.map +1 -1
- package/dist/bridge.js +3 -3
- package/dist/bridge.js.map +1 -1
- package/dist/errors.d.ts +0 -2
- package/dist/errors.js +1 -6
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mac/accounts.js.map +1 -1
- package/dist/mac/attachments.js +1 -1
- package/dist/mac/attachments.js.map +1 -1
- package/dist/mac/bounces.js +8 -12
- package/dist/mac/bounces.js.map +1 -1
- package/dist/mac/cleanup.js +4 -41
- package/dist/mac/cleanup.js.map +1 -1
- package/dist/mac/drafts.d.ts +3 -1
- package/dist/mac/drafts.js +34 -33
- package/dist/mac/drafts.js.map +1 -1
- package/dist/mac/folders.d.ts +5 -3
- package/dist/mac/folders.js +18 -19
- package/dist/mac/folders.js.map +1 -1
- package/dist/mac/profile.js.map +1 -1
- package/dist/mac/read.d.ts +4 -0
- package/dist/mac/read.js +54 -16
- package/dist/mac/read.js.map +1 -1
- package/dist/mac/run.d.ts +19 -2
- package/dist/mac/run.js +42 -2
- package/dist/mac/run.js.map +1 -1
- package/dist/mac/scripts.d.ts +21 -14
- package/dist/mac/scripts.js +52 -21
- package/dist/mac/scripts.js.map +1 -1
- package/dist/mac/send.d.ts +3 -3
- package/dist/mac/send.js +44 -12
- package/dist/mac/send.js.map +1 -1
- package/dist/mac/templates.js +15 -18
- package/dist/mac/templates.js.map +1 -1
- package/dist/mail.d.ts +5 -3
- package/dist/mail.js +19 -6
- package/dist/mail.js.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/shared/args.js.map +1 -1
- package/dist/shared/attachmentMatch.d.ts +0 -6
- package/dist/shared/attachmentMatch.js +0 -1
- package/dist/shared/attachmentMatch.js.map +1 -1
- package/dist/shared/exec.js.map +1 -1
- package/dist/shared/json.d.ts +11 -6
- package/dist/shared/json.js +12 -7
- package/dist/shared/json.js.map +1 -1
- package/dist/shared/locate.d.ts +0 -8
- package/dist/shared/locate.js +0 -1
- package/dist/shared/locate.js.map +1 -1
- package/dist/shared/replyBody.d.ts +0 -15
- package/dist/shared/replyBody.js +0 -2
- package/dist/shared/replyBody.js.map +1 -1
- package/dist/shared/templateLimits.d.ts +14 -0
- package/dist/shared/templateLimits.js +21 -0
- package/dist/shared/templateLimits.js.map +1 -0
- package/dist/templateBody.d.ts +6 -0
- package/dist/templateBody.js +8 -1
- package/dist/templateBody.js.map +1 -1
- package/dist/types.d.ts +23 -3
- package/dist/types.js.map +1 -1
- package/dist/windows/bounces.js +4 -4
- package/dist/windows/bounces.js.map +1 -1
- package/dist/windows/cleanup.d.ts +5 -1
- package/dist/windows/cleanup.js +16 -11
- package/dist/windows/cleanup.js.map +1 -1
- package/dist/windows/drafts.d.ts +4 -4
- package/dist/windows/drafts.js +20 -31
- package/dist/windows/drafts.js.map +1 -1
- package/dist/windows/folders.js +1 -1
- package/dist/windows/folders.js.map +1 -1
- package/dist/windows/read.js +6 -2
- package/dist/windows/read.js.map +1 -1
- package/dist/windows/run.d.ts +0 -2
- package/dist/windows/run.js +1 -2
- package/dist/windows/run.js.map +1 -1
- package/dist/windows/scripts.d.ts +4 -4
- package/dist/windows/scripts.js +10 -10
- package/dist/windows/scripts.js.map +1 -1
- package/dist/windows/send.d.ts +8 -3
- package/dist/windows/send.js +10 -2
- package/dist/windows/send.js.map +1 -1
- package/dist/windows/templates.js +9 -15
- package/dist/windows/templates.js.map +1 -1
- package/package.json +2 -2
package/dist/mac/scripts.d.ts
CHANGED
|
@@ -52,8 +52,16 @@ export declare function dateProperty(rootId: number): string;
|
|
|
52
52
|
* AppleScript literal is unreadable, and the parts are known here anyway.
|
|
53
53
|
*/
|
|
54
54
|
export declare function macFolderPath(emailAccount: string, rootLabel: string, segments: readonly string[]): string;
|
|
55
|
-
/**
|
|
56
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Walk a folder's `container` chain to the top as the list `chainNames`,
|
|
57
|
+
* nearest first. Requires `theFolder`, and leaves `cur` on the folder the walk
|
|
58
|
+
* stopped at: the account's nameless root folder, when it got that far.
|
|
59
|
+
*
|
|
60
|
+
* The chain's last element is the folder directly under the account, and an
|
|
61
|
+
* account can't hold two top-level folders of one name, so comparing that name
|
|
62
|
+
* is exact.
|
|
63
|
+
*/
|
|
64
|
+
export declare function folderChainSnippet(indent: string): string;
|
|
57
65
|
/**
|
|
58
66
|
* Resolve `scopeFolder` from `targetAcct`: a well-known root walked down through
|
|
59
67
|
* any further segments. Also binds `scopeCreated`.
|
|
@@ -81,16 +89,15 @@ export declare function partitionMessageIds(entryIds: readonly string[]): {
|
|
|
81
89
|
invalid: ItemFailure[];
|
|
82
90
|
};
|
|
83
91
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
92
|
+
* Bind `theMsg` to a message id, or fail as NOT_FOUND. `message id N` resolves
|
|
93
|
+
* against the application, so the message is found wherever it sits.
|
|
86
94
|
*/
|
|
87
|
-
export declare function messageLookupSnippet(id: string
|
|
95
|
+
export declare function messageLookupSnippet(id: string): string;
|
|
88
96
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* first.
|
|
97
|
+
* `theMsg`'s sender as `sndName` / `sndAddr`. `sender` is a record, and
|
|
98
|
+
* `address of sender of m` doesn't coerce, so the record is bound first.
|
|
92
99
|
*/
|
|
93
|
-
export declare function senderSnippet(
|
|
100
|
+
export declare function senderSnippet(indent?: string): string;
|
|
94
101
|
/**
|
|
95
102
|
* Everything a reader wants off one message bound to `theMsg`, emitted together
|
|
96
103
|
* with the row it produces (see `messageDetailFields`) so the read order and the
|
|
@@ -111,12 +118,12 @@ export declare const MessageDetail: {
|
|
|
111
118
|
readonly body: 6;
|
|
112
119
|
};
|
|
113
120
|
/**
|
|
114
|
-
*
|
|
115
|
-
*
|
|
121
|
+
* `theMsg`'s first recipient as `sndName` / `sndAddr` — what outgoing mail
|
|
122
|
+
* reports in place of a sender.
|
|
116
123
|
*/
|
|
117
|
-
export declare function firstRecipientSnippet(
|
|
118
|
-
/** Every address
|
|
119
|
-
export declare function allRecipientsSnippet(
|
|
124
|
+
export declare function firstRecipientSnippet(indent?: string): string;
|
|
125
|
+
/** Every address `theMsg` was sent to — To, CC and BCC — as the list `addrList`. */
|
|
126
|
+
export declare function allRecipientsSnippet(indent?: string): string;
|
|
120
127
|
/**
|
|
121
128
|
* Recursive, case-insensitive, depth-capped folder search from `startFolder` —
|
|
122
129
|
* the macOS counterpart of the Windows Find-FolderByName.
|
package/dist/mac/scripts.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.accountLookupSnippet = accountLookupSnippet;
|
|
|
6
6
|
exports.rootFolderSnippet = rootFolderSnippet;
|
|
7
7
|
exports.dateProperty = dateProperty;
|
|
8
8
|
exports.macFolderPath = macFolderPath;
|
|
9
|
-
exports.
|
|
9
|
+
exports.folderChainSnippet = folderChainSnippet;
|
|
10
10
|
exports.mailScopeSnippet = mailScopeSnippet;
|
|
11
11
|
exports.macMessageId = macMessageId;
|
|
12
12
|
exports.partitionMessageIds = partitionMessageIds;
|
|
@@ -113,6 +113,38 @@ function dateProperty(rootId) {
|
|
|
113
113
|
function macFolderPath(emailAccount, rootLabel, segments) {
|
|
114
114
|
return ['\\\\' + emailAccount, rootLabel, ...segments].join('\\');
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Walk a folder's `container` chain to the top as the list `chainNames`,
|
|
118
|
+
* nearest first. Requires `theFolder`, and leaves `cur` on the folder the walk
|
|
119
|
+
* stopped at: the account's nameless root folder, when it got that far.
|
|
120
|
+
*
|
|
121
|
+
* The chain's last element is the folder directly under the account, and an
|
|
122
|
+
* account can't hold two top-level folders of one name, so comparing that name
|
|
123
|
+
* is exact.
|
|
124
|
+
*/
|
|
125
|
+
function folderChainSnippet(indent) {
|
|
126
|
+
return `${indent}set chainNames to {}
|
|
127
|
+
${indent}set cur to theFolder
|
|
128
|
+
${indent}set guard to 0
|
|
129
|
+
${indent}repeat while cur is not missing value and guard < 25
|
|
130
|
+
${indent} -- The account's root folder has a name of missing value, and coercing
|
|
131
|
+
${indent} -- that yields the STRING "missing value" — so test before coercing.
|
|
132
|
+
${indent} set rawName to missing value
|
|
133
|
+
${indent} try
|
|
134
|
+
${indent} set rawName to name of cur
|
|
135
|
+
${indent} end try
|
|
136
|
+
${indent} if rawName is missing value then exit repeat
|
|
137
|
+
${indent} set nm to rawName as string
|
|
138
|
+
${indent} if nm is "" then exit repeat
|
|
139
|
+
${indent} set end of chainNames to nm
|
|
140
|
+
${indent} set nextUp to missing value
|
|
141
|
+
${indent} try
|
|
142
|
+
${indent} set nextUp to container of cur
|
|
143
|
+
${indent} end try
|
|
144
|
+
${indent} set cur to nextUp
|
|
145
|
+
${indent} set guard to guard + 1
|
|
146
|
+
${indent}end repeat`;
|
|
147
|
+
}
|
|
116
148
|
/** The dictionary term for a root, or NOT_IMPLEMENTED naming what was asked. */
|
|
117
149
|
function rootTerm(ref, folderLabel = '') {
|
|
118
150
|
const term = exports.MAC_ROOT_TERMS[ref.rootId];
|
|
@@ -188,27 +220,26 @@ function partitionMessageIds(entryIds) {
|
|
|
188
220
|
return { valid, invalid };
|
|
189
221
|
}
|
|
190
222
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
223
|
+
* Bind `theMsg` to a message id, or fail as NOT_FOUND. `message id N` resolves
|
|
224
|
+
* against the application, so the message is found wherever it sits.
|
|
193
225
|
*/
|
|
194
|
-
function messageLookupSnippet(id
|
|
226
|
+
function messageLookupSnippet(id) {
|
|
195
227
|
const complaint = `${(0, errors_1.failureTag)('NOT_FOUND', 'email')}No email found for message id '${id}'. It may have been deleted - list the mail again for a current id.`;
|
|
196
|
-
return ` set
|
|
228
|
+
return ` set theMsg to missing value
|
|
197
229
|
try
|
|
198
|
-
set
|
|
230
|
+
set theMsg to message id ${id}
|
|
199
231
|
end try
|
|
200
|
-
if
|
|
232
|
+
if theMsg is missing value then error ${(0, run_1.asString)(complaint)}`;
|
|
201
233
|
}
|
|
202
234
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* first.
|
|
235
|
+
* `theMsg`'s sender as `sndName` / `sndAddr`. `sender` is a record, and
|
|
236
|
+
* `address of sender of m` doesn't coerce, so the record is bound first.
|
|
206
237
|
*/
|
|
207
|
-
function senderSnippet(
|
|
238
|
+
function senderSnippet(indent = ' ') {
|
|
208
239
|
return `${indent}set sndName to ""
|
|
209
240
|
${indent}set sndAddr to ""
|
|
210
241
|
${indent}try
|
|
211
|
-
${indent} set snd to sender of
|
|
242
|
+
${indent} set snd to sender of theMsg
|
|
212
243
|
${indent} try
|
|
213
244
|
${indent} set sndAddr to (address of snd) as string
|
|
214
245
|
${indent} end try
|
|
@@ -228,7 +259,7 @@ function messageDetailSnippet(withBody = false, indent = ' ') {
|
|
|
228
259
|
${indent}try
|
|
229
260
|
${indent} set subj to (subject of theMsg) as string
|
|
230
261
|
${indent}end try
|
|
231
|
-
${senderSnippet(
|
|
262
|
+
${senderSnippet(indent)}
|
|
232
263
|
${indent}set recvd to ""
|
|
233
264
|
${indent}try
|
|
234
265
|
${indent} set recvd to my isoDate(time received of theMsg)
|
|
@@ -248,7 +279,7 @@ ${indent}end try` : '');
|
|
|
248
279
|
}
|
|
249
280
|
/** The fields `messageDetailSnippet` fills, in row order — see `MessageDetail`. */
|
|
250
281
|
function messageDetailFields(withBody = false) {
|
|
251
|
-
const fields = ['(id of theMsg as string)', 'subj', 'sndName', 'sndAddr', 'recvd', 'my
|
|
282
|
+
const fields = ['(id of theMsg as string)', 'subj', 'sndName', 'sndAddr', 'recvd', 'my sanitizePositionalList(attNames)'];
|
|
252
283
|
if (withBody)
|
|
253
284
|
fields.push('bodyText');
|
|
254
285
|
return fields;
|
|
@@ -264,14 +295,14 @@ exports.MessageDetail = {
|
|
|
264
295
|
body: 6,
|
|
265
296
|
};
|
|
266
297
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
298
|
+
* `theMsg`'s first recipient as `sndName` / `sndAddr` — what outgoing mail
|
|
299
|
+
* reports in place of a sender.
|
|
269
300
|
*/
|
|
270
|
-
function firstRecipientSnippet(
|
|
301
|
+
function firstRecipientSnippet(indent = ' ') {
|
|
271
302
|
return `${indent}set sndName to ""
|
|
272
303
|
${indent}set sndAddr to ""
|
|
273
304
|
${indent}try
|
|
274
|
-
${indent} set rcps to to recipients of
|
|
305
|
+
${indent} set rcps to to recipients of theMsg
|
|
275
306
|
${indent} if (count of rcps) > 0 then
|
|
276
307
|
${indent} set ea to email address of (item 1 of rcps)
|
|
277
308
|
${indent} try
|
|
@@ -283,11 +314,11 @@ ${indent} end try
|
|
|
283
314
|
${indent} end if
|
|
284
315
|
${indent}end try`;
|
|
285
316
|
}
|
|
286
|
-
/** Every address
|
|
287
|
-
function allRecipientsSnippet(
|
|
317
|
+
/** Every address `theMsg` was sent to — To, CC and BCC — as the list `addrList`. */
|
|
318
|
+
function allRecipientsSnippet(indent = ' ') {
|
|
288
319
|
return `${indent}set addrList to {}
|
|
289
320
|
${indent}try
|
|
290
|
-
${indent} repeat with r in (every recipient of
|
|
321
|
+
${indent} repeat with r in (every recipient of theMsg)
|
|
291
322
|
${indent} try
|
|
292
323
|
${indent} -- The record is bound before its field is read: a nested
|
|
293
324
|
${indent} -- 'address of (email address of r)' doesn't coerce, and fails
|
package/dist/mac/scripts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/mac/scripts.ts"],"names":[],"mappings":";;;AAuBA,8CAKC;AAgBD,oDAiBC;AAQD,8CAmBC;AAkBD,oCAEC;AAOD,sCAEC;AAGD,4BAUC;AAUD,4CAuBC;AASD,oCASC;AAOD,kDAWC;AAMD,oDAOC;AAOD,sCAYC;AAQD,oDAsBC;AAGD,kDAIC;AAiBD,sDAeC;AAGD,oDAcC;AA7TD,yEAAyE;AACzE,+BAAiC;AACjC,uCAAgD;AAChD,sCAAiF;AACjF,kCAAmD;AAkBnD,uFAAuF;AAChF,KAAK,UAAU,iBAAiB,CAAC,YAAoB;IACxD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,MAAM,IAAA,6BAAmB,GAAE,CAAC;SACtC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC,CAAC,CAAC,EAAC,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAC,CAAC,CAAC,CAAC,EAAC,YAAY,EAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,oBAAoB,CAAC,IAAgB,EAAE,kBAAkB,GAAG,KAAK;IAC7E,MAAM,KAAK,GAAG;;;mDAGiC,IAAA,cAAQ,EAAC,IAAI,CAAC,YAAY,CAAC;;;;;YAKlE,CAAC;IACT,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,kBAAkB;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS;QAC5B,CAAC,CAAC,GAAG,IAAA,mBAAU,EAAC,iBAAiB,CAAC,4CAA4C,IAAI,CAAC,YAAY,KAAK;cAClG,gHAAgH;QAClH,CAAC,CAAC,GAAG,IAAA,mBAAU,EAAC,mBAAmB,CAAC,YAAY,IAAI,CAAC,YAAY,yBAAyB,CAAC;IAC/F,OAAO,GAAG,KAAK;gDAC6B,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,IAAgB,EAAE,IAAY,EAAE,QAAgB;IAC9E,MAAM,UAAU,GAAG,WAAW,QAAQ,OAAO,IAAI,gBAAgB,CAAC;IAClE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACnB,OAAO;cACD,QAAQ,sBAAsB,EAAE;;EAE5C,UAAU;WACD,CAAC;IACR,CAAC;IACD,6EAA6E;IAC7E,uEAAuE;IACvE,oDAAoD;IACpD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,YAAY,YAAY,IAAI,gCAAgC,CAAC;QACpI,OAAO,iDAAiD,IAAA,cAAQ,EAAC,SAAS,CAAC;EACjF,UAAU,EAAE,CAAC;IACX,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACU,QAAA,cAAc,GAAqC;IAC5D,CAAC,eAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IACzB,CAAC,eAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY;IACjC,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC3B,CAAC,eAAQ,CAAC,YAAY,CAAC,EAAE,eAAe;IACxC,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC3B,CAAC,eAAQ,CAAC,IAAI,CAAC,EAAE,WAAW;CAC/B,CAAC;AAEF,8CAA8C;AAC9C,SAAgB,YAAY,CAAC,MAAc;IACvC,OAAO,IAAA,qBAAc,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,YAAoB,EAAE,SAAiB,EAAE,QAA2B;IAC9F,OAAO,CAAC,MAAM,GAAG,YAAY,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,gFAAgF;AAChF,SAAgB,QAAQ,CAAC,GAAkB,EAAE,WAAW,GAAG,EAAE;IACzD,MAAM,IAAI,GAAG,sBAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,gBAAgB,WAAW,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,4BAAmB,CACzB,gBAAgB,GAAG,CAAC,SAAS,WAAW,KAAK,EAAE,EAC/C,mCAAmC,MAAM,CAAC,MAAM,CAAC,sBAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;IACN,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,IAAgB,EAAE,GAAkB,EAAE,WAAW,GAAG,EAAE,EAAE,aAAa,GAAG,KAAK;IAC1G,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QACpC,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,OAAO,sBAAsB,GAAG,CAAC,SAAS,IAAI,CAAC;QAChH,MAAM,MAAM,GAAG,aAAa;YACxB,CAAC,CAAC,yFAAyF,IAAA,cAAQ,EAAC,OAAO,CAAC;iCACvF;YACrB,CAAC,CAAC,iBAAiB,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,OAAO;;;uCAGwB,IAAA,cAAQ,EAAC,OAAO,CAAC;;;;;;EAMtD,MAAM;;mCAE2B,CAAC;IAChC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO;EACT,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,IAAI,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,OAAe;IACxC,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,4BAAmB,CACzB,IAAI,OAAO,qEAAqE;cAC9E,kFAAkF,CACvF,CAAC;IACN,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,QAA2B;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,EAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAC,CAAC,CAAC;QAC3F,CAAC;IACL,CAAC;IACD,OAAO,EAAC,KAAK,EAAE,OAAO,EAAC,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,EAAU,EAAE,QAAQ,GAAG,QAAQ;IAChE,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,OAAO,CAAC,kCAAkC,EAAE,qEAAqE,CAAC;IAC/J,OAAO,WAAW,QAAQ;;cAEhB,QAAQ,kBAAkB,EAAE;;SAEjC,QAAQ,gCAAgC,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,eAAe,GAAG,QAAQ,EAAE,MAAM,GAAG,MAAM;IACrE,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM,4BAA4B,eAAe;EACjD,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,QAAQ,GAAG,KAAK,EAAE,MAAM,GAAG,MAAM;IAClE,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC;EAC/B,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;EAC9B,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,mFAAmF;AACnF,SAAgB,mBAAmB,CAAC,QAAQ,GAAG,KAAK;IAChD,MAAM,MAAM,GAAG,CAAC,0BAA0B,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,2BAA2B,CAAC,CAAC;IAChH,IAAI,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,mDAAmD;AACtC,QAAA,aAAa,GAAG;IACzB,EAAE,EAAE,CAAC;IACL,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,CAAC;IACf,eAAe,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC;CACD,CAAC;AAEX;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,eAAe,GAAG,QAAQ,EAAE,MAAM,GAAG,MAAM;IAC7E,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM,oCAAoC,eAAe;EACzD,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,qFAAqF;AACrF,SAAgB,oBAAoB,CAAC,eAAe,GAAG,QAAQ,EAAE,MAAM,GAAG,MAAM;IAC5E,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM,4CAA4C,eAAe;EACjE,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED;;;GAGG;AACU,QAAA,mBAAmB,GAAG;;;;;;;;;;;;;;;CAelC,CAAC;AAEF;;;GAGG;AACU,QAAA,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBpC,CAAC","sourcesContent":["// The AppleScript fragments more than one macOS operation is built from.\nimport { asString } from './run';\nimport { readProfileAccounts } from './profile';\nimport { failureTag, InvalidRequestError, NotImplementedError } from '../errors';\nimport { FolderId, isOutgoingRoot } from '../mail';\nimport type { ItemFailure, MailFolderRef } from '../types';\n\n/**\n * An account as the generated AppleScript reaches it.\n *\n * `folderIds` carries what Outlook's profile database knows about the mailbox's\n * well-known folders — the only handle on a mailbox the dictionary publishes no\n * account object for (see profile.ts). It is filled in for every account the\n * profile lists, because the generated script chooses between the account\n * object and the folder id at run time; nothing here has to predict which kinds\n * of account a given Outlook build exposes.\n */\nexport interface MacAccount {\n readonly emailAccount: string;\n readonly folderIds?: Readonly<Record<string, number>>;\n}\n\n/** Look an address up in Outlook's profile database, for the folder ids it can add. */\nexport async function resolveMacAccount(emailAccount: string): Promise<MacAccount> {\n const wanted = emailAccount.trim().toLowerCase();\n const found = (await readProfileAccounts())\n .find(account => account.emailAccount.trim().toLowerCase() === wanted);\n return found ? {emailAccount, folderIds: found.folderIds} : {emailAccount};\n}\n\n/**\n * Resolve the account whose address matches into `targetAcct`, inside a\n * `tell application \"Microsoft Outlook\"` block.\n *\n * `every account` errors even in legacy mode, so the typed classes are probed.\n * A `whose email address is …` filter can't be used either: `email address` is\n * also a class name, and AppleScript resolves it as one.\n *\n * A mailbox the dictionary publishes no account object for leaves `targetAcct`\n * as `missing value` rather than failing, provided the profile gave a folder id\n * to reach it by. `needsAccountObject` is for composing mail, which can't work\n * without the object: the account a message is sent from can only be set from\n * it, and a message composed without it goes out from the default mailbox.\n */\nexport function accountLookupSnippet(acct: MacAccount, needsAccountObject = false): string {\n const probe = ` set targetAcct to missing value\n try\n repeat with a in (exchange accounts & imap accounts & pop accounts)\n if (email address of a as string) is ${asString(acct.emailAccount)} then\n set targetAcct to a\n exit repeat\n end if\n end repeat\n end try`;\n if (acct.folderIds && !needsAccountObject) return probe;\n const complaint = acct.folderIds\n ? `${failureTag('INVALID_REQUEST')}Outlook publishes no account object for '${acct.emailAccount}', `\n + 'so the account a message is sent from cannot be set. Its folders can be read; mail cannot be composed from it.'\n : `${failureTag('ACCOUNT_NOT_FOUND')}Account '${acct.emailAccount}' not found in Outlook.`;\n return `${probe}\n if targetAcct is missing value then error ${asString(complaint)}`;\n}\n\n/**\n * Bind `variable` to one of the account's well-known folders: through the\n * account object when the probe found one, else by the folder's own id. `mail\n * folder id N` resolves against the application rather than an account, and N is\n * the id Outlook's profile database records for that folder.\n */\nexport function rootFolderSnippet(acct: MacAccount, term: string, variable: string): string {\n const viaAccount = ` set ${variable} to ${term} of targetAcct`;\n const id = acct.folderIds?.[term];\n if (id !== undefined) {\n return ` if targetAcct is missing value then\n set ${variable} to mail folder id ${id}\n else\n${viaAccount}\n end if`;\n }\n // The profile listed the mailbox but not this root, so the probe is the only\n // way in — and it may have come up empty. Name the folder out of reach\n // rather than let `<term> of missing value` say it.\n if (acct.folderIds) {\n const complaint = `${failureTag('NOT_FOUND', 'folder')}Account '${acct.emailAccount}' has no ${term} folder AppleScript can reach.`;\n return ` if targetAcct is missing value then error ${asString(complaint)}\n${viaAccount}`;\n }\n return viaAccount;\n}\n\n/**\n * Outlook for Mac's dictionary term for each well-known root, by olDefaultFolders\n * id. Verified against the running app: the terms are NOT what the Windows names\n * suggest — `sent mail` and `junk email` don't compile, `sent items` and `junk\n * mail` do — and one bad term fails the whole script at compile time.\n */\nexport const MAC_ROOT_TERMS: Readonly<Record<number, string>> = {\n [FolderId.Inbox]: 'inbox',\n [FolderId.SentMail]: 'sent items',\n [FolderId.Drafts]: 'drafts',\n [FolderId.DeletedItems]: 'deleted items',\n [FolderId.Outbox]: 'outbox',\n [FolderId.Junk]: 'junk mail',\n};\n\n/** The date property a root's items carry. */\nexport function dateProperty(rootId: number): string {\n return isOutgoingRoot(rootId) ? 'time sent' : 'time received';\n}\n\n/**\n * The Windows folder-path shape (`\\\\mailbox\\Inbox\\Invoices`), assembled in\n * TypeScript: escaping backslashes through a template literal and then an\n * AppleScript literal is unreadable, and the parts are known here anyway.\n */\nexport function macFolderPath(emailAccount: string, rootLabel: string, segments: readonly string[]): string {\n return ['\\\\\\\\' + emailAccount, rootLabel, ...segments].join('\\\\');\n}\n\n/** The dictionary term for a root, or NOT_IMPLEMENTED naming what was asked. */\nexport function rootTerm(ref: MailFolderRef, folderLabel = ''): string {\n const term = MAC_ROOT_TERMS[ref.rootId];\n if (!term) {\n const asked = folderLabel ? ` (asked for '${folderLabel}')` : '';\n throw new NotImplementedError(\n `Reading the '${ref.rootLabel}' folder${asked}`,\n `macOS, whose readable roots are ${Object.values(MAC_ROOT_TERMS).join(', ')}`,\n );\n }\n return term;\n}\n\n/**\n * Resolve `scopeFolder` from `targetAcct`: a well-known root walked down through\n * any further segments. Also binds `scopeCreated`.\n *\n * Names compare with `is`, which is case-insensitive in AppleScript, matching\n * the Windows walk. A missing segment fails as NOT_FOUND rather than falling\n * back to the root; `createMissing` builds the chain instead.\n */\nexport function mailScopeSnippet(acct: MacAccount, ref: MailFolderRef, folderLabel = '', createMissing = false): string {\n const term = rootTerm(ref, folderLabel);\n const walk = ref.segments.map(segment => {\n const complaint = `${failureTag('NOT_FOUND', 'folder')}Folder '${segment}' not found under '${ref.rootLabel}'.`;\n const create = createMissing\n ? ` set foundFolder to (make new mail folder at scopeFolder with properties {name:${asString(segment)}})\n set scopeCreated to true`\n : ` error ${asString(complaint)}`;\n return `\n set foundFolder to missing value\n repeat with sf in (mail folders of scopeFolder)\n if (name of sf as string) is ${asString(segment)} then\n set foundFolder to sf\n exit repeat\n end if\n end repeat\n if foundFolder is missing value then\n${create}\n end if\n set scopeFolder to foundFolder`;\n }).join('');\n return ` set scopeCreated to false\n${rootFolderSnippet(acct, term, 'scopeFolder')}${walk}`;\n}\n\n/**\n * The message id text for a script, or INVALID_REQUEST.\n *\n * Outlook for Mac ids are small integers; a Windows EntryID is refused up front\n * rather than left to fail as a confusing \"not found\", because a caller that\n * persisted one from a Windows run needs to be told exactly that.\n */\nexport function macMessageId(entryId: string): string {\n const id = String(entryId ?? '').trim();\n if (!/^\\d+$/.test(id)) {\n throw new InvalidRequestError(\n `'${entryId}' is not an Outlook for Mac message id. Mac ids are small integers `\n + '(e.g. \"1263\") listed on this machine; a Windows EntryID cannot be resolved here.',\n );\n }\n return id;\n}\n\n/**\n * Split ids into those a script can look up and those that can only fail. A\n * batch reports an unusable id beside a genuine miss rather than throwing and\n * discarding the ids that would have worked.\n */\nexport function partitionMessageIds(entryIds: readonly string[]): { valid: string[]; invalid: ItemFailure[] } {\n const valid: string[] = [];\n const invalid: ItemFailure[] = [];\n for (const entryId of entryIds) {\n try {\n valid.push(macMessageId(entryId));\n } catch (error) {\n invalid.push({entryId: String(entryId), subject: '', error: (error as Error).message});\n }\n }\n return {valid, invalid};\n}\n\n/**\n * Resolve `variable` from a message id, or fail as NOT_FOUND. `message id N`\n * resolves against the application, so the message is found wherever it sits.\n */\nexport function messageLookupSnippet(id: string, variable = 'theMsg'): string {\n const complaint = `${failureTag('NOT_FOUND', 'email')}No email found for message id '${id}'. It may have been deleted - list the mail again for a current id.`;\n return ` set ${variable} to missing value\n try\n set ${variable} to message id ${id}\n end try\n if ${variable} is missing value then error ${asString(complaint)}`;\n}\n\n/**\n * The sender's display name and address as `sndName` / `sndAddr`. `sender` is a\n * record, and `address of sender of m` doesn't coerce, so the record is bound\n * first.\n */\nexport function senderSnippet(messageVariable = 'theMsg', indent = ' '): string {\n return `${indent}set sndName to \"\"\n${indent}set sndAddr to \"\"\n${indent}try\n${indent} set snd to sender of ${messageVariable}\n${indent} try\n${indent} set sndAddr to (address of snd) as string\n${indent} end try\n${indent} try\n${indent} set sndName to (name of snd) as string\n${indent} end try\n${indent}end try`;\n}\n\n/**\n * Everything a reader wants off one message bound to `theMsg`, emitted together\n * with the row it produces (see `messageDetailFields`) so the read order and the\n * positions the decoders index into cannot drift apart. `bodyText` is emitted\n * LAST when asked for, so a stray separator in an earlier field can't shift it.\n */\nexport function messageDetailSnippet(withBody = false, indent = ' '): string {\n return `${indent}set subj to \"\"\n${indent}try\n${indent} set subj to (subject of theMsg) as string\n${indent}end try\n${senderSnippet('theMsg', indent)}\n${indent}set recvd to \"\"\n${indent}try\n${indent} set recvd to my isoDate(time received of theMsg)\n${indent}on error\n${indent} try\n${indent} set recvd to my isoDate(time sent of theMsg)\n${indent} end try\n${indent}end try\n${indent}set attNames to {}\n${indent}try\n${indent} set attNames to name of every attachment of theMsg\n${indent}end try` + (withBody ? `\n${indent}set bodyText to \"\"\n${indent}try\n${indent} set bodyText to (plain text content of theMsg) as string\n${indent}end try` : '');\n}\n\n/** The fields `messageDetailSnippet` fills, in row order — see `MessageDetail`. */\nexport function messageDetailFields(withBody = false): string[] {\n const fields = ['(id of theMsg as string)', 'subj', 'sndName', 'sndAddr', 'recvd', 'my sanitizeList(attNames)'];\n if (withBody) fields.push('bodyText');\n return fields;\n}\n\n/** Where each of those fields lands in the row. */\nexport const MessageDetail = {\n id: 0,\n subject: 1,\n senderName: 2,\n senderEmail: 3,\n receivedTime: 4,\n attachmentNames: 5,\n body: 6,\n} as const;\n\n/**\n * The first recipient's name and address as `sndName` / `sndAddr` — what\n * outgoing mail reports in place of a sender.\n */\nexport function firstRecipientSnippet(messageVariable = 'theMsg', indent = ' '): string {\n return `${indent}set sndName to \"\"\n${indent}set sndAddr to \"\"\n${indent}try\n${indent} set rcps to to recipients of ${messageVariable}\n${indent} if (count of rcps) > 0 then\n${indent} set ea to email address of (item 1 of rcps)\n${indent} try\n${indent} set sndAddr to (address of ea) as string\n${indent} end try\n${indent} try\n${indent} set sndName to (name of ea) as string\n${indent} end try\n${indent} end if\n${indent}end try`;\n}\n\n/** Every address a message was sent to — To, CC and BCC — as the list `addrList`. */\nexport function allRecipientsSnippet(messageVariable = 'theMsg', indent = ' '): string {\n return `${indent}set addrList to {}\n${indent}try\n${indent} repeat with r in (every recipient of ${messageVariable})\n${indent} try\n${indent} -- The record is bound before its field is read: a nested\n${indent} -- 'address of (email address of r)' doesn't coerce, and fails\n${indent} -- inside the try as an empty list rather than an error.\n${indent} set ea to email address of r\n${indent} set oneAddr to (address of ea) as string\n${indent} if oneAddr is not \"\" then set end of addrList to oneAddr\n${indent} end try\n${indent} end repeat\n${indent}end try`;\n}\n\n/**\n * Recursive, case-insensitive, depth-capped folder search from `startFolder` —\n * the macOS counterpart of the Windows Find-FolderByName.\n */\nexport const FIND_FOLDER_HANDLER = `\non findFolderByName(startFolder, wantedName, depth)\n tell application \"Microsoft Outlook\"\n set subs to mail folders of startFolder\n end tell\n repeat with f in subs\n if (name of f as string) is wantedName then return f\n end repeat\n if depth is less than or equal to 1 then return missing value\n repeat with f in subs\n set hit to my findFolderByName(f, wantedName, depth - 1)\n if hit is not missing value then return hit\n end repeat\n return missing value\nend findFolderByName\n`;\n\n/**\n * Enumerate the accounts, probing each class separately: legacy Outlook errors\n * on `every account`, and New Outlook returns empty lists for the classes.\n */\nexport const LIST_ACCOUNTS_SNIPPET = `\nset acctList to {}\ntell application \"Microsoft Outlook\"\n repeat with acctClass in {\"exchange\", \"imap\", \"pop\"}\n try\n if (acctClass as string) is \"exchange\" then\n set accts to exchange accounts\n else if (acctClass as string) is \"imap\" then\n set accts to imap accounts\n else\n set accts to pop accounts\n end if\n repeat with a in accts\n try\n set end of acctList to (email address of a as string)\n end try\n end repeat\n end try\n end repeat\nend tell\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/mac/scripts.ts"],"names":[],"mappings":";;;AAuBA,8CAKC;AAgBD,oDAiBC;AAQD,8CAmBC;AAkBD,oCAEC;AAOD,sCAEC;AAWD,gDAsBC;AAuBD,4CAuBC;AASD,oCASC;AAOD,kDAWC;AAMD,oDAOC;AAMD,sCAYC;AAQD,oDAsBC;AAGD,kDAIC;AAiBD,sDAeC;AAGD,oDAcC;AA7VD,yEAAyE;AACzE,+BAAiC;AACjC,uCAAgD;AAChD,sCAAiF;AACjF,kCAAmD;AAkBnD,uFAAuF;AAChF,KAAK,UAAU,iBAAiB,CAAC,YAAoB;IACxD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,MAAM,IAAA,6BAAmB,GAAE,CAAC;SACtC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;AACnF,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,oBAAoB,CAAC,IAAgB,EAAE,kBAAkB,GAAG,KAAK;IAC7E,MAAM,KAAK,GAAG;;;mDAGiC,IAAA,cAAQ,EAAC,IAAI,CAAC,YAAY,CAAC;;;;;YAKlE,CAAC;IACT,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,kBAAkB;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS;QAC5B,CAAC,CAAC,GAAG,IAAA,mBAAU,EAAC,iBAAiB,CAAC,4CAA4C,IAAI,CAAC,YAAY,KAAK;cAClG,gHAAgH;QAClH,CAAC,CAAC,GAAG,IAAA,mBAAU,EAAC,mBAAmB,CAAC,YAAY,IAAI,CAAC,YAAY,yBAAyB,CAAC;IAC/F,OAAO,GAAG,KAAK;gDAC6B,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,IAAgB,EAAE,IAAY,EAAE,QAAgB;IAC9E,MAAM,UAAU,GAAG,WAAW,QAAQ,OAAO,IAAI,gBAAgB,CAAC;IAClE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACnB,OAAO;cACD,QAAQ,sBAAsB,EAAE;;EAE5C,UAAU;WACD,CAAC;IACR,CAAC;IACD,6EAA6E;IAC7E,uEAAuE;IACvE,oDAAoD;IACpD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,YAAY,YAAY,IAAI,gCAAgC,CAAC;QACpI,OAAO,iDAAiD,IAAA,cAAQ,EAAC,SAAS,CAAC;EACjF,UAAU,EAAE,CAAC;IACX,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACU,QAAA,cAAc,GAAqC;IAC5D,CAAC,eAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IACzB,CAAC,eAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY;IACjC,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC3B,CAAC,eAAQ,CAAC,YAAY,CAAC,EAAE,eAAe;IACxC,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC3B,CAAC,eAAQ,CAAC,IAAI,CAAC,EAAE,WAAW;CAC/B,CAAC;AAEF,8CAA8C;AAC9C,SAAgB,YAAY,CAAC,MAAc;IACvC,OAAO,IAAA,qBAAc,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,YAAoB,EAAE,SAAiB,EAAE,QAA2B;IAC9F,OAAO,CAAC,MAAM,GAAG,YAAY,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAAC,MAAc;IAC7C,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,YAAY,CAAC;AACrB,CAAC;AAED,gFAAgF;AAChF,SAAS,QAAQ,CAAC,GAAkB,EAAE,WAAW,GAAG,EAAE;IAClD,MAAM,IAAI,GAAG,sBAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,gBAAgB,WAAW,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,4BAAmB,CACzB,gBAAgB,GAAG,CAAC,SAAS,WAAW,KAAK,EAAE,EAC/C,mCAAmC,MAAM,CAAC,MAAM,CAAC,sBAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;IACN,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,IAAgB,EAAE,GAAkB,EAAE,WAAW,GAAG,EAAE,EAAE,aAAa,GAAG,KAAK;IAC1G,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QACpC,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,OAAO,sBAAsB,GAAG,CAAC,SAAS,IAAI,CAAC;QAChH,MAAM,MAAM,GAAG,aAAa;YACxB,CAAC,CAAC,yFAAyF,IAAA,cAAQ,EAAC,OAAO,CAAC;iCACvF;YACrB,CAAC,CAAC,iBAAiB,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,OAAO;;;uCAGwB,IAAA,cAAQ,EAAC,OAAO,CAAC;;;;;;EAMtD,MAAM;;mCAE2B,CAAC;IAChC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO;EACT,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,IAAI,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,OAAe;IACxC,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,4BAAmB,CACzB,IAAI,OAAO,qEAAqE;cAC9E,kFAAkF,CACvF,CAAC;IACN,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,QAA2B;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7F,CAAC;IACL,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,EAAU;IAC3C,MAAM,SAAS,GAAG,GAAG,IAAA,mBAAU,EAAC,WAAW,EAAE,OAAO,CAAC,kCAAkC,EAAE,qEAAqE,CAAC;IAC/J,OAAO;;mCAEwB,EAAE;;4CAEO,IAAA,cAAQ,EAAC,SAAS,CAAC,EAAE,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAAC,MAAM,GAAG,MAAM;IACzC,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,QAAQ,GAAG,KAAK,EAAE,MAAM,GAAG,MAAM;IAClE,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,aAAa,CAAC,MAAM,CAAC;EACrB,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;EAC9B,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,mFAAmF;AACnF,SAAgB,mBAAmB,CAAC,QAAQ,GAAG,KAAK;IAChD,MAAM,MAAM,GAAG,CAAC,0BAA0B,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,qCAAqC,CAAC,CAAC;IAC1H,IAAI,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,mDAAmD;AACtC,QAAA,aAAa,GAAG;IACzB,EAAE,EAAE,CAAC;IACL,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,CAAC;IACf,eAAe,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC;CACD,CAAC;AAEX;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,MAAM,GAAG,MAAM;IACjD,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,oFAAoF;AACpF,SAAgB,oBAAoB,CAAC,MAAM,GAAG,MAAM;IAChD,OAAO,GAAG,MAAM;EAClB,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM;EACN,MAAM,SAAS,CAAC;AAClB,CAAC;AAED;;;GAGG;AACU,QAAA,mBAAmB,GAAG;;;;;;;;;;;;;;;CAelC,CAAC;AAEF;;;GAGG;AACU,QAAA,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;CAoBpC,CAAC","sourcesContent":["// The AppleScript fragments more than one macOS operation is built from.\nimport { asString } from './run';\nimport { readProfileAccounts } from './profile';\nimport { failureTag, InvalidRequestError, NotImplementedError } from '../errors';\nimport { FolderId, isOutgoingRoot } from '../mail';\nimport type { ItemFailure, MailFolderRef } from '../types';\n\n/**\n * An account as the generated AppleScript reaches it.\n *\n * `folderIds` carries what Outlook's profile database knows about the mailbox's\n * well-known folders — the only handle on a mailbox the dictionary publishes no\n * account object for (see profile.ts). It is filled in for every account the\n * profile lists, because the generated script chooses between the account\n * object and the folder id at run time; nothing here has to predict which kinds\n * of account a given Outlook build exposes.\n */\nexport interface MacAccount {\n readonly emailAccount: string;\n readonly folderIds?: Readonly<Record<string, number>>;\n}\n\n/** Look an address up in Outlook's profile database, for the folder ids it can add. */\nexport async function resolveMacAccount(emailAccount: string): Promise<MacAccount> {\n const wanted = emailAccount.trim().toLowerCase();\n const found = (await readProfileAccounts())\n .find(account => account.emailAccount.trim().toLowerCase() === wanted);\n return found ? { emailAccount, folderIds: found.folderIds } : { emailAccount };\n}\n\n/**\n * Resolve the account whose address matches into `targetAcct`, inside a\n * `tell application \"Microsoft Outlook\"` block.\n *\n * `every account` errors even in legacy mode, so the typed classes are probed.\n * A `whose email address is …` filter can't be used either: `email address` is\n * also a class name, and AppleScript resolves it as one.\n *\n * A mailbox the dictionary publishes no account object for leaves `targetAcct`\n * as `missing value` rather than failing, provided the profile gave a folder id\n * to reach it by. `needsAccountObject` is for composing mail, which can't work\n * without the object: the account a message is sent from can only be set from\n * it, and a message composed without it goes out from the default mailbox.\n */\nexport function accountLookupSnippet(acct: MacAccount, needsAccountObject = false): string {\n const probe = ` set targetAcct to missing value\n try\n repeat with a in (exchange accounts & imap accounts & pop accounts)\n if (email address of a as string) is ${asString(acct.emailAccount)} then\n set targetAcct to a\n exit repeat\n end if\n end repeat\n end try`;\n if (acct.folderIds && !needsAccountObject) return probe;\n const complaint = acct.folderIds\n ? `${failureTag('INVALID_REQUEST')}Outlook publishes no account object for '${acct.emailAccount}', `\n + 'so the account a message is sent from cannot be set. Its folders can be read; mail cannot be composed from it.'\n : `${failureTag('ACCOUNT_NOT_FOUND')}Account '${acct.emailAccount}' not found in Outlook.`;\n return `${probe}\n if targetAcct is missing value then error ${asString(complaint)}`;\n}\n\n/**\n * Bind `variable` to one of the account's well-known folders: through the\n * account object when the probe found one, else by the folder's own id. `mail\n * folder id N` resolves against the application rather than an account, and N is\n * the id Outlook's profile database records for that folder.\n */\nexport function rootFolderSnippet(acct: MacAccount, term: string, variable: string): string {\n const viaAccount = ` set ${variable} to ${term} of targetAcct`;\n const id = acct.folderIds?.[term];\n if (id !== undefined) {\n return ` if targetAcct is missing value then\n set ${variable} to mail folder id ${id}\n else\n${viaAccount}\n end if`;\n }\n // The profile listed the mailbox but not this root, so the probe is the only\n // way in — and it may have come up empty. Name the folder out of reach\n // rather than let `<term> of missing value` say it.\n if (acct.folderIds) {\n const complaint = `${failureTag('NOT_FOUND', 'folder')}Account '${acct.emailAccount}' has no ${term} folder AppleScript can reach.`;\n return ` if targetAcct is missing value then error ${asString(complaint)}\n${viaAccount}`;\n }\n return viaAccount;\n}\n\n/**\n * Outlook for Mac's dictionary term for each well-known root, by olDefaultFolders\n * id. Verified against the running app: the terms are NOT what the Windows names\n * suggest — `sent mail` and `junk email` don't compile, `sent items` and `junk\n * mail` do — and one bad term fails the whole script at compile time.\n */\nexport const MAC_ROOT_TERMS: Readonly<Record<number, string>> = {\n [FolderId.Inbox]: 'inbox',\n [FolderId.SentMail]: 'sent items',\n [FolderId.Drafts]: 'drafts',\n [FolderId.DeletedItems]: 'deleted items',\n [FolderId.Outbox]: 'outbox',\n [FolderId.Junk]: 'junk mail',\n};\n\n/** The date property a root's items carry. */\nexport function dateProperty(rootId: number): string {\n return isOutgoingRoot(rootId) ? 'time sent' : 'time received';\n}\n\n/**\n * The Windows folder-path shape (`\\\\mailbox\\Inbox\\Invoices`), assembled in\n * TypeScript: escaping backslashes through a template literal and then an\n * AppleScript literal is unreadable, and the parts are known here anyway.\n */\nexport function macFolderPath(emailAccount: string, rootLabel: string, segments: readonly string[]): string {\n return ['\\\\\\\\' + emailAccount, rootLabel, ...segments].join('\\\\');\n}\n\n/**\n * Walk a folder's `container` chain to the top as the list `chainNames`,\n * nearest first. Requires `theFolder`, and leaves `cur` on the folder the walk\n * stopped at: the account's nameless root folder, when it got that far.\n *\n * The chain's last element is the folder directly under the account, and an\n * account can't hold two top-level folders of one name, so comparing that name\n * is exact.\n */\nexport function folderChainSnippet(indent: string): string {\n return `${indent}set chainNames to {}\n${indent}set cur to theFolder\n${indent}set guard to 0\n${indent}repeat while cur is not missing value and guard < 25\n${indent} -- The account's root folder has a name of missing value, and coercing\n${indent} -- that yields the STRING \"missing value\" — so test before coercing.\n${indent} set rawName to missing value\n${indent} try\n${indent} set rawName to name of cur\n${indent} end try\n${indent} if rawName is missing value then exit repeat\n${indent} set nm to rawName as string\n${indent} if nm is \"\" then exit repeat\n${indent} set end of chainNames to nm\n${indent} set nextUp to missing value\n${indent} try\n${indent} set nextUp to container of cur\n${indent} end try\n${indent} set cur to nextUp\n${indent} set guard to guard + 1\n${indent}end repeat`;\n}\n\n/** The dictionary term for a root, or NOT_IMPLEMENTED naming what was asked. */\nfunction rootTerm(ref: MailFolderRef, folderLabel = ''): string {\n const term = MAC_ROOT_TERMS[ref.rootId];\n if (!term) {\n const asked = folderLabel ? ` (asked for '${folderLabel}')` : '';\n throw new NotImplementedError(\n `Reading the '${ref.rootLabel}' folder${asked}`,\n `macOS, whose readable roots are ${Object.values(MAC_ROOT_TERMS).join(', ')}`,\n );\n }\n return term;\n}\n\n/**\n * Resolve `scopeFolder` from `targetAcct`: a well-known root walked down through\n * any further segments. Also binds `scopeCreated`.\n *\n * Names compare with `is`, which is case-insensitive in AppleScript, matching\n * the Windows walk. A missing segment fails as NOT_FOUND rather than falling\n * back to the root; `createMissing` builds the chain instead.\n */\nexport function mailScopeSnippet(acct: MacAccount, ref: MailFolderRef, folderLabel = '', createMissing = false): string {\n const term = rootTerm(ref, folderLabel);\n const walk = ref.segments.map(segment => {\n const complaint = `${failureTag('NOT_FOUND', 'folder')}Folder '${segment}' not found under '${ref.rootLabel}'.`;\n const create = createMissing\n ? ` set foundFolder to (make new mail folder at scopeFolder with properties {name:${asString(segment)}})\n set scopeCreated to true`\n : ` error ${asString(complaint)}`;\n return `\n set foundFolder to missing value\n repeat with sf in (mail folders of scopeFolder)\n if (name of sf as string) is ${asString(segment)} then\n set foundFolder to sf\n exit repeat\n end if\n end repeat\n if foundFolder is missing value then\n${create}\n end if\n set scopeFolder to foundFolder`;\n }).join('');\n return ` set scopeCreated to false\n${rootFolderSnippet(acct, term, 'scopeFolder')}${walk}`;\n}\n\n/**\n * The message id text for a script, or INVALID_REQUEST.\n *\n * Outlook for Mac ids are small integers; a Windows EntryID is refused up front\n * rather than left to fail as a confusing \"not found\", because a caller that\n * persisted one from a Windows run needs to be told exactly that.\n */\nexport function macMessageId(entryId: string): string {\n const id = String(entryId ?? '').trim();\n if (!/^\\d+$/.test(id)) {\n throw new InvalidRequestError(\n `'${entryId}' is not an Outlook for Mac message id. Mac ids are small integers `\n + '(e.g. \"1263\") listed on this machine; a Windows EntryID cannot be resolved here.',\n );\n }\n return id;\n}\n\n/**\n * Split ids into those a script can look up and those that can only fail. A\n * batch reports an unusable id beside a genuine miss rather than throwing and\n * discarding the ids that would have worked.\n */\nexport function partitionMessageIds(entryIds: readonly string[]): { valid: string[]; invalid: ItemFailure[] } {\n const valid: string[] = [];\n const invalid: ItemFailure[] = [];\n for (const entryId of entryIds) {\n try {\n valid.push(macMessageId(entryId));\n } catch (error) {\n invalid.push({ entryId: String(entryId), subject: '', error: (error as Error).message });\n }\n }\n return { valid, invalid };\n}\n\n/**\n * Bind `theMsg` to a message id, or fail as NOT_FOUND. `message id N` resolves\n * against the application, so the message is found wherever it sits.\n */\nexport function messageLookupSnippet(id: string): string {\n const complaint = `${failureTag('NOT_FOUND', 'email')}No email found for message id '${id}'. It may have been deleted - list the mail again for a current id.`;\n return ` set theMsg to missing value\n try\n set theMsg to message id ${id}\n end try\n if theMsg is missing value then error ${asString(complaint)}`;\n}\n\n/**\n * `theMsg`'s sender as `sndName` / `sndAddr`. `sender` is a record, and\n * `address of sender of m` doesn't coerce, so the record is bound first.\n */\nexport function senderSnippet(indent = ' '): string {\n return `${indent}set sndName to \"\"\n${indent}set sndAddr to \"\"\n${indent}try\n${indent} set snd to sender of theMsg\n${indent} try\n${indent} set sndAddr to (address of snd) as string\n${indent} end try\n${indent} try\n${indent} set sndName to (name of snd) as string\n${indent} end try\n${indent}end try`;\n}\n\n/**\n * Everything a reader wants off one message bound to `theMsg`, emitted together\n * with the row it produces (see `messageDetailFields`) so the read order and the\n * positions the decoders index into cannot drift apart. `bodyText` is emitted\n * LAST when asked for, so a stray separator in an earlier field can't shift it.\n */\nexport function messageDetailSnippet(withBody = false, indent = ' '): string {\n return `${indent}set subj to \"\"\n${indent}try\n${indent} set subj to (subject of theMsg) as string\n${indent}end try\n${senderSnippet(indent)}\n${indent}set recvd to \"\"\n${indent}try\n${indent} set recvd to my isoDate(time received of theMsg)\n${indent}on error\n${indent} try\n${indent} set recvd to my isoDate(time sent of theMsg)\n${indent} end try\n${indent}end try\n${indent}set attNames to {}\n${indent}try\n${indent} set attNames to name of every attachment of theMsg\n${indent}end try` + (withBody ? `\n${indent}set bodyText to \"\"\n${indent}try\n${indent} set bodyText to (plain text content of theMsg) as string\n${indent}end try` : '');\n}\n\n/** The fields `messageDetailSnippet` fills, in row order — see `MessageDetail`. */\nexport function messageDetailFields(withBody = false): string[] {\n const fields = ['(id of theMsg as string)', 'subj', 'sndName', 'sndAddr', 'recvd', 'my sanitizePositionalList(attNames)'];\n if (withBody) fields.push('bodyText');\n return fields;\n}\n\n/** Where each of those fields lands in the row. */\nexport const MessageDetail = {\n id: 0,\n subject: 1,\n senderName: 2,\n senderEmail: 3,\n receivedTime: 4,\n attachmentNames: 5,\n body: 6,\n} as const;\n\n/**\n * `theMsg`'s first recipient as `sndName` / `sndAddr` — what outgoing mail\n * reports in place of a sender.\n */\nexport function firstRecipientSnippet(indent = ' '): string {\n return `${indent}set sndName to \"\"\n${indent}set sndAddr to \"\"\n${indent}try\n${indent} set rcps to to recipients of theMsg\n${indent} if (count of rcps) > 0 then\n${indent} set ea to email address of (item 1 of rcps)\n${indent} try\n${indent} set sndAddr to (address of ea) as string\n${indent} end try\n${indent} try\n${indent} set sndName to (name of ea) as string\n${indent} end try\n${indent} end if\n${indent}end try`;\n}\n\n/** Every address `theMsg` was sent to — To, CC and BCC — as the list `addrList`. */\nexport function allRecipientsSnippet(indent = ' '): string {\n return `${indent}set addrList to {}\n${indent}try\n${indent} repeat with r in (every recipient of theMsg)\n${indent} try\n${indent} -- The record is bound before its field is read: a nested\n${indent} -- 'address of (email address of r)' doesn't coerce, and fails\n${indent} -- inside the try as an empty list rather than an error.\n${indent} set ea to email address of r\n${indent} set oneAddr to (address of ea) as string\n${indent} if oneAddr is not \"\" then set end of addrList to oneAddr\n${indent} end try\n${indent} end repeat\n${indent}end try`;\n}\n\n/**\n * Recursive, case-insensitive, depth-capped folder search from `startFolder` —\n * the macOS counterpart of the Windows Find-FolderByName.\n */\nexport const FIND_FOLDER_HANDLER = `\non findFolderByName(startFolder, wantedName, depth)\n tell application \"Microsoft Outlook\"\n set subs to mail folders of startFolder\n end tell\n repeat with f in subs\n if (name of f as string) is wantedName then return f\n end repeat\n if depth is less than or equal to 1 then return missing value\n repeat with f in subs\n set hit to my findFolderByName(f, wantedName, depth - 1)\n if hit is not missing value then return hit\n end repeat\n return missing value\nend findFolderByName\n`;\n\n/**\n * Enumerate the accounts, probing each class separately: legacy Outlook errors\n * on `every account`, and New Outlook returns empty lists for the classes.\n */\nexport const LIST_ACCOUNTS_SNIPPET = `\nset acctList to {}\ntell application \"Microsoft Outlook\"\n repeat with acctClass in {\"exchange\", \"imap\", \"pop\"}\n try\n if (acctClass as string) is \"exchange\" then\n set accts to exchange accounts\n else if (acctClass as string) is \"imap\" then\n set accts to imap accounts\n else\n set accts to pop accounts\n end if\n repeat with a in accts\n try\n set end of acctList to (email address of a as string)\n end try\n end repeat\n end try\n end repeat\nend tell\n`;\n"]}
|
package/dist/mac/send.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReplyRequest, SendRequest } from '../backend';
|
|
2
|
-
import type { ReplyEmailResult } from '../types';
|
|
3
|
-
/** Send, display or file a new email. */
|
|
4
|
-
export declare function sendOutlookEmail(request: SendRequest): Promise<
|
|
2
|
+
import type { ReplyEmailResult, SendEmailResult } from '../types';
|
|
3
|
+
/** Send, display or file a new email; a filed draft reports its id. */
|
|
4
|
+
export declare function sendOutlookEmail(request: SendRequest): Promise<SendEmailResult>;
|
|
5
5
|
/**
|
|
6
6
|
* Reply to an email with the composed HTML above the quoted original.
|
|
7
7
|
*
|
package/dist/mac/send.js
CHANGED
|
@@ -7,25 +7,55 @@ const run_1 = require("./run");
|
|
|
7
7
|
const scripts_1 = require("./scripts");
|
|
8
8
|
const args_1 = require("../shared/args");
|
|
9
9
|
/**
|
|
10
|
-
* What to do with a composed message.
|
|
10
|
+
* What to do with a composed message. A filed draft leaves its id in
|
|
11
|
+
* `filedDraftId` ("" for the other dispositions, or when it can't be told).
|
|
11
12
|
*
|
|
12
13
|
* A new outgoing message lands in Temporary Items, not Drafts — `open` only
|
|
13
14
|
* shows it — so a windowless draft is moved into Drafts explicitly. `move`
|
|
14
15
|
* reports success even where it silently does nothing, so the folder is
|
|
15
|
-
* confirmed to
|
|
16
|
+
* confirmed to hold a message it didn't before rather than report a draft that
|
|
17
|
+
* doesn't exist.
|
|
18
|
+
*
|
|
19
|
+
* Moving rewrites a message's id, so the draft's id is the one Drafts gained.
|
|
20
|
+
* Another draft can land in the same moment — an autosave of a compose window,
|
|
21
|
+
* a sync — and then the subject tells them apart; a tie is left unnamed rather
|
|
22
|
+
* than guessed, since a caller that keeps the id may later send by it.
|
|
16
23
|
*/
|
|
17
24
|
function dispose(variable, disposition) {
|
|
18
25
|
switch (disposition) {
|
|
19
26
|
case 'send':
|
|
20
|
-
return { prelude: '', action: ` send ${variable}` };
|
|
27
|
+
return { prelude: ' set filedDraftId to ""', action: ` send ${variable}` };
|
|
21
28
|
case 'display':
|
|
22
|
-
return { prelude: '', action: ` open ${variable}` };
|
|
29
|
+
return { prelude: ' set filedDraftId to ""', action: ` open ${variable}` };
|
|
23
30
|
case 'save':
|
|
24
31
|
return {
|
|
25
|
-
prelude: ` set
|
|
26
|
-
set
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
prelude: ` set filedDraftId to ""
|
|
33
|
+
set draftsFolder to drafts of targetAcct
|
|
34
|
+
set draftIdsBefore to id of every message of draftsFolder`,
|
|
35
|
+
action: ` set filedSubject to ""
|
|
36
|
+
try
|
|
37
|
+
set filedSubject to (subject of ${variable}) as string
|
|
38
|
+
end try
|
|
39
|
+
move ${variable} to draftsFolder
|
|
40
|
+
-- Bound before the loop, so it walks a local list rather than asking
|
|
41
|
+
-- Outlook for each item in turn.
|
|
42
|
+
set draftIdsAfter to id of every message of draftsFolder
|
|
43
|
+
set newIds to {}
|
|
44
|
+
repeat with anId in draftIdsAfter
|
|
45
|
+
if draftIdsBefore does not contain (contents of anId) then set end of newIds to (contents of anId)
|
|
46
|
+
end repeat
|
|
47
|
+
if (count of newIds) is 0 then error "Outlook did not file the draft in the Drafts folder."
|
|
48
|
+
if (count of newIds) is 1 then
|
|
49
|
+
set filedDraftId to (item 1 of newIds) as string
|
|
50
|
+
else
|
|
51
|
+
set sameSubject to {}
|
|
52
|
+
repeat with anId in newIds
|
|
53
|
+
try
|
|
54
|
+
if ((subject of message id (contents of anId)) as string) is filedSubject then set end of sameSubject to (contents of anId)
|
|
55
|
+
end try
|
|
56
|
+
end repeat
|
|
57
|
+
if (count of sameSubject) is 1 then set filedDraftId to (item 1 of sameSubject) as string
|
|
58
|
+
end if`,
|
|
29
59
|
};
|
|
30
60
|
}
|
|
31
61
|
}
|
|
@@ -39,7 +69,7 @@ function recipientLines(kind, entries) {
|
|
|
39
69
|
return ` make new ${kind} recipient at newMsg with properties {email address:${emailAddress}}`;
|
|
40
70
|
});
|
|
41
71
|
}
|
|
42
|
-
/** Send, display or file a new email. */
|
|
72
|
+
/** Send, display or file a new email; a filed draft reports its id. */
|
|
43
73
|
async function sendOutlookEmail(request) {
|
|
44
74
|
const acct = await (0, scripts_1.resolveMacAccount)(request.account);
|
|
45
75
|
const { prelude, action } = dispose('newMsg', request.disposition);
|
|
@@ -49,7 +79,7 @@ async function sendOutlookEmail(request) {
|
|
|
49
79
|
...recipientLines('bcc', request.bcc),
|
|
50
80
|
...request.attachments.map(file => ` make new attachment at newMsg with properties {file:POSIX file ${(0, run_1.asString)(file)}}`),
|
|
51
81
|
];
|
|
52
|
-
await (0, run_1.runOsaScript)(`
|
|
82
|
+
const raw = await (0, run_1.runOsaScript)(`
|
|
53
83
|
tell application "Microsoft Outlook"
|
|
54
84
|
${(0, scripts_1.accountLookupSnippet)(acct, true)}
|
|
55
85
|
${prelude}
|
|
@@ -57,7 +87,9 @@ ${prelude}
|
|
|
57
87
|
${lines.join('\n')}
|
|
58
88
|
set account of newMsg to targetAcct
|
|
59
89
|
${action}
|
|
90
|
+
return filedDraftId
|
|
60
91
|
end tell`, 'standard');
|
|
92
|
+
return { draftEntryId: raw.trim() };
|
|
61
93
|
}
|
|
62
94
|
/**
|
|
63
95
|
* Reply to an email with the composed HTML above the quoted original.
|
|
@@ -105,9 +137,9 @@ ${prelude}
|
|
|
105
137
|
set subj to (subject of theReply) as string
|
|
106
138
|
end try
|
|
107
139
|
${action}
|
|
108
|
-
return
|
|
140
|
+
return ${(0, run_1.asRow)(['toLine', 'subj', 'repliedTo'])}
|
|
109
141
|
end tell`, 'standard');
|
|
110
|
-
const parts = (0, run_1.
|
|
142
|
+
const parts = (0, run_1.summaryFields)(raw);
|
|
111
143
|
return { to: (0, run_1.field)(parts, 0), subject: (0, run_1.field)(parts, 1), repliedToSender: (0, run_1.field)(parts, 2) };
|
|
112
144
|
}
|
|
113
145
|
//# sourceMappingURL=send.js.map
|
package/dist/mac/send.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/mac/send.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/mac/send.ts"],"names":[],"mappings":"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","sourcesContent":["// Composing outgoing mail on macOS: a new email, and a reply to an existing one.\nimport { asRow, asString, field, runOsaScript, summaryFields } from './run';\nimport { accountLookupSnippet, macMessageId, messageLookupSnippet, resolveMacAccount } from './scripts';\nimport { parseRecipient } from '../shared/args';\nimport type { Disposition, ReplyRequest, SendRequest } from '../backend';\nimport type { ReplyEmailResult, SendEmailResult } from '../types';\n\n/**\n * What to do with a composed message. A filed draft leaves its id in\n * `filedDraftId` (\"\" for the other dispositions, or when it can't be told).\n *\n * A new outgoing message lands in Temporary Items, not Drafts — `open` only\n * shows it — so a windowless draft is moved into Drafts explicitly. `move`\n * reports success even where it silently does nothing, so the folder is\n * confirmed to hold a message it didn't before rather than report a draft that\n * doesn't exist.\n *\n * Moving rewrites a message's id, so the draft's id is the one Drafts gained.\n * Another draft can land in the same moment — an autosave of a compose window,\n * a sync — and then the subject tells them apart; a tie is left unnamed rather\n * than guessed, since a caller that keeps the id may later send by it.\n */\nfunction dispose(variable: string, disposition: Disposition): { prelude: string; action: string } {\n switch (disposition) {\n case 'send':\n return { prelude: ' set filedDraftId to \"\"', action: ` send ${variable}` };\n case 'display':\n return { prelude: ' set filedDraftId to \"\"', action: ` open ${variable}` };\n case 'save':\n return {\n prelude: ` set filedDraftId to \"\"\n set draftsFolder to drafts of targetAcct\n set draftIdsBefore to id of every message of draftsFolder`,\n action: ` set filedSubject to \"\"\n try\n set filedSubject to (subject of ${variable}) as string\n end try\n move ${variable} to draftsFolder\n -- Bound before the loop, so it walks a local list rather than asking\n -- Outlook for each item in turn.\n set draftIdsAfter to id of every message of draftsFolder\n set newIds to {}\n repeat with anId in draftIdsAfter\n if draftIdsBefore does not contain (contents of anId) then set end of newIds to (contents of anId)\n end repeat\n if (count of newIds) is 0 then error \"Outlook did not file the draft in the Drafts folder.\"\n if (count of newIds) is 1 then\n set filedDraftId to (item 1 of newIds) as string\n else\n set sameSubject to {}\n repeat with anId in newIds\n try\n if ((subject of message id (contents of anId)) as string) is filedSubject then set end of sameSubject to (contents of anId)\n end try\n end repeat\n if (count of sameSubject) is 1 then set filedDraftId to (item 1 of sameSubject) as string\n end if`,\n };\n }\n}\n\n/** One `make new … recipient` line per entry, keeping a display name when given. */\nfunction recipientLines(kind: 'to' | 'cc' | 'bcc', entries: readonly string[]): string[] {\n return entries.map(entry => {\n const { name, address } = parseRecipient(entry);\n const emailAddress = name\n ? `{name:${asString(name)}, address:${asString(address)}}`\n : `{address:${asString(address)}}`;\n return ` make new ${kind} recipient at newMsg with properties {email address:${emailAddress}}`;\n });\n}\n\n/** Send, display or file a new email; a filed draft reports its id. */\nexport async function sendOutlookEmail(request: SendRequest): Promise<SendEmailResult> {\n const acct = await resolveMacAccount(request.account);\n const { prelude, action } = dispose('newMsg', request.disposition);\n const lines = [\n ...recipientLines('to', request.to),\n ...recipientLines('cc', request.cc),\n ...recipientLines('bcc', request.bcc),\n ...request.attachments.map(file => ` make new attachment at newMsg with properties {file:POSIX file ${asString(file)}}`),\n ];\n const raw = await runOsaScript(`\ntell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct, true)}\n${prelude}\n set newMsg to make new outgoing message with properties {subject:${asString(request.subject)}, content:${asString(request.htmlBody)}}\n${lines.join('\\n')}\n set account of newMsg to targetAcct\n${action}\n return filedDraftId\nend tell`, 'standard');\n return { draftEntryId: raw.trim() };\n}\n\n/**\n * Reply to an email with the composed HTML above the quoted original.\n *\n * `reply to` builds the same quoted body COM's Reply() returns, so the insertion\n * point is the one thing the platforms must agree on (see WORD_SECTION_ANCHOR).\n * `to` comes back as the reply's resolved addresses: Outlook for Mac exposes\n * recipients as records, and the address is the half worth checking.\n */\nexport async function replyOutlookEmail(request: ReplyRequest): Promise<ReplyEmailResult> {\n const id = macMessageId(request.email.entryId);\n const acct = await resolveMacAccount(request.account);\n const { prelude, action } = dispose('theReply', request.disposition);\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct, true)}\n${messageLookupSnippet(id)}\n set repliedTo to \"\"\n try\n -- Bind the record before reading its field: a nested\n -- 'address of (sender of theMsg)' does not coerce.\n set origSender to sender of theMsg\n set repliedTo to (address of origSender) as string\n end try\n${prelude}\n set theReply to reply to theMsg opening window false ${request.replyAll ? 'reply to all true' : 'without reply to all'}\n -- Neither of these is wrapped in a try. A swallowed account assignment sends\n -- from the default mailbox, and a swallowed insertion files a reply missing\n -- its text — both invisible to the caller if tolerated here.\n set account of theReply to targetAcct\n set content of theReply to my insertAboveQuoted(content of theReply, ${asString(request.html)})\n -- Read the outgoing fields BEFORE acting: sending moves the item, and the\n -- reference can't be read afterwards.\n set toList to {}\n try\n repeat with r in (every to recipient of theReply)\n try\n set ea to email address of r\n set end of toList to (address of ea) as string\n end try\n end repeat\n end try\n set toLine to my joinList(toList, \", \")\n set subj to \"\"\n try\n set subj to (subject of theReply) as string\n end try\n${action}\n return ${asRow(['toLine', 'subj', 'repliedTo'])}\nend tell`, 'standard');\n const parts = summaryFields(raw);\n return { to: field(parts, 0), subject: field(parts, 1), repliedToSender: field(parts, 2) };\n}\n"]}
|
package/dist/mac/templates.js
CHANGED
|
@@ -11,21 +11,12 @@ exports.editEmailTemplate = editEmailTemplate;
|
|
|
11
11
|
// two platforms.
|
|
12
12
|
const run_1 = require("./run");
|
|
13
13
|
const scripts_1 = require("./scripts");
|
|
14
|
+
const templateLimits_1 = require("../shared/templateLimits");
|
|
14
15
|
const templateBody_1 = require("../templateBody");
|
|
15
16
|
const errors_1 = require("../errors");
|
|
16
|
-
/**
|
|
17
|
-
const TEMPLATE_SEARCH_DEPTH = 3;
|
|
18
|
-
/** Cap on one template body, matching Windows. */
|
|
19
|
-
const MAX_TEMPLATE_HTML = 100_000;
|
|
20
|
-
/** Plain text standing in for a body that wasn't asked for. */
|
|
21
|
-
const PREVIEW_CHARS = 200;
|
|
22
|
-
/**
|
|
23
|
-
* Embedded (cid:) images live as attachments on the TEMPLATE item, so its HTML
|
|
24
|
-
* reused elsewhere shows broken-image placeholders. Template emails are text
|
|
25
|
-
* and markup only.
|
|
26
|
-
*/
|
|
17
|
+
/** A template body without its embedded images — see EMBEDDED_IMAGE_SOURCE. */
|
|
27
18
|
function stripEmbeddedImages(html) {
|
|
28
|
-
return html.replace(
|
|
19
|
+
return html.replace(new RegExp(templateLimits_1.EMBEDDED_IMAGE_SOURCE, 'gi'), '');
|
|
29
20
|
}
|
|
30
21
|
/**
|
|
31
22
|
* The template emails in a mailbox folder, newest first; a missing folder is
|
|
@@ -43,7 +34,7 @@ tell application "Microsoft Outlook"
|
|
|
43
34
|
${(0, scripts_1.accountLookupSnippet)(acct)}
|
|
44
35
|
${(0, scripts_1.rootFolderSnippet)(acct, 'root folder', 'rootFolder')}
|
|
45
36
|
end tell
|
|
46
|
-
set theFolder to my findFolderByName(rootFolder, ${(0, run_1.asString)(request.folder)}, ${(0, run_1.asInt)(TEMPLATE_SEARCH_DEPTH)})
|
|
37
|
+
set theFolder to my findFolderByName(rootFolder, ${(0, run_1.asString)(request.folder)}, ${(0, run_1.asInt)(templateLimits_1.TEMPLATE_SEARCH_DEPTH)})
|
|
47
38
|
tell application "Microsoft Outlook"
|
|
48
39
|
if theFolder is missing value then
|
|
49
40
|
set names to {}
|
|
@@ -62,7 +53,10 @@ tell application "Microsoft Outlook"
|
|
|
62
53
|
set modList to {}
|
|
63
54
|
end try
|
|
64
55
|
set hasMods to ((count of modList) is (count of idList))
|
|
65
|
-
|
|
56
|
+
-- The folder may sit up to the search depth down, so its whole chain is
|
|
57
|
+
-- reported, not just its name: the path is the one Windows' FolderPath gives.
|
|
58
|
+
${(0, scripts_1.folderChainSnippet)(' ')}
|
|
59
|
+
set out to ${(0, run_1.asRow)(['"1"', 'my sanitizeList(chainNames)'])}
|
|
66
60
|
repeat with i from 1 to (count of idList)
|
|
67
61
|
set modAt to ""
|
|
68
62
|
if hasMods then set modAt to my isoDate(item i of modList)
|
|
@@ -74,7 +68,10 @@ end tell`, 'standard'));
|
|
|
74
68
|
if ((0, run_1.field)(header, 0) !== '1') {
|
|
75
69
|
return { folderFound: false, folderPath: '', templates: [], availableFolders: (0, run_1.splitList)((0, run_1.field)(header, 1)) };
|
|
76
70
|
}
|
|
77
|
-
const
|
|
71
|
+
const chain = (0, run_1.splitList)((0, run_1.field)(header, 1)).reverse();
|
|
72
|
+
const folderPath = chain.length
|
|
73
|
+
? (0, scripts_1.macFolderPath)(request.account, chain[0], chain.slice(1))
|
|
74
|
+
: (0, scripts_1.macFolderPath)(request.account, request.folder, []);
|
|
78
75
|
const wanted = (request.subject ?? '').toLowerCase();
|
|
79
76
|
const chosen = records.slice(1)
|
|
80
77
|
.map(record => {
|
|
@@ -113,7 +110,7 @@ end tell`, 'standard');
|
|
|
113
110
|
}
|
|
114
111
|
const templates = chosen.map(item => {
|
|
115
112
|
const body = bodies.get(item.id) ?? '';
|
|
116
|
-
const html = request.includeBody ? stripEmbeddedImages(body).slice(0, MAX_TEMPLATE_HTML) : '';
|
|
113
|
+
const html = request.includeBody ? stripEmbeddedImages(body).slice(0, templateLimits_1.MAX_TEMPLATE_HTML) : '';
|
|
117
114
|
// With the HTML in hand it is authoritative (markers survive Word
|
|
118
115
|
// splitting them across tags); without it, the plain text is scanned,
|
|
119
116
|
// where a marker can't have been split.
|
|
@@ -122,7 +119,7 @@ end tell`, 'standard');
|
|
|
122
119
|
entryId: item.id,
|
|
123
120
|
subject: item.subject,
|
|
124
121
|
htmlBody: html,
|
|
125
|
-
bodyPreview: request.includeBody ? '' : body.trim().slice(0,
|
|
122
|
+
bodyPreview: request.includeBody ? '' : body.trim().slice(0, templateLimits_1.TEMPLATE_PREVIEW_CHARS),
|
|
126
123
|
sections: markers.sections,
|
|
127
124
|
placeholders: markers.placeholders,
|
|
128
125
|
lastModified: item.lastModified,
|
|
@@ -141,7 +138,7 @@ tell application "Microsoft Outlook"
|
|
|
141
138
|
${(0, scripts_1.accountLookupSnippet)(acct)}
|
|
142
139
|
${(0, scripts_1.rootFolderSnippet)(acct, 'root folder', 'rootFolder')}
|
|
143
140
|
end tell
|
|
144
|
-
set theFolder to my findFolderByName(rootFolder, ${(0, run_1.asString)(request.folder)}, ${(0, run_1.asInt)(TEMPLATE_SEARCH_DEPTH)})
|
|
141
|
+
set theFolder to my findFolderByName(rootFolder, ${(0, run_1.asString)(request.folder)}, ${(0, run_1.asInt)(templateLimits_1.TEMPLATE_SEARCH_DEPTH)})
|
|
145
142
|
tell application "Microsoft Outlook"
|
|
146
143
|
set wasCreated to false
|
|
147
144
|
if theFolder is missing value then
|