@dawnlit/outlook-bridge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +253 -0
  3. package/dist/OutlookService.d.ts +43 -0
  4. package/dist/OutlookService.js +137 -0
  5. package/dist/OutlookService.js.map +1 -0
  6. package/dist/errors.d.ts +112 -0
  7. package/dist/errors.js +140 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.js +71 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/mac/accounts.d.ts +5 -0
  13. package/dist/mac/accounts.js +17 -0
  14. package/dist/mac/accounts.js.map +1 -0
  15. package/dist/mac/attachments.d.ts +28 -0
  16. package/dist/mac/attachments.js +120 -0
  17. package/dist/mac/attachments.js.map +1 -0
  18. package/dist/mac/bounces.d.ts +32 -0
  19. package/dist/mac/bounces.js +285 -0
  20. package/dist/mac/bounces.js.map +1 -0
  21. package/dist/mac/cleanup.d.ts +29 -0
  22. package/dist/mac/cleanup.js +219 -0
  23. package/dist/mac/cleanup.js.map +1 -0
  24. package/dist/mac/drafts.d.ts +27 -0
  25. package/dist/mac/drafts.js +214 -0
  26. package/dist/mac/drafts.js.map +1 -0
  27. package/dist/mac/folders.d.ts +28 -0
  28. package/dist/mac/folders.js +127 -0
  29. package/dist/mac/folders.js.map +1 -0
  30. package/dist/mac/index.d.ts +22 -0
  31. package/dist/mac/index.js +119 -0
  32. package/dist/mac/index.js.map +1 -0
  33. package/dist/mac/read.d.ts +46 -0
  34. package/dist/mac/read.js +406 -0
  35. package/dist/mac/read.js.map +1 -0
  36. package/dist/mac/run.d.ts +64 -0
  37. package/dist/mac/run.js +250 -0
  38. package/dist/mac/run.js.map +1 -0
  39. package/dist/mac/scripts.d.ts +137 -0
  40. package/dist/mac/scripts.js +337 -0
  41. package/dist/mac/scripts.js.map +1 -0
  42. package/dist/mac/send.d.ts +23 -0
  43. package/dist/mac/send.js +135 -0
  44. package/dist/mac/send.js.map +1 -0
  45. package/dist/mac/signatures.d.ts +4 -0
  46. package/dist/mac/signatures.js +36 -0
  47. package/dist/mac/signatures.js.map +1 -0
  48. package/dist/mac/templates.d.ts +34 -0
  49. package/dist/mac/templates.js +266 -0
  50. package/dist/mac/templates.js.map +1 -0
  51. package/dist/mail.d.ts +72 -0
  52. package/dist/mail.js +131 -0
  53. package/dist/mail.js.map +1 -0
  54. package/dist/outlookTemplateSections.d.ts +62 -0
  55. package/dist/outlookTemplateSections.js +313 -0
  56. package/dist/outlookTemplateSections.js.map +1 -0
  57. package/dist/runtime.d.ts +76 -0
  58. package/dist/runtime.js +123 -0
  59. package/dist/runtime.js.map +1 -0
  60. package/dist/shared/attachmentMatch.d.ts +32 -0
  61. package/dist/shared/attachmentMatch.js +50 -0
  62. package/dist/shared/attachmentMatch.js.map +1 -0
  63. package/dist/shared/bounceRules.d.ts +33 -0
  64. package/dist/shared/bounceRules.js +104 -0
  65. package/dist/shared/bounceRules.js.map +1 -0
  66. package/dist/shared/capabilities.d.ts +3 -0
  67. package/dist/shared/capabilities.js +9 -0
  68. package/dist/shared/capabilities.js.map +1 -0
  69. package/dist/shared/json.d.ts +11 -0
  70. package/dist/shared/json.js +45 -0
  71. package/dist/shared/json.js.map +1 -0
  72. package/dist/shared/replyBody.d.ts +49 -0
  73. package/dist/shared/replyBody.js +113 -0
  74. package/dist/shared/replyBody.js.map +1 -0
  75. package/dist/types.d.ts +365 -0
  76. package/dist/types.js +13 -0
  77. package/dist/types.js.map +1 -0
  78. package/dist/windows/accounts.d.ts +2 -0
  79. package/dist/windows/accounts.js +22 -0
  80. package/dist/windows/accounts.js.map +1 -0
  81. package/dist/windows/attachments.d.ts +28 -0
  82. package/dist/windows/attachments.js +141 -0
  83. package/dist/windows/attachments.js.map +1 -0
  84. package/dist/windows/bounces.d.ts +34 -0
  85. package/dist/windows/bounces.js +267 -0
  86. package/dist/windows/bounces.js.map +1 -0
  87. package/dist/windows/cleanup.d.ts +29 -0
  88. package/dist/windows/cleanup.js +165 -0
  89. package/dist/windows/cleanup.js.map +1 -0
  90. package/dist/windows/drafts.d.ts +29 -0
  91. package/dist/windows/drafts.js +253 -0
  92. package/dist/windows/drafts.js.map +1 -0
  93. package/dist/windows/folders.d.ts +16 -0
  94. package/dist/windows/folders.js +88 -0
  95. package/dist/windows/folders.js.map +1 -0
  96. package/dist/windows/index.d.ts +27 -0
  97. package/dist/windows/index.js +100 -0
  98. package/dist/windows/index.js.map +1 -0
  99. package/dist/windows/read.d.ts +54 -0
  100. package/dist/windows/read.js +372 -0
  101. package/dist/windows/read.js.map +1 -0
  102. package/dist/windows/run.d.ts +54 -0
  103. package/dist/windows/run.js +161 -0
  104. package/dist/windows/run.js.map +1 -0
  105. package/dist/windows/scripts.d.ts +56 -0
  106. package/dist/windows/scripts.js +163 -0
  107. package/dist/windows/scripts.js.map +1 -0
  108. package/dist/windows/send.d.ts +11 -0
  109. package/dist/windows/send.js +114 -0
  110. package/dist/windows/send.js.map +1 -0
  111. package/dist/windows/signatures.d.ts +14 -0
  112. package/dist/windows/signatures.js +69 -0
  113. package/dist/windows/signatures.js.map +1 -0
  114. package/dist/windows/templates.d.ts +25 -0
  115. package/dist/windows/templates.js +246 -0
  116. package/dist/windows/templates.js.map +1 -0
  117. package/package.json +50 -0
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AS_HANDLERS = exports.AS_LIST_SEP = exports.AS_RECORD_SEP = exports.AS_FIELD_SEP = exports.LIST_SEP = exports.RECORD_SEP = exports.FIELD_SEP = void 0;
7
+ exports.runOsaScript = runOsaScript;
8
+ exports.asEscape = asEscape;
9
+ exports.asBool = asBool;
10
+ exports.asRow = asRow;
11
+ exports.splitRecords = splitRecords;
12
+ exports.splitFields = splitFields;
13
+ exports.splitList = splitList;
14
+ exports.field = field;
15
+ exports.summaryFields = summaryFields;
16
+ exports.intField = intField;
17
+ exports.boolField = boolField;
18
+ // Getting a generated AppleScript to osascript and its output back.
19
+ //
20
+ // The macOS counterpart of windows/run.ts: the run itself, the escaping rules,
21
+ // and the record framing every reader here shares.
22
+ const child_process_1 = require("child_process");
23
+ const fs_1 = __importDefault(require("fs"));
24
+ const runtime_1 = require("../runtime");
25
+ const errors_1 = require("../errors");
26
+ const replyBody_1 = require("../shared/replyBody");
27
+ const RUNNER = 'osascript';
28
+ /**
29
+ * Run an AppleScript via a temp file (avoids arg-length and quoting limits).
30
+ *
31
+ * `AS_HANDLERS` is prepended here rather than by each caller — the Windows runner
32
+ * already owns its UTF-8 prelude the same way. It matters more on this side: a
33
+ * script missing a handler fails at COMPILE time for the WHOLE script, with a
34
+ * message pointing nowhere near the omission, so "remember to paste the handlers"
35
+ * was a footgun every new script had to survive.
36
+ *
37
+ * `timeout` overrides the configured default for this one call; see `configure()`
38
+ * for that and for the stdout cap.
39
+ */
40
+ function runOsaScript(source, timeout) {
41
+ // The full text is what osascript compiled, so it is also what the error's
42
+ // line numbers refer to and what the debug hook and ScriptError must carry.
43
+ const script = exports.AS_HANDLERS + source;
44
+ const scriptFile = (0, runtime_1.tempFile)('osa', 'applescript');
45
+ fs_1.default.writeFileSync(scriptFile, script, 'utf-8');
46
+ const { timeoutMs, maxBufferBytes, signal } = (0, runtime_1.getConfig)();
47
+ const effectiveTimeout = timeout ?? timeoutMs;
48
+ const startedAt = Date.now();
49
+ return new Promise((resolve, reject) => {
50
+ (0, child_process_1.execFile)('osascript', [scriptFile], { maxBuffer: maxBufferBytes, timeout: effectiveTimeout, signal }, (error, stdout, stderr) => {
51
+ const durationMs = Date.now() - startedAt;
52
+ try {
53
+ fs_1.default.unlinkSync(scriptFile);
54
+ }
55
+ catch { /* ignore */
56
+ }
57
+ if (error) {
58
+ // Running from a file, osascript prefixes the script path:
59
+ // "/tmp/outlook-bridge-osa-1.applescript:12:34: execution error:
60
+ // Microsoft Outlook got an error: … (-1728)". Keep just the human
61
+ // part — these strings reach the user in per-email failure lists.
62
+ const msg = (stderr || error.message)
63
+ .replace(/^(?:.*?:)?\d+:\d+:\s*execution error:\s*/m, '')
64
+ .trim();
65
+ const failure = (0, errors_1.classifyRunFailure)({
66
+ runner: RUNNER,
67
+ script,
68
+ stderr: msg,
69
+ durationMs,
70
+ nodeError: error,
71
+ timeoutMs: effectiveTimeout,
72
+ signal,
73
+ });
74
+ (0, runtime_1.reportRun)({ runner: RUNNER, script, durationMs, error: failure.message });
75
+ reject(failure);
76
+ }
77
+ else {
78
+ (0, runtime_1.reportRun)({ runner: RUNNER, script, durationMs });
79
+ resolve(stdout.replace(/\n$/, ''));
80
+ }
81
+ });
82
+ });
83
+ }
84
+ /** Escape a string for embedding inside an AppleScript double-quoted literal. */
85
+ function asEscape(s) {
86
+ return s
87
+ .replace(/\\/g, '\\\\')
88
+ .replace(/"/g, '\\"')
89
+ .replace(/\r\n|\r|\n/g, '\\n');
90
+ }
91
+ /** AppleScript's boolean literals. */
92
+ function asBool(value) {
93
+ return value ? 'true' : 'false';
94
+ }
95
+ // Control characters as separators: subjects and bodies contain tabs, newlines
96
+ // and commas, but never these. Every emitted field also passes through the
97
+ // `sanitize` handler below, which is what makes the framing safe rather than
98
+ // merely unlikely to break.
99
+ exports.FIELD_SEP = '\u001f';
100
+ exports.RECORD_SEP = '\u001e';
101
+ exports.LIST_SEP = '\u001d';
102
+ /** The same three, as AppleScript expressions. */
103
+ exports.AS_FIELD_SEP = '(character id 31)';
104
+ exports.AS_RECORD_SEP = '(character id 30)';
105
+ exports.AS_LIST_SEP = '(character id 29)';
106
+ /**
107
+ * Emit one record: the AppleScript expressions in `fields`, separated and
108
+ * terminated so `splitRecords`/`splitFields` can take them apart again.
109
+ *
110
+ * Every field goes through `sanitize`, which is what makes the framing safe
111
+ * rather than merely unlikely to break. A field holding a LIST must be built
112
+ * with `my sanitizeList(...)`, which cleans the elements instead — `sanitize`
113
+ * deliberately leaves the list separator alone.
114
+ */
115
+ function asRow(fields) {
116
+ return fields
117
+ .map(f => `my sanitize(${f})`)
118
+ .join(` & ${exports.AS_FIELD_SEP} & `) + ` & ${exports.AS_RECORD_SEP}`;
119
+ }
120
+ /**
121
+ * The AppleScript handlers every script here relies on. Called with `my` from
122
+ * inside a `tell` block.
123
+ *
124
+ * `isoDate` produces the zero-padded 'yyyy-MM-dd HH:mm' both platforms' readers
125
+ * return; `sanitize` strips the framing characters; `joinList` and `replaceText`
126
+ * are the text-item-delimiter dance nobody should write twice.
127
+ */
128
+ exports.AS_HANDLERS = `
129
+ on pad2(n)
130
+ set s to (n as integer) as string
131
+ if (length of s) < 2 then set s to "0" & s
132
+ return s
133
+ end pad2
134
+
135
+ on isoDate(d)
136
+ if d is missing value then return ""
137
+ return (year of d as string) & "-" & pad2(month of d as integer) & "-" & pad2(day of d) & " " & pad2(hours of d) & ":" & pad2(minutes of d)
138
+ end isoDate
139
+
140
+ on joinList(lst, sep)
141
+ set saved to AppleScript's text item delimiters
142
+ set AppleScript's text item delimiters to sep
143
+ set out to lst as string
144
+ set AppleScript's text item delimiters to saved
145
+ return out
146
+ end joinList
147
+
148
+ on replaceText(t, findWhat, replaceWith)
149
+ set saved to AppleScript's text item delimiters
150
+ set AppleScript's text item delimiters to findWhat
151
+ set parts to text items of t
152
+ set AppleScript's text item delimiters to replaceWith
153
+ set out to parts as string
154
+ set AppleScript's text item delimiters to saved
155
+ return out
156
+ end replaceText
157
+
158
+ -- Strips the FIELD and RECORD separators only. The LIST separator is left
159
+ -- alone on purpose: a field may legitimately BE a list, and stripping 29 here
160
+ -- collapsed every such field into one run-on string.
161
+ on sanitize(v)
162
+ if v is missing value then return ""
163
+ set t to v as string
164
+ repeat with codePoint in {30, 31}
165
+ set marker to (character id (codePoint as integer))
166
+ if t contains marker then set t to my replaceText(t, marker, " ")
167
+ end repeat
168
+ return t
169
+ end sanitize
170
+
171
+ -- A list field: each element loses all three separators, then they are joined
172
+ -- with the LIST separator that splitList() takes them apart on.
173
+ on sanitizeList(lst)
174
+ set cleaned to {}
175
+ repeat with item_ in lst
176
+ set t to my sanitize(item_)
177
+ repeat with codePoint in {29}
178
+ set marker to (character id (codePoint as integer))
179
+ if t contains marker then set t to my replaceText(t, marker, " ")
180
+ end repeat
181
+ set end of cleaned to t
182
+ end repeat
183
+ return my joinList(cleaned, (character id 29))
184
+ end sanitizeList
185
+
186
+ on insertAboveQuoted(c, ins)
187
+ if c is missing value then return ins
188
+ set c to c as string
189
+ if (length of c) is 0 then return ins
190
+ -- Outlook builds a reply as a document whose own empty paragraph sits inside
191
+ -- WordSection1; inserting straight after that tag puts the new text where the
192
+ -- user's cursor would have been. Anything else falls back to just inside <body>.
193
+ -- 'at' is a reserved AppleScript parameter name, so the cut point cannot be
194
+ -- called that however naturally it reads.
195
+ set cutPoint to my tagEnd(c, "${replyBody_1.WORD_SECTION_ANCHOR}")
196
+ if cutPoint is 0 then set cutPoint to my tagEnd(c, "<body")
197
+ if cutPoint is 0 then return ins & c
198
+ if cutPoint is (length of c) then return c & ins
199
+ return (text 1 thru cutPoint of c) & ins & (text (cutPoint + 1) thru -1 of c)
200
+ end insertAboveQuoted
201
+
202
+ -- 'rest' is an AppleScript term (rest of list), so the remainder cannot be
203
+ -- called that: assigning to it compiles and then fails at run time.
204
+ on tagEnd(c, marker)
205
+ set ix to offset of marker in c
206
+ if ix is 0 then return 0
207
+ if marker ends with ">" then return ix + (length of marker) - 1
208
+ set tailText to text ix thru -1 of c
209
+ set gt to offset of ">" in tailText
210
+ if gt is 0 then return 0
211
+ return ix + gt - 1
212
+ end tagEnd
213
+ `;
214
+ /** Split a script's output into records, dropping the trailing empty one. */
215
+ function splitRecords(raw) {
216
+ return raw.split(exports.RECORD_SEP).filter(record => record.trim() !== '');
217
+ }
218
+ /** Split one record into its fields. */
219
+ function splitFields(record) {
220
+ return record.split(exports.FIELD_SEP);
221
+ }
222
+ /** Split one field that carries a list. */
223
+ function splitList(value) {
224
+ return (value || '').split(exports.LIST_SEP).filter(Boolean);
225
+ }
226
+ /** A field by position — a missing field reads as ''. */
227
+ function field(fields, index) {
228
+ return fields[index] ?? '';
229
+ }
230
+ /**
231
+ * The fields of a script's ONE summary record — the shape every mutation here
232
+ * returns (counts first, then any per-item failures as further records).
233
+ */
234
+ function summaryFields(raw) {
235
+ return splitFields(splitRecords(raw)[0] ?? '');
236
+ }
237
+ /** A numeric field, defaulting to `fallback` when absent or unparsable. */
238
+ function intField(fields, index, fallback = 0) {
239
+ const parsed = Number.parseInt(field(fields, index), 10);
240
+ return Number.isNaN(parsed) ? fallback : parsed;
241
+ }
242
+ /**
243
+ * A boolean field. AppleScript renders booleans as the bare words `true`/`false`,
244
+ * so this is the counterpart of `shared/json.ts`'s coercions for the framed
245
+ * output — the Windows side gets those free from ConvertFrom-Json.
246
+ */
247
+ function boolField(fields, index) {
248
+ return field(fields, index).trim() === 'true';
249
+ }
250
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/mac/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ import type { MailFolderRef } from '../types';
2
+ /**
3
+ * Resolve the account whose SMTP address matches, or raise. Emitted into a
4
+ * `tell application "Microsoft Outlook"` block; binds `targetAcct`.
5
+ *
6
+ * `every account` errors even in legacy mode, so probe the typed classes. A
7
+ * `whose email address is ...` filter can't be used either: `email address` is
8
+ * also a class name, and AppleScript resolves it as one ("into type specifier").
9
+ *
10
+ * The thrown sentence is the one `classifyRunFailure` recognises to raise
11
+ * `AccountNotFoundError`, so its wording is load-bearing.
12
+ */
13
+ export declare function accountLookupSnippet(emailAccount: string): string;
14
+ /**
15
+ * Outlook for Mac's dictionary term for each well-known root, keyed by the
16
+ * olDefaultFolders id `mailFolderRef` resolves.
17
+ *
18
+ * Verified against the running app. The terms are NOT the ones the Windows ids
19
+ * suggest — `sent mail` and `junk email` do not compile at all, while
20
+ * `sent items` and `junk mail` do, and a bad term fails the whole script at
21
+ * compile time rather than at the offending line.
22
+ */
23
+ export declare const MAC_ROOT_TERMS: Record<number, string>;
24
+ /** The date property a folder's items actually carry. */
25
+ export declare function dateProperty(rootId: number): string;
26
+ /**
27
+ * The Windows `FolderPath` shape (`\\mailbox\Inbox\Invoices`), built here rather
28
+ * than in AppleScript — escaping backslashes through a template literal and then
29
+ * an AppleScript literal is unreadable, and TS already knows the parts.
30
+ */
31
+ export declare function macFolderPath(emailAccount: string, rootLabel: string, segments: string[]): string;
32
+ /** The dictionary term for a root, or a NOT_IMPLEMENTED naming what was asked. */
33
+ export declare function rootTerm(ref: MailFolderRef, folderLabel?: string): string;
34
+ /**
35
+ * Emit the AppleScript that resolves `scopeFolder` from `targetAcct`, walking a
36
+ * well-known root down through any further path segments. Also binds
37
+ * `scopeCreated`.
38
+ *
39
+ * Folder names are compared with `is`, which is case-insensitive in AppleScript —
40
+ * matching the Windows walk's `-ieq` so 'invoices' finds 'Invoices' on both.
41
+ * A missing segment errors by name instead of falling back to the root: silently
42
+ * returning the Inbox for a caller that scoped to one folder hands back the wrong
43
+ * emails under a name that says otherwise. `createMissing` builds the whole
44
+ * chain instead, so a nested destination is one call.
45
+ */
46
+ export declare function mailScopeSnippet(ref: MailFolderRef, folderLabel?: string, createMissing?: boolean): string;
47
+ /**
48
+ * The message-id text for a script, or an InvalidRequestError.
49
+ *
50
+ * Outlook for Mac ids are small integers; a Windows MAPI EntryID is rejected up
51
+ * front rather than left to fail as a confusing "not found", because a caller
52
+ * that persisted one from a Windows run needs to be told exactly that.
53
+ */
54
+ export declare function macMessageId(entryId: string): string;
55
+ /**
56
+ * Split ids into the ones a script can look up and the ones that can only fail.
57
+ *
58
+ * The per-id operations report failures rather than throwing, so an unusable id
59
+ * belongs in the result's `failed` list beside a genuine lookup miss — not as an
60
+ * exception that discards the ids that would have worked.
61
+ */
62
+ export declare function partitionMessageIds(entryIds: readonly string[]): {
63
+ valid: string[];
64
+ invalid: {
65
+ entryId: string;
66
+ error: string;
67
+ }[];
68
+ };
69
+ /**
70
+ * Resolve `theMsg` from a macOS message id, or raise.
71
+ *
72
+ * `message id N` resolves against the application rather than one folder, so the
73
+ * message is found wherever it currently sits — including a subfolder.
74
+ */
75
+ export declare function messageLookupSnippet(id: string, variable?: string): string;
76
+ /**
77
+ * The sender's display name and address, as `sndName` / `sndAddr`.
78
+ *
79
+ * `sender` yields a record, and `address of sender of m` fails to coerce, so the
80
+ * record has to be bound first. `name` is absent when there is no display name.
81
+ */
82
+ export declare function senderSnippet(messageVariable?: string, indent?: string): string;
83
+ /**
84
+ * Everything a reader wants off ONE message already bound to `theMsg`, and the
85
+ * row it produces — emitted together so the read order and the positions the
86
+ * TypeScript decoders index into cannot drift apart.
87
+ *
88
+ * Three callers share it (`readEmailBody`, `readSelectedEmail`, and the
89
+ * attachment resolver) and differ only in how they bind `theMsg`. They used to
90
+ * share it by copy: thirty lines repeated, with the `time received` → `time sent`
91
+ * fallback and the field order restated each time, so a dictionary fix reached
92
+ * one reader and not the others.
93
+ *
94
+ * `bodyText` is emitted LAST when asked for, so a stray separator in an earlier
95
+ * field cannot shift it.
96
+ */
97
+ export declare function messageDetailSnippet(withBody?: boolean, indent?: string): string;
98
+ /**
99
+ * The fields `messageDetailSnippet` fills, in row order. The decoders read them
100
+ * back by the positions in `MessageDetail`.
101
+ */
102
+ export declare function messageDetailFields(withBody?: boolean): string[];
103
+ /** Where each of those fields lands in the emitted row. */
104
+ export declare const MessageDetail: {
105
+ readonly id: 0;
106
+ readonly subject: 1;
107
+ readonly senderName: 2;
108
+ readonly senderEmail: 3;
109
+ readonly receivedTime: 4;
110
+ readonly attachmentNames: 5;
111
+ readonly body: 6;
112
+ };
113
+ /**
114
+ * The first recipient's name and address, as `sndName` / `sndAddr` — what
115
+ * outgoing mail reports in place of a sender, matching the Windows reader's
116
+ * contract for Sent Items (a folder of mail from yourself is unreadable).
117
+ */
118
+ export declare function firstRecipientSnippet(messageVariable?: string, indent?: string): string;
119
+ /**
120
+ * Every SMTP address a message was addressed to, as the list `addrList`.
121
+ *
122
+ * `every recipient` covers To, CC and BCC — the full set, which is the whole
123
+ * point of readSentRecipientGroups.
124
+ */
125
+ export declare function allRecipientsSnippet(messageVariable?: string, indent?: string): string;
126
+ /**
127
+ * Recursive folder-by-name search from `startFolder`, case-insensitive and
128
+ * depth-capped — the macOS counterpart of the Windows Find-FolderByName, used to
129
+ * resolve a template folder anywhere in the mailbox tree.
130
+ */
131
+ export declare 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";
132
+ /**
133
+ * Account enumeration only works when Outlook runs in legacy mode; New Outlook
134
+ * errors on `every account` and returns empty lists for the typed classes, so
135
+ * each class is probed independently and failures are ignored.
136
+ */
137
+ export declare 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";