@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
package/LICENSE ADDED
@@ -0,0 +1,190 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing
141
+ the origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ Copyright 2026 Dawnlit
179
+
180
+ Licensed under the Apache License, Version 2.0 (the "License");
181
+ you may not use this file except in compliance with the License.
182
+ You may obtain a copy of the License at
183
+
184
+ http://www.apache.org/licenses/LICENSE-2.0
185
+
186
+ Unless required by applicable law or agreed to in writing, software
187
+ distributed under the License is distributed on an "AS IS" BASIS,
188
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189
+ See the License for the specific language governing permissions and
190
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # @dawnlit/outlook-bridge
2
+
3
+ Drive a real, locally installed Outlook client from Node — read the inbox, send and reply to mail, manage drafts, work
4
+ with signatures and template emails, file and delete messages. No Graph API, no app registration, no cloud permissions:
5
+ this automates the desktop client itself, the same way a person would.
6
+
7
+ - **Windows** — via PowerShell + Outlook's COM object model.
8
+ - **macOS** — via AppleScript. The whole surface is ported, with two differences no capability flag can express (see
9
+ [Platform differences](#platform-differences)). Requires **legacy** Outlook for Mac: New Outlook implements only a
10
+ slice of the AppleScript dictionary — accounts don't enumerate and the inbox reports 0 messages — so calls fail
11
+ loudly with `ACCOUNT_NOT_FOUND` there rather than quietly doing the wrong thing.
12
+ - Any other platform — `capabilities()` reports everything false and every call rejects with `UNSUPPORTED_PLATFORM`.
13
+
14
+ ## Install
15
+
16
+ Install straight off GitHub `main`, rather than a versioned release:
17
+
18
+ ```bash
19
+ npm install github:dawnlit-ai/outlook-bridge#main
20
+ ```
21
+
22
+ `prepare` runs `npm run build` automatically on install, so `dist/` is built from that checked-out
23
+ source with no separate step. npm resolves the branch to a commit and pins it in `package-lock.json`,
24
+ so a later plain `npm install` won't pick up new commits on its own — re-run the command above
25
+ (naming the package and `#main` explicitly) whenever you want to advance to the current tip.
26
+
27
+ Requires Node 24+ and a real Outlook installation on the machine running it — this is desktop automation, not a hosted
28
+ API client.
29
+
30
+ ## Usage
31
+
32
+ ```ts
33
+ import { getOutlookAccounts, readInboxEmails, sendOutlookEmail } from '@dawnlit/outlook-bridge';
34
+
35
+ const accounts = await getOutlookAccounts();
36
+
37
+ const emails = await readInboxEmails(accounts[0]);
38
+
39
+ await sendOutlookEmail({
40
+ emailAccount: accounts[0],
41
+ to: 'someone@example.com', // comma- or semicolon-separated
42
+ subject: 'Hello from @dawnlit/outlook-bridge',
43
+ htmlBody: '<p>Sent by driving the Outlook client directly.</p>',
44
+ sendImmediately: false, // false leaves it in Drafts
45
+ });
46
+ ```
47
+
48
+ Every function is exposed under one signature regardless of platform — the dispatcher pins both implementations to the
49
+ same `OutlookBridge` interface, so nothing here returns a per-platform union you have to narrow.
50
+
51
+ ## Platform differences
52
+
53
+ Both platforms implement the whole contract, so `capabilities()` is all-true on Windows and on macOS. It still exists,
54
+ and is still worth asking, because it answers for the machine you are actually on — on any other OS every entry is
55
+ false and every call rejects:
56
+
57
+ ```ts
58
+ import { createOutlookBridge } from '@dawnlit/outlook-bridge';
59
+
60
+ const bridge = createOutlookBridge();
61
+
62
+ if (bridge.supports('searchInboxByFilter')) { /* … */ }
63
+
64
+ bridge.capabilities(); // { readInboxEmails: true, replyOutlookEmail: true, … }
65
+ ```
66
+
67
+ The map is derived from `keyof OutlookBridge`, so a function added to the contract fails both platform maps at
68
+ compile time rather than quietly defaulting to supported.
69
+
70
+ Two things differ between the platforms that no flag can express, and code moving between them has to know both:
71
+
72
+ **Ids are not portable.** Windows returns MAPI `EntryID` strings; macOS returns Outlook for Mac's small integer message
73
+ ids (`"1263"`). Each platform rejects the other's with `INVALID_REQUEST` rather than failing later as a confusing "not
74
+ found". `storeId` has no macOS equivalent: it is returned as `''` and accepted-and-ignored wherever it is a parameter.
75
+ Don't persist an id from one platform and look it up on the other.
76
+
77
+ **`searchInboxByFilter` filters in-process on macOS.** Windows hands `subjectLike` and the date window to Outlook's
78
+ server-side `Items.Restrict`; AppleScript has no counterpart, so the macOS walk indexes each folder with bulk property
79
+ reads and applies the same tests here. Same results, different cost — a `daysBack` of 0 over a large mailbox tree is
80
+ considerably heavier on macOS.
81
+
82
+ Two smaller notes: `replyOutlookEmail` reports `to` as the reply's resolved recipient addresses on macOS rather than the
83
+ display-name string Windows reports; and `editEmailTemplate` on macOS files the edited draft when you answer Outlook's
84
+ own "save this message?" prompt on close, where Windows asks for Ctrl+S.
85
+
86
+ ## Configuration
87
+
88
+ Each call generates a script and shells out to an interpreter. That leaves four things otherwise out of your reach:
89
+ how long a run may take, how much it may print, how to call it off, and what the script actually said.
90
+
91
+ `createOutlookBridge()` gives you those on an instance no other caller in the process can disturb:
92
+
93
+ ```ts
94
+ import { createOutlookBridge } from '@dawnlit/outlook-bridge';
95
+
96
+ const bridge = createOutlookBridge({
97
+ timeoutMs: 120_000, // default per-run ceiling; 0 disables
98
+ maxBufferBytes: 32 * 1024 * 1024, // raise before a scan that returns thousands of bodies
99
+ tempDir: '/var/tmp/outlook', // scratch scripts and default attachment destination
100
+ debug: (e) => log(e.script), // every generated script, its duration, and any error
101
+ });
102
+
103
+ await bridge.readInboxEmails(account);
104
+ ```
105
+
106
+ `bridge.withOptions({ … })` derives a bridge with some settings changed — how one call gets its own budget, or its
107
+ own cancellation:
108
+
109
+ ```ts
110
+ const controller = new AbortController();
111
+ cancelButton.onclick = () => controller.abort();
112
+
113
+ await bridge.withOptions({ signal: controller.signal }).searchInboxByFilter(account, filter);
114
+ // → rejects with an AbortedError (code 'ABORTED'), interpreter killed
115
+ ```
116
+
117
+ The same functions are also exported directly, running against a process-wide config that `configure()` sets. That is
118
+ the simpler thing for a program that owns its process; prefer `createOutlookBridge` in anything sharing a process
119
+ with code you do not own.
120
+
121
+ ```ts
122
+ import { configure, readInboxEmails } from '@dawnlit/outlook-bridge';
123
+
124
+ configure({ timeoutMs: 60_000 });
125
+ await readInboxEmails(account);
126
+ ```
127
+
128
+ `OUTLOOK_BRIDGE_DEBUG=1` in the environment turns on script logging to stderr without a code change.
129
+
130
+ Calls that carry a genuinely different budget (a full-mailbox walk, a purge) keep their own timeout and ignore
131
+ `timeoutMs`. `searchInboxByFilter` is the one most likely to push against `maxBufferBytes`, since it returns whole
132
+ message bodies.
133
+
134
+ ## Errors
135
+
136
+ Every deliberate failure is an `OutlookError` carrying a stable `code`. **The codes are the API; the messages are
137
+ not** — branch on `code`, never on message text.
138
+
139
+ ```ts
140
+ import { OutlookError } from '@dawnlit/outlook-bridge';
141
+
142
+ try {
143
+ await bridge.replyOutlookEmail(params);
144
+ } catch (error) {
145
+ if (!(error instanceof OutlookError)) throw error; // a real bug
146
+ switch (error.code) {
147
+ case 'ACCOUNT_NOT_FOUND': return promptForAccount(error.account);
148
+ case 'NOT_IMPLEMENTED': return degrade(error.operation);
149
+ case 'ABORTED': return;
150
+ case 'SCRIPT_FAILED': return report(error.script, error.stderr);
151
+ }
152
+ }
153
+ ```
154
+
155
+ | code | class | meaning |
156
+ | --- | --- | --- |
157
+ | `UNSUPPORTED_PLATFORM` | `UnsupportedPlatformError` | No Outlook automation exists on this OS. |
158
+ | `NOT_IMPLEMENTED` | `NotImplementedError` | The platform could, but this corner isn't written. Carries `operation`. Now only reachable for a folder root macOS has no term for (Journal and the like). |
159
+ | `ACCOUNT_NOT_FOUND` | `AccountNotFoundError` | No configured account matches. Carries `account`. |
160
+ | `NOT_FOUND` | `NotFoundError` | A folder, template, signature or item did not resolve. Carries `kind`. |
161
+ | `INVALID_REQUEST` | `InvalidRequestError` | The arguments cannot produce a call; nothing was attempted. |
162
+ | `SCRIPT_FAILED` | `ScriptError` | The interpreter ran and failed. Carries `script`, `stderr`, `runner`, `durationMs`. |
163
+ | `TIMEOUT` | `TimeoutError` | The run exceeded its budget and was killed. Carries `timeoutMs`. |
164
+ | `ABORTED` | `AbortedError` | The caller's `AbortSignal` fired. |
165
+
166
+ `ScriptError` carries the generated script verbatim — the thing you actually want when one fires, and otherwise
167
+ reachable only if you wired up a `debug` hook in advance.
168
+
169
+ ## Module format
170
+
171
+ Published as CommonJS. ESM consumers can use named imports normally (`import { sendOutlookEmail } from …`); Node
172
+ resolves them off the CJS build.
173
+
174
+ There is deliberately no dual ESM/CJS build. This package identifies its errors with `instanceof`, and a dual-format
175
+ package can load two copies of itself into one process — at which point `error instanceof OutlookError` returns
176
+ `false` for errors the package itself threw. One format avoids that failure entirely.
177
+
178
+ ## API
179
+
180
+ **Accounts & inbox** — `getOutlookAccounts`, `readInboxEmails`, `readEmailBody`,
181
+ `listInboxFolders`, `moveOutlookEmails`, `openOutlookEmail`.
182
+
183
+ **Search & selection** — `searchInboxByFilter` (walks every folder under the Inbox for one
184
+ account, filtering by subject pattern/date window/reply-exclusion/attachment presence — the
185
+ building block for "find the emails matching X" without knowing which subfolder holds them),
186
+ `readSelectedEmail` (the email currently selected or open in Outlook).
187
+
188
+ **Sending & replying** — `sendOutlookEmail`, `replyOutlookEmail` (answers the sender; pass `replyAll: true` to answer
189
+ every recipient), `sendAllDrafts`.
190
+
191
+ **Drafts** — `listOutlookDrafts`, `deleteOutlookDrafts`.
192
+
193
+ **Attachments** — `saveEmailAttachment`, `saveEmailAttachmentDetailed`, `saveEmailAttachments`
194
+ (the same, batched into one COM round trip for several attachments off one email). All take an optional `destDir`,
195
+ created if absent. Without one, each call saves into a fresh private directory — attachments keep the name the sender
196
+ gave them, so a shared folder means two emails carrying `invoice.pdf` overwrite each other.
197
+
198
+ **Signatures & templates** — `listOutlookSignatures`, `readOutlookSignatureHtml`,
199
+ `readTemplateEmails`, `saveTemplateEmail`, `editEmailTemplate` (opens the template in a real Outlook compose window,
200
+ waits for the user to close it, and returns the saved HTML — so it has no timeout by default; give it an
201
+ `AbortSignal` if you need a way to give up).
202
+
203
+ **Bounce handling** — `cleanUndeliverableEmails`, `collectBouncedRecipients`,
204
+ `readSentRecipientGroups`.
205
+
206
+ **Mailbox cleanup** — `deleteOutlookEmails`, `purgeDeletedItems`.
207
+
208
+ **Template-section parsing** — a small pure-string toolkit for templates that carry several reply variants between
209
+ `[[SECTION]] ... [[/SECTION]]` markers around one shared greeting/signature, with `{{PLACEHOLDER}}` tokens filled in by
210
+ the caller: `findTemplateMarkers`, `composeTemplateBody`, `findTokens`,
211
+ `findUnfilledTokens`, `replaceToken`, `removeTokenLine`.
212
+
213
+ **Platform-neutral helpers** — usable with no Outlook session at all: `mailFolderRef` (parse any folder string a user
214
+ might type into a well-known root plus segments), `splitQuotedOriginal` (separate a reply's own text from the thread
215
+ quoted below it), `WELL_KNOWN_FOLDERS`.
216
+
217
+ **Instances, capabilities and errors** — `createOutlookBridge` (a bridge with its own settings; see
218
+ [Configuration](#configuration)), `capabilities` / `supports`, and the `OutlookError` family
219
+ (see [Errors](#errors)).
220
+
221
+ Every exported type (`InboxEmail`, `ReplyEmailParams`, `MailFolderRef`, `OutlookBridge`, `CapabilityMap`,
222
+ `OutlookErrorCode`, etc.) is exported alongside its function.
223
+
224
+ ## Development
225
+
226
+ ```bash
227
+ npm run build # tsc → dist/
228
+ npm test # build, then node:test over the platform-independent parts
229
+ ```
230
+
231
+ The tests cover the parts that need no Outlook session — folder-string parsing, quote splitting, template
232
+ composition, scratch-file handling, the error taxonomy and its run classifier, capability maps, config scoping, and
233
+ the shape of the PowerShell the folder walk emits — so they run anywhere, with or without Outlook installed.
234
+
235
+ On a **Mac with Outlook installed** they additionally compile every AppleScript the macOS implementation generates.
236
+ The runner is stubbed, each operation is driven with plausible arguments, and the captured scripts go through
237
+ `osacompile` — which resolves terminology against the real dictionary without opening a session, sending anything or
238
+ touching a message. This is worth the trouble because one bad dictionary term fails the WHOLE script at compile time
239
+ rather than at the offending line, so a live failure never names the thing that caused it. Those tests skip
240
+ automatically elsewhere.
241
+
242
+ Two guards over the same captured scripts run **everywhere**, with no Outlook needed, because they cover the
243
+ failures compiling cannot catch — both of which shipped once and only surfaced against a live mailbox: assigning to a
244
+ reserved AppleScript word (`set rest to …` parses, then fails at run time), and reading a record field through a
245
+ nested accessor (`address of (sender of m)` does not coerce, and inside a `try` that means a silently empty sender).
246
+
247
+ What no test can cover is the automation itself: driving a real Outlook client is the whole point of the package, and
248
+ behaviour against a live mailbox — that a `move` really filed the mail, that a reply threaded correctly — is verified
249
+ by running it, not in CI.
250
+
251
+ ## License
252
+
253
+ Apache-2.0 © Dawnlit
@@ -0,0 +1,43 @@
1
+ import type { BridgeOptions, ResolvedConfig } from './runtime';
2
+ import type { BridgeCapability, CapabilityMap, OutlookBridge } from './types';
3
+ /** Which operations work on this machine. See `CapabilityMap`. */
4
+ export declare function capabilities(): CapabilityMap;
5
+ /** Whether one operation works here — `capabilities()` for a single name. */
6
+ export declare function supports(operation: BridgeCapability): boolean;
7
+ /**
8
+ * An Outlook bridge carrying its own settings, plus capability discovery.
9
+ *
10
+ * The free functions exported below are the same automation against the
11
+ * process-wide config; this is what you want when the process holds more than
12
+ * one caller, or when a call needs its own timeout or AbortSignal.
13
+ */
14
+ export interface OutlookBridgeInstance extends OutlookBridge {
15
+ /** The settings this instance runs with. */
16
+ readonly options: Readonly<ResolvedConfig>;
17
+ /** Which operations work on this machine. */
18
+ capabilities(): CapabilityMap;
19
+ /** Whether one operation works here. */
20
+ supports(operation: BridgeCapability): boolean;
21
+ /**
22
+ * A bridge like this one with some settings changed — the per-call escape
23
+ * hatch, and how a cancellable call is made:
24
+ * `bridge.withOptions({ signal }).searchInboxByFilter(...)`.
25
+ */
26
+ withOptions(options: BridgeOptions): OutlookBridgeInstance;
27
+ }
28
+ /**
29
+ * A bridge with its own settings, isolated from `configure()` and from every
30
+ * other instance.
31
+ *
32
+ * ```ts
33
+ * const bridge = createOutlookBridge({ timeoutMs: 30_000 });
34
+ * if (bridge.supports('searchInboxByFilter')) {
35
+ * await bridge.withOptions({ signal }).searchInboxByFilter(account, filter);
36
+ * }
37
+ * ```
38
+ *
39
+ * Options left out fall back to the process-wide values as they stand when this
40
+ * is called.
41
+ */
42
+ export declare function createOutlookBridge(options?: BridgeOptions): OutlookBridgeInstance;
43
+ export declare const getOutlookAccounts: () => Promise<string[]>, sendOutlookEmail: (params: import("./types").SendEmailParams) => Promise<void>, replyOutlookEmail: (params: import("./types").ReplyEmailParams) => Promise<import("./types").ReplyEmailResult>, sendAllDrafts: (emailAccount: string) => Promise<import("./types").SendAllDraftsResult>, readInboxEmails: (emailAccount: string, daysBack?: number, limit?: number, folder?: string) => Promise<import("./types").InboxEmail[]>, searchInboxByFilter: (emailAccount: string, filter?: import("./types").InboxSearchFilter, daysBack?: number) => Promise<import("./types").InboxSearchMatch[]>, readSelectedEmail: () => Promise<import("./types").SelectedEmail>, readEmailBody: (entryId: string, storeId?: string, maxChars?: number, includeQuoted?: boolean) => Promise<import("./types").EmailBodyResult>, openOutlookEmail: (entryId: string) => Promise<void>, listInboxFolders: (emailAccount: string, maxDepth?: number) => Promise<import("./types").InboxFolderInfo[]>, moveOutlookEmails: (emailAccount: string, entryIds: string[], folderName: string, createIfMissing?: boolean) => Promise<import("./types").MoveEmailsResult>, listOutlookDrafts: (emailAccount: string, limit?: number, previewChars?: number) => Promise<import("./types").ListDraftsResult>, deleteOutlookDrafts: (emailAccount: string, entryIds: string[]) => Promise<import("./types").DeleteDraftsResult>, deleteOutlookEmails: (emailAccount: string, entryIds: string[], options?: import("./types").DeleteMailOptions) => Promise<import("./types").DeleteMailResult>, purgeDeletedItems: (emailAccount: string, olderThanDays?: number, dryRun?: boolean) => Promise<import("./types").PurgeDeletedItemsResult>, saveEmailAttachment: (entryId: string, fileName: string, storeId?: string, destDir?: string) => Promise<string>, saveEmailAttachmentDetailed: (entryId: string, fileName: string, storeId?: string, destDir?: string) => Promise<import("./types").SavedAttachment>, saveEmailAttachments: (entryId: string, fileNames: string[], storeId?: string, destDir?: string) => Promise<import("./types").SavedAttachment[]>, cleanUndeliverableEmails: (emailAccount: string, daysBack?: number, dryRun?: boolean) => Promise<import("./types").CleanUndeliverableResult>, collectBouncedRecipients: (emailAccount: string, daysBack?: number, scanDeleted?: boolean) => Promise<string[]>, readSentRecipientGroups: (emailAccount: string, daysBack?: number, limit?: number) => Promise<import("./types").SentRecipientGroup[]>, listOutlookSignatures: () => Promise<string[]>, readOutlookSignatureHtml: (name: string) => Promise<string>, readTemplateEmails: (emailAccount: string, folderName?: string, limit?: number, includeBody?: boolean, subject?: string) => Promise<import("./types").TemplateFolderResult>, saveTemplateEmail: (emailAccount: string, subject: string, htmlBody: string, folderName?: string) => Promise<import("./types").SaveTemplateResult>, editEmailTemplate: (label: string, currentHtml: string) => Promise<string>;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.editEmailTemplate = exports.saveTemplateEmail = exports.readTemplateEmails = exports.readOutlookSignatureHtml = exports.listOutlookSignatures = exports.readSentRecipientGroups = exports.collectBouncedRecipients = exports.cleanUndeliverableEmails = exports.saveEmailAttachments = exports.saveEmailAttachmentDetailed = exports.saveEmailAttachment = exports.purgeDeletedItems = exports.deleteOutlookEmails = exports.deleteOutlookDrafts = exports.listOutlookDrafts = exports.moveOutlookEmails = exports.listInboxFolders = exports.openOutlookEmail = exports.readEmailBody = exports.readSelectedEmail = exports.searchInboxByFilter = exports.readInboxEmails = exports.sendAllDrafts = exports.replyOutlookEmail = exports.sendOutlookEmail = exports.getOutlookAccounts = void 0;
37
+ exports.capabilities = capabilities;
38
+ exports.supports = supports;
39
+ exports.createOutlookBridge = createOutlookBridge;
40
+ // Platform dispatcher for Outlook automation: Windows drives Outlook via
41
+ // PowerShell + COM, macOS via AppleScript (see each implementation's index for
42
+ // its platform notes — New Outlook for Mac supports composing but not mailbox
43
+ // reading). Other platforms report no capabilities and every call rejects.
44
+ //
45
+ // Both implementations are pinned to `OutlookBridge` here rather than being
46
+ // destructured straight off the module namespaces. That is the difference
47
+ // between a consumer seeing `Promise<CleanUndeliverableResult>` and seeing
48
+ // `Promise<CleanUndeliverableResult | { matched: unknown[] }>` — a union of
49
+ // whatever the two platforms happened to declare, which is what this used to
50
+ // publish.
51
+ const windowsBridge = __importStar(require("./windows"));
52
+ const macBridge = __importStar(require("./mac"));
53
+ const runtime_1 = require("./runtime");
54
+ const errors_1 = require("./errors");
55
+ /** Every operation name, taken from the Windows bridge — the complete one. */
56
+ const ALL_CAPABILITIES = Object.keys(windowsBridge.bridge);
57
+ /**
58
+ * The backend for an OS with no Outlook automation at all.
59
+ *
60
+ * A third implementation rather than a fallback to the PowerShell one: making
61
+ * Windows the default for Linux and everything else meant the dispatcher held a
62
+ * bridge whose capability map had to be second-guessed afterwards, and whose
63
+ * functions each had to remember to refuse. Answering "not here" is itself an
64
+ * implementation of the contract, so it is written as one, once.
65
+ */
66
+ const unsupportedBridge = {
67
+ bridge: Object.fromEntries(ALL_CAPABILITIES.map(name => [
68
+ name,
69
+ () => Promise.reject(new errors_1.UnsupportedPlatformError(process.platform)),
70
+ ])),
71
+ capabilities: Object.freeze(Object.fromEntries(ALL_CAPABILITIES.map(name => [name, false]))),
72
+ };
73
+ // The platform decision, made once. Everything below reads `impl` and
74
+ // `implCapabilities` without asking which OS this is.
75
+ const { bridge: impl, capabilities: implCapabilities } = process.platform === 'win32' ? windowsBridge
76
+ : process.platform === 'darwin' ? macBridge
77
+ : unsupportedBridge;
78
+ /** Which operations work on this machine. See `CapabilityMap`. */
79
+ function capabilities() {
80
+ return implCapabilities;
81
+ }
82
+ /** Whether one operation works here — `capabilities()` for a single name. */
83
+ function supports(operation) {
84
+ return implCapabilities[operation] === true;
85
+ }
86
+ /**
87
+ * Build a bridge whose every call runs with `config` in force.
88
+ *
89
+ * The wrapper is what makes per-instance settings work at all: the platform
90
+ * implementations read their config from a module-level accessor, so the config
91
+ * has to be established around the call rather than passed into it. `withConfig`
92
+ * puts it in an AsyncLocalStorage that the whole async subtree inherits, which is
93
+ * why two bridges with different timeouts can run concurrently without seeing
94
+ * each other's.
95
+ */
96
+ function build(config) {
97
+ const instance = {
98
+ capabilities,
99
+ supports,
100
+ withOptions: (options) => build((0, runtime_1.mergeOptions)(config, options)),
101
+ options: Object.freeze({ ...config }),
102
+ };
103
+ const source = impl;
104
+ for (const name of ALL_CAPABILITIES) {
105
+ const fn = source[name];
106
+ instance[name] = (...args) => {
107
+ // Errors thrown synchronously (an argument check ahead of the first
108
+ // await) become rejections here, so a caller has one failure channel.
109
+ try {
110
+ return (0, runtime_1.withConfig)(config, () => fn(...args));
111
+ }
112
+ catch (error) {
113
+ return Promise.reject(error);
114
+ }
115
+ };
116
+ }
117
+ return instance;
118
+ }
119
+ /**
120
+ * A bridge with its own settings, isolated from `configure()` and from every
121
+ * other instance.
122
+ *
123
+ * ```ts
124
+ * const bridge = createOutlookBridge({ timeoutMs: 30_000 });
125
+ * if (bridge.supports('searchInboxByFilter')) {
126
+ * await bridge.withOptions({ signal }).searchInboxByFilter(account, filter);
127
+ * }
128
+ * ```
129
+ *
130
+ * Options left out fall back to the process-wide values as they stand when this
131
+ * is called.
132
+ */
133
+ function createOutlookBridge(options = {}) {
134
+ return build((0, runtime_1.mergeOptions)((0, runtime_1.getGlobalConfig)(), options));
135
+ }
136
+ exports.getOutlookAccounts = impl.getOutlookAccounts, exports.sendOutlookEmail = impl.sendOutlookEmail, exports.replyOutlookEmail = impl.replyOutlookEmail, exports.sendAllDrafts = impl.sendAllDrafts, exports.readInboxEmails = impl.readInboxEmails, exports.searchInboxByFilter = impl.searchInboxByFilter, exports.readSelectedEmail = impl.readSelectedEmail, exports.readEmailBody = impl.readEmailBody, exports.openOutlookEmail = impl.openOutlookEmail, exports.listInboxFolders = impl.listInboxFolders, exports.moveOutlookEmails = impl.moveOutlookEmails, exports.listOutlookDrafts = impl.listOutlookDrafts, exports.deleteOutlookDrafts = impl.deleteOutlookDrafts, exports.deleteOutlookEmails = impl.deleteOutlookEmails, exports.purgeDeletedItems = impl.purgeDeletedItems, exports.saveEmailAttachment = impl.saveEmailAttachment, exports.saveEmailAttachmentDetailed = impl.saveEmailAttachmentDetailed, exports.saveEmailAttachments = impl.saveEmailAttachments, exports.cleanUndeliverableEmails = impl.cleanUndeliverableEmails, exports.collectBouncedRecipients = impl.collectBouncedRecipients, exports.readSentRecipientGroups = impl.readSentRecipientGroups, exports.listOutlookSignatures = impl.listOutlookSignatures, exports.readOutlookSignatureHtml = impl.readOutlookSignatureHtml, exports.readTemplateEmails = impl.readTemplateEmails, exports.saveTemplateEmail = impl.saveTemplateEmail, exports.editEmailTemplate = impl.editEmailTemplate;
137
+ //# sourceMappingURL=OutlookService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OutlookService.js","sourceRoot":"","sources":["../src/OutlookService.ts"],"names":[],"mappings":"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"}