@dawnlit/outlook-bridge 1.1.1 → 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 +152 -183
- package/dist/backend.d.ts +151 -0
- package/dist/backend.js +3 -0
- package/dist/backend.js.map +1 -0
- package/dist/bridge.d.ts +56 -0
- package/dist/bridge.js +507 -0
- package/dist/bridge.js.map +1 -0
- package/dist/errors.d.ts +79 -43
- package/dist/errors.js +93 -52
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +25 -52
- package/dist/index.js.map +1 -1
- package/dist/mac/accounts.d.ts +7 -2
- package/dist/mac/accounts.js +23 -6
- package/dist/mac/accounts.js.map +1 -1
- package/dist/mac/attachments.d.ts +5 -25
- package/dist/mac/attachments.js +40 -99
- package/dist/mac/attachments.js.map +1 -1
- package/dist/mac/bounces.d.ts +12 -27
- package/dist/mac/bounces.js +96 -117
- package/dist/mac/bounces.js.map +1 -1
- package/dist/mac/cleanup.d.ts +11 -25
- package/dist/mac/cleanup.js +44 -107
- package/dist/mac/cleanup.js.map +1 -1
- package/dist/mac/drafts.d.ts +15 -34
- package/dist/mac/drafts.js +113 -186
- package/dist/mac/drafts.js.map +1 -1
- package/dist/mac/folders.d.ts +12 -21
- package/dist/mac/folders.js +44 -59
- package/dist/mac/folders.js.map +1 -1
- package/dist/mac/index.d.ts +2 -22
- package/dist/mac/index.js +19 -81
- package/dist/mac/index.js.map +1 -1
- package/dist/mac/profile.d.ts +13 -0
- package/dist/mac/profile.js +149 -0
- package/dist/mac/profile.js.map +1 -0
- package/dist/mac/read.d.ts +21 -37
- package/dist/mac/read.js +198 -216
- package/dist/mac/read.js.map +1 -1
- package/dist/mac/run.d.ts +51 -38
- package/dist/mac/run.js +138 -103
- package/dist/mac/run.js.map +1 -1
- package/dist/mac/scripts.d.ts +90 -91
- package/dist/mac/scripts.js +167 -126
- package/dist/mac/scripts.js.map +1 -1
- package/dist/mac/send.d.ts +10 -20
- package/dist/mac/send.js +99 -89
- package/dist/mac/send.js.map +1 -1
- package/dist/mac/signatures.d.ts +2 -2
- package/dist/mac/signatures.js +9 -11
- package/dist/mac/signatures.js.map +1 -1
- package/dist/mac/templates.d.ts +14 -26
- package/dist/mac/templates.js +79 -120
- package/dist/mac/templates.js.map +1 -1
- package/dist/mail.d.ts +80 -46
- package/dist/mail.js +179 -73
- package/dist/mail.js.map +1 -1
- package/dist/runtime.d.ts +76 -43
- package/dist/runtime.js +103 -48
- package/dist/runtime.js.map +1 -1
- package/dist/shared/args.d.ts +48 -0
- package/dist/shared/args.js +216 -0
- package/dist/shared/args.js.map +1 -0
- package/dist/shared/attachmentMatch.d.ts +26 -20
- package/dist/shared/attachmentMatch.js +60 -23
- package/dist/shared/attachmentMatch.js.map +1 -1
- package/dist/shared/bounceReport.d.ts +11 -0
- package/dist/shared/bounceReport.js +45 -0
- package/dist/shared/bounceReport.js.map +1 -0
- package/dist/shared/bounceRules.d.ts +38 -10
- package/dist/shared/bounceRules.js +50 -32
- package/dist/shared/bounceRules.js.map +1 -1
- package/dist/shared/exec.d.ts +21 -0
- package/dist/shared/exec.js +47 -0
- package/dist/shared/exec.js.map +1 -0
- package/dist/shared/json.d.ts +17 -6
- package/dist/shared/json.js +35 -24
- package/dist/shared/json.js.map +1 -1
- package/dist/shared/locate.d.ts +31 -0
- package/dist/shared/locate.js +128 -0
- package/dist/shared/locate.js.map +1 -0
- package/dist/shared/replyBody.d.ts +31 -36
- package/dist/shared/replyBody.js +83 -72
- 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 +69 -0
- package/dist/{outlookTemplateSections.js → templateBody.js} +80 -73
- package/dist/templateBody.js.map +1 -0
- package/dist/types.d.ts +381 -168
- package/dist/types.js +8 -9
- package/dist/types.js.map +1 -1
- package/dist/windows/accounts.d.ts +7 -12
- package/dist/windows/accounts.js +19 -34
- package/dist/windows/accounts.js.map +1 -1
- package/dist/windows/attachments.d.ts +9 -24
- package/dist/windows/attachments.js +94 -119
- package/dist/windows/attachments.js.map +1 -1
- package/dist/windows/bounces.d.ts +13 -26
- package/dist/windows/bounces.js +168 -200
- package/dist/windows/bounces.js.map +1 -1
- package/dist/windows/cleanup.d.ts +23 -23
- package/dist/windows/cleanup.js +99 -113
- package/dist/windows/cleanup.js.map +1 -1
- package/dist/windows/drafts.d.ts +16 -35
- package/dist/windows/drafts.js +156 -253
- package/dist/windows/drafts.js.map +1 -1
- package/dist/windows/folders.d.ts +8 -13
- package/dist/windows/folders.js +44 -52
- package/dist/windows/folders.js.map +1 -1
- package/dist/windows/index.d.ts +2 -27
- package/dist/windows/index.js +11 -66
- package/dist/windows/index.js.map +1 -1
- package/dist/windows/read.d.ts +24 -60
- package/dist/windows/read.js +265 -306
- package/dist/windows/read.js.map +1 -1
- package/dist/windows/run.d.ts +38 -40
- package/dist/windows/run.js +151 -112
- package/dist/windows/run.js.map +1 -1
- package/dist/windows/scripts.d.ts +65 -55
- package/dist/windows/scripts.js +109 -85
- package/dist/windows/scripts.js.map +1 -1
- package/dist/windows/send.d.ts +9 -9
- package/dist/windows/send.js +76 -88
- package/dist/windows/send.js.map +1 -1
- package/dist/windows/signatures.d.ts +4 -10
- package/dist/windows/signatures.js +30 -37
- package/dist/windows/signatures.js.map +1 -1
- package/dist/windows/templates.d.ts +12 -18
- package/dist/windows/templates.js +117 -150
- package/dist/windows/templates.js.map +1 -1
- package/package.json +5 -4
- package/dist/OutlookService.d.ts +0 -43
- package/dist/OutlookService.js +0 -137
- package/dist/OutlookService.js.map +0 -1
- package/dist/outlookTemplateSections.d.ts +0 -62
- package/dist/outlookTemplateSections.js.map +0 -1
- package/dist/shared/capabilities.d.ts +0 -3
- package/dist/shared/capabilities.js +0 -9
- package/dist/shared/capabilities.js.map +0 -1
|
@@ -4,245 +4,212 @@ exports.readTemplateEmails = readTemplateEmails;
|
|
|
4
4
|
exports.saveTemplateEmail = saveTemplateEmail;
|
|
5
5
|
exports.editEmailTemplate = editEmailTemplate;
|
|
6
6
|
// Template emails: ordinary mail items kept in a mailbox folder and reused as
|
|
7
|
-
//
|
|
7
|
+
// email bodies, plus the compose-window editor for one.
|
|
8
8
|
const run_1 = require("./run");
|
|
9
9
|
const scripts_1 = require("./scripts");
|
|
10
10
|
const json_1 = require("../shared/json");
|
|
11
|
-
const
|
|
11
|
+
const templateLimits_1 = require("../shared/templateLimits");
|
|
12
|
+
const templateBody_1 = require("../templateBody");
|
|
12
13
|
const mail_1 = require("../mail");
|
|
13
14
|
const errors_1 = require("../errors");
|
|
14
15
|
const runtime_1 = require("../runtime");
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* caller can ask the user whether to create it rather than fail.
|
|
17
|
+
* The template emails in a mailbox folder, newest first. A missing folder is
|
|
18
|
+
* reported as folderFound:false with the mailbox's top-level folder names
|
|
19
|
+
* rather than thrown, so a caller can offer to create it.
|
|
20
20
|
*/
|
|
21
|
-
async function readTemplateEmails(
|
|
22
|
-
(0, run_1.
|
|
23
|
-
const cap = (0, mail_1.clamp)(limit, 1, 50);
|
|
24
|
-
const wanted = (subject || '').trim();
|
|
25
|
-
const script = `${(0, scripts_1.accountScript)(emailAccount)}
|
|
21
|
+
async function readTemplateEmails(request) {
|
|
22
|
+
const output = await (0, run_1.runPowerShellJson)(`${(0, scripts_1.accountScript)(request.account)}
|
|
26
23
|
${scripts_1.DELIVERY_STORE_PS}
|
|
27
24
|
$root = $store.GetRootFolder()
|
|
28
25
|
${scripts_1.FIND_FOLDER_PS}
|
|
29
|
-
$folder = Find-FolderByName $root
|
|
26
|
+
$folder = Find-FolderByName $root ${(0, run_1.psString)(request.folder)} ${(0, run_1.psInt)(templateLimits_1.TEMPLATE_SEARCH_DEPTH)}
|
|
30
27
|
if ($folder -eq $null) {
|
|
31
28
|
$names = @()
|
|
32
|
-
foreach ($f in $root.Folders) { $names += $f.Name }
|
|
33
|
-
ConvertTo-Json @{ folderFound = $false; folderPath = ''; templates = @(); availableFolders = $names }
|
|
29
|
+
foreach ($f in $root.Folders) { $names += [string]$f.Name }
|
|
30
|
+
ConvertTo-Json -Compress -Depth 3 -InputObject ([PSCustomObject]@{ folderFound = $false; folderPath = ''; templates = @(); availableFolders = @($names) })
|
|
34
31
|
exit 0
|
|
35
32
|
}
|
|
36
|
-
$includeBody = ${(0, run_1.psBool)(includeBody)}
|
|
37
|
-
$wanted =
|
|
33
|
+
$includeBody = ${(0, run_1.psBool)(request.includeBody)}
|
|
34
|
+
$wanted = ${(0, run_1.psString)(request.subject ?? '')}
|
|
35
|
+
$limit = ${(0, run_1.psInt)(request.limit)}
|
|
36
|
+
$maxHtml = ${(0, run_1.psInt)(templateLimits_1.MAX_TEMPLATE_HTML)}
|
|
37
|
+
$previewChars = ${(0, run_1.psInt)(templateLimits_1.TEMPLATE_PREVIEW_CHARS)}
|
|
38
38
|
$items = $folder.Items
|
|
39
39
|
$items.Sort('[LastModificationTime]', $true)
|
|
40
|
-
$
|
|
41
|
-
# Without a subject filter the sort order does the capping (newest first). With one,
|
|
42
|
-
# scan the whole folder — the wanted template need not be among the newest — and stop
|
|
43
|
-
# as soon as the cap is filled.
|
|
40
|
+
$rows = @()
|
|
44
41
|
$count = $items.Count
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
# Without a subject the sort does the capping, newest first. With one, the whole
|
|
43
|
+
# folder is scanned — the template wanted need not be among the newest.
|
|
44
|
+
for ($i = 1; $i -le $count -and $rows.Count -lt $limit; $i++) {
|
|
47
45
|
$item = $null
|
|
48
46
|
try { $item = $items.Item($i) } catch { continue }
|
|
49
47
|
if ($item -eq $null) { continue }
|
|
50
|
-
$
|
|
51
|
-
try { $
|
|
52
|
-
if ($
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if ($subj -eq $null) { $subj = '' }
|
|
57
|
-
if ($subj.Trim() -ine $wanted) { continue }
|
|
58
|
-
}
|
|
48
|
+
$class = 0
|
|
49
|
+
try { $class = [int]$item.Class } catch {}
|
|
50
|
+
if ($class -ne 43) { continue }
|
|
51
|
+
$subject = ''
|
|
52
|
+
try { $subject = ([string]$item.Subject).Trim() } catch {}
|
|
53
|
+
if ($wanted -and $subject -ine $wanted) { continue }
|
|
59
54
|
$html = ''
|
|
60
55
|
$preview = ''
|
|
61
56
|
$markers = ''
|
|
62
|
-
$plain = ''
|
|
63
57
|
if ($includeBody) {
|
|
64
58
|
try { $html = [string]$item.HTMLBody } catch {}
|
|
65
|
-
# Embedded (cid:) images
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
$html = [regex]::Replace($html, '<img[^>]*src="cid:[^"]*"[^>]*>', '')
|
|
70
|
-
if ($html.Length -gt 100000) { $html = $html.Substring(0, 100000) }
|
|
59
|
+
# Embedded (cid:) images are attachments of the TEMPLATE item, so they
|
|
60
|
+
# would show as broken placeholders anywhere else.
|
|
61
|
+
$html = [regex]::Replace($html, ${(0, run_1.psString)(templateLimits_1.EMBEDDED_IMAGE_SOURCE)}, '', [Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
|
62
|
+
if ($html.Length -gt $maxHtml) { $html = $html.Substring(0, $maxHtml) }
|
|
71
63
|
} else {
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
$found = @()
|
|
83
|
-
foreach ($x in [regex]::Matches($plain, '\\[\\[\\s*/?\\s*[A-Za-z0-9_-]{1,40}\\s*\\]\\]|\\{\\{\\s*[A-Za-z0-9_-]{1,40}\\s*\\}\\}')) {
|
|
84
|
-
$t = ($x.Value -replace '\\s', '')
|
|
85
|
-
if ($found -notcontains $t) { $found += $t }
|
|
86
|
-
}
|
|
87
|
-
$markers = ($found -join ' ')
|
|
88
|
-
$preview = $plain.Trim()
|
|
89
|
-
if ($preview.Length -gt 200) { $preview = $preview.Substring(0, 200) }
|
|
64
|
+
# No body asked for: a short preview, plus the section and placeholder
|
|
65
|
+
# markers scanned here from the full plain text — so a caller can confirm
|
|
66
|
+
# a template is intact without its body crossing stdout. Word can split a
|
|
67
|
+
# marker across tags in the HTML but not in the plain text.
|
|
68
|
+
$plain = ''
|
|
69
|
+
try { $plain = [string]$item.Body } catch {}
|
|
70
|
+
$found = @()
|
|
71
|
+
foreach ($m in [regex]::Matches($plain, ${(0, run_1.psString)(templateBody_1.MARKER_TOKEN_SOURCE)})) {
|
|
72
|
+
$token = $m.Value -replace '\\s', ''
|
|
73
|
+
if ($found -notcontains $token) { $found += $token }
|
|
90
74
|
}
|
|
75
|
+
$markers = $found -join ' '
|
|
76
|
+
$preview = $plain.Trim()
|
|
77
|
+
if ($preview.Length -gt $previewChars) { $preview = $preview.Substring(0, $previewChars) }
|
|
91
78
|
}
|
|
92
|
-
$
|
|
93
|
-
|
|
94
|
-
|
|
79
|
+
$modified = ''
|
|
80
|
+
try { $modified = $item.LastModificationTime.ToString('yyyy-MM-dd HH:mm') } catch {}
|
|
81
|
+
$rows += [PSCustomObject]@{
|
|
82
|
+
entryId = [string]$item.EntryID
|
|
83
|
+
subject = $subject
|
|
95
84
|
htmlBody = $html
|
|
96
85
|
bodyPreview = $preview
|
|
97
86
|
markers = $markers
|
|
98
|
-
lastModified = $
|
|
87
|
+
lastModified = $modified
|
|
99
88
|
}
|
|
100
89
|
}
|
|
101
|
-
ConvertTo-Json
|
|
102
|
-
|
|
103
|
-
|
|
90
|
+
ConvertTo-Json -Depth 4 -InputObject ([PSCustomObject]@{
|
|
91
|
+
folderFound = $true
|
|
92
|
+
folderPath = [string]$folder.FolderPath
|
|
93
|
+
templates = @($rows)
|
|
94
|
+
availableFolders = @()
|
|
95
|
+
})
|
|
96
|
+
`, 'standard');
|
|
97
|
+
const e = (0, json_1.record)(output);
|
|
104
98
|
return {
|
|
105
|
-
folderFound:
|
|
106
|
-
folderPath: (0, json_1.str)(
|
|
107
|
-
templates: (0, json_1.toArray)(
|
|
108
|
-
const
|
|
109
|
-
const html = (0, json_1.str)(
|
|
110
|
-
// With
|
|
111
|
-
//
|
|
112
|
-
// of the plain
|
|
113
|
-
const markers = (0,
|
|
99
|
+
folderFound: (0, json_1.bool)(e.folderFound),
|
|
100
|
+
folderPath: (0, json_1.str)(e.folderPath),
|
|
101
|
+
templates: (0, json_1.toArray)(e.templates).map(row => {
|
|
102
|
+
const t = (0, json_1.record)(row);
|
|
103
|
+
const html = (0, json_1.str)(t.htmlBody);
|
|
104
|
+
// With the HTML in hand it is authoritative (markers survive Word
|
|
105
|
+
// splitting them across tags); without it, the markers the script
|
|
106
|
+
// scanned out of the plain text stand in.
|
|
107
|
+
const markers = (0, templateBody_1.findTemplateMarkers)(request.includeBody ? html : (0, json_1.str)(t.markers));
|
|
114
108
|
return {
|
|
115
|
-
entryId: (0, json_1.str)(
|
|
116
|
-
subject: (0, json_1.str)(
|
|
109
|
+
entryId: (0, json_1.str)(t.entryId),
|
|
110
|
+
subject: (0, json_1.str)(t.subject),
|
|
117
111
|
htmlBody: html,
|
|
118
|
-
bodyPreview: (0, json_1.str)(
|
|
112
|
+
bodyPreview: (0, json_1.str)(t.bodyPreview),
|
|
119
113
|
sections: markers.sections,
|
|
120
114
|
placeholders: markers.placeholders,
|
|
121
|
-
lastModified: (0, json_1.str)(
|
|
115
|
+
lastModified: (0, json_1.str)(t.lastModified),
|
|
122
116
|
};
|
|
123
117
|
}),
|
|
124
|
-
availableFolders: (0, json_1.toArray)(
|
|
118
|
+
availableFolders: (0, json_1.toArray)(e.availableFolders).map(json_1.str),
|
|
125
119
|
};
|
|
126
120
|
}
|
|
127
121
|
/**
|
|
128
|
-
* Save a new template email into a
|
|
129
|
-
*
|
|
130
|
-
* plain unsent mail (subject + HTML body) that can be edited in Outlook.
|
|
131
|
-
* Never overwrites an existing item — it always adds a new one, so check with
|
|
132
|
-
* readTemplateEmails first and only call after the user has agreed to create it.
|
|
122
|
+
* Save a new template email into a folder, creating the folder at the mailbox
|
|
123
|
+
* root when absent. Always adds a new item — never overwrites one.
|
|
133
124
|
*/
|
|
134
|
-
async function saveTemplateEmail(
|
|
135
|
-
(0, run_1.
|
|
136
|
-
|
|
137
|
-
|
|
125
|
+
async function saveTemplateEmail(request) {
|
|
126
|
+
const body = (0, run_1.scriptInput)('template-body', request.htmlBody);
|
|
127
|
+
try {
|
|
128
|
+
const output = await (0, run_1.runPowerShellJson)(`${(0, scripts_1.accountScript)(request.account)}
|
|
138
129
|
${scripts_1.DELIVERY_STORE_PS}
|
|
139
130
|
$root = $store.GetRootFolder()
|
|
140
131
|
${scripts_1.FIND_FOLDER_PS}
|
|
141
|
-
$
|
|
132
|
+
$folderName = ${(0, run_1.psString)(request.folder)}
|
|
133
|
+
$folder = Find-FolderByName $root $folderName ${(0, run_1.psInt)(templateLimits_1.TEMPLATE_SEARCH_DEPTH)}
|
|
142
134
|
$folderCreated = $false
|
|
143
135
|
if ($folder -eq $null) {
|
|
144
|
-
$folder = $root.Folders.Add(
|
|
136
|
+
$folder = $root.Folders.Add($folderName)
|
|
145
137
|
$folderCreated = $true
|
|
146
138
|
}
|
|
147
139
|
$mail = $outlook.CreateItem(0)
|
|
148
|
-
$mail.Subject =
|
|
149
|
-
$mail.HTMLBody = [IO.File]::ReadAllText(
|
|
140
|
+
$mail.Subject = ${(0, run_1.psString)(request.subject)}
|
|
141
|
+
$mail.HTMLBody = [IO.File]::ReadAllText(${(0, run_1.psString)(body.path)}, [Text.Encoding]::UTF8)
|
|
150
142
|
$mail.Save()
|
|
151
|
-
$
|
|
152
|
-
ConvertTo-Json @{ folderPath = $folder.FolderPath; folderCreated = $folderCreated }
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
folderPath: (0, json_1.str)(parsed.folderPath),
|
|
158
|
-
folderCreated: Boolean(parsed.folderCreated),
|
|
159
|
-
};
|
|
143
|
+
[void]$mail.Move($folder)
|
|
144
|
+
ConvertTo-Json -Compress -InputObject ([PSCustomObject]@{ folderPath = [string]$folder.FolderPath; folderCreated = $folderCreated })
|
|
145
|
+
`, 'standard');
|
|
146
|
+
const e = (0, json_1.record)(output);
|
|
147
|
+
return { folderPath: (0, json_1.str)(e.folderPath), folderCreated: (0, json_1.bool)(e.folderCreated) };
|
|
160
148
|
}
|
|
161
149
|
finally {
|
|
162
150
|
body.cleanup();
|
|
163
151
|
}
|
|
164
152
|
}
|
|
165
153
|
/**
|
|
166
|
-
* Open
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* Deliberately unbounded: the run lasts as long as the person is editing. Give
|
|
170
|
-
* it an AbortSignal (`bridge.withOptions({ signal })`) if the caller needs a way
|
|
171
|
-
* to give up on them.
|
|
154
|
+
* Open a compose window pre-filled with the HTML, wait for it to close, and
|
|
155
|
+
* return what was saved (Ctrl+S) — or, failing a save, the body as it last
|
|
156
|
+
* stood while the window was open. Leftover editor drafts are removed.
|
|
172
157
|
*/
|
|
173
|
-
async function editEmailTemplate(
|
|
174
|
-
(0, run_1.
|
|
175
|
-
const input = (0, run_1.scriptInput)('template-input', currentHtml);
|
|
158
|
+
async function editEmailTemplate(request) {
|
|
159
|
+
const input = (0, run_1.scriptInput)('template-input', request.html);
|
|
176
160
|
const outputFile = (0, runtime_1.tempFile)('template-output', 'html');
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
$
|
|
180
|
-
$
|
|
181
|
-
$outputPath = '${(0, run_1.psEscape)(outputFile)}'
|
|
182
|
-
$subject = '${(0, run_1.psEscape)(subject)}'
|
|
183
|
-
|
|
184
|
-
$outlook = New-Object -ComObject Outlook.Application
|
|
185
|
-
$ns = $outlook.GetNamespace('mapi')
|
|
161
|
+
try {
|
|
162
|
+
await (0, run_1.runPowerShell)(`${scripts_1.SESSION_PS}
|
|
163
|
+
$subject = ${(0, run_1.psString)(`${request.label} - Save (Ctrl+S) and close when done`)}
|
|
164
|
+
$outputPath = ${(0, run_1.psString)(outputFile)}
|
|
186
165
|
$mail = $outlook.CreateItem(0)
|
|
187
166
|
$mail.Subject = $subject
|
|
188
|
-
$mail.HTMLBody = [IO.File]::ReadAllText($
|
|
167
|
+
$mail.HTMLBody = [IO.File]::ReadAllText(${(0, run_1.psString)(input.path)}, [Text.Encoding]::UTF8)
|
|
189
168
|
$mail.Display()
|
|
190
|
-
|
|
191
|
-
# Give the inspector time to fully initialize
|
|
192
169
|
Start-Sleep -Seconds 2
|
|
193
|
-
|
|
194
|
-
#
|
|
195
|
-
# fallback for the case where the user edits but never presses Ctrl+S.
|
|
170
|
+
# Poll until the compose window closes, keeping the last live body as the
|
|
171
|
+
# fallback for an edit that was never saved.
|
|
196
172
|
$liveBody = ''
|
|
197
173
|
while ($true) {
|
|
198
174
|
Start-Sleep -Milliseconds 700
|
|
199
175
|
$open = $false
|
|
200
176
|
try {
|
|
201
|
-
foreach ($
|
|
202
|
-
$
|
|
203
|
-
try { $
|
|
204
|
-
if ($
|
|
177
|
+
foreach ($inspector in $outlook.Inspectors) {
|
|
178
|
+
$current = $null
|
|
179
|
+
try { $current = $inspector.CurrentItem } catch {}
|
|
180
|
+
if ($current -ne $null -and [string]$current.Subject -eq $subject) {
|
|
205
181
|
$open = $true
|
|
206
|
-
try { $liveBody = $
|
|
182
|
+
try { $liveBody = [string]$current.HTMLBody } catch {}
|
|
207
183
|
break
|
|
208
184
|
}
|
|
209
185
|
}
|
|
210
186
|
} catch {}
|
|
211
187
|
if (-not $open) { break }
|
|
212
188
|
}
|
|
213
|
-
|
|
214
|
-
#
|
|
215
|
-
# inspector closing, unlike the original mail reference. Also removes any
|
|
216
|
-
# leftover editor drafts so they don't pile up in the Drafts folder.
|
|
189
|
+
# Prefer the saved draft: it is what the person chose to keep, and it outlives
|
|
190
|
+
# the window. Every editor draft is removed so none pile up in Drafts.
|
|
217
191
|
$savedBody = ''
|
|
218
192
|
try {
|
|
219
|
-
$
|
|
220
|
-
$draftItems = $drafts.Items
|
|
193
|
+
$draftItems = $ns.GetDefaultFolder(${(0, run_1.psInt)(mail_1.FolderId.Drafts)}).Items
|
|
221
194
|
for ($i = $draftItems.Count; $i -ge 1; $i--) {
|
|
222
|
-
$
|
|
223
|
-
if ($
|
|
224
|
-
if (-not $savedBody) { try { $savedBody = $
|
|
225
|
-
try { $
|
|
195
|
+
$draft = $draftItems.Item($i)
|
|
196
|
+
if ([string]$draft.Subject -eq $subject) {
|
|
197
|
+
if (-not $savedBody) { try { $savedBody = [string]$draft.HTMLBody } catch {} }
|
|
198
|
+
try { $draft.Delete() } catch {}
|
|
226
199
|
}
|
|
227
200
|
}
|
|
228
201
|
} catch {}
|
|
229
|
-
|
|
230
202
|
$finalBody = if ($savedBody) { $savedBody } else { $liveBody }
|
|
231
|
-
if ($finalBody) {
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
`;
|
|
235
|
-
try {
|
|
236
|
-
// 0 disables the timeout: this run is as long as the edit takes.
|
|
237
|
-
await (0, run_1.runPowerShellFile)(script, 0);
|
|
203
|
+
if ($finalBody) { [IO.File]::WriteAllText($outputPath, $finalBody, [Text.Encoding]::UTF8) }
|
|
204
|
+
`, 'interactive');
|
|
238
205
|
}
|
|
239
206
|
finally {
|
|
240
207
|
input.cleanup();
|
|
241
208
|
}
|
|
242
|
-
const
|
|
243
|
-
if (!
|
|
244
|
-
throw new errors_1.NotFoundError('template', 'No template saved.
|
|
209
|
+
const saved = (0, run_1.readScriptOutput)(outputFile);
|
|
210
|
+
if (!saved) {
|
|
211
|
+
throw new errors_1.NotFoundError('template', 'No template was saved. Save (Ctrl+S) before closing the window.');
|
|
245
212
|
}
|
|
246
|
-
return
|
|
213
|
+
return saved;
|
|
247
214
|
}
|
|
248
215
|
//# sourceMappingURL=templates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/windows/templates.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/windows/templates.ts"],"names":[],"mappings":"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","sourcesContent":["// Template emails: ordinary mail items kept in a mailbox folder and reused as\n// email bodies, plus the compose-window editor for one.\nimport { psBool, psInt, psString, readScriptOutput, runPowerShell, runPowerShellJson, scriptInput } from './run';\nimport { accountScript, DELIVERY_STORE_PS, FIND_FOLDER_PS, SESSION_PS } from './scripts';\nimport { bool, record, str, toArray } from '../shared/json';\nimport {\n EMBEDDED_IMAGE_SOURCE,\n MAX_TEMPLATE_HTML,\n TEMPLATE_PREVIEW_CHARS,\n TEMPLATE_SEARCH_DEPTH,\n} from '../shared/templateLimits';\nimport { findTemplateMarkers, MARKER_TOKEN_SOURCE } from '../templateBody';\nimport { FolderId } from '../mail';\nimport { NotFoundError } from '../errors';\nimport { tempFile } from '../runtime';\nimport type { EditTemplateRequest, ReadTemplatesRequest, SaveTemplateRequest } from '../backend';\nimport type { SaveTemplateResult, TemplateFolderResult } from '../types';\n\n/**\n * The template emails in a mailbox folder, newest first. A missing folder is\n * reported as folderFound:false with the mailbox's top-level folder names\n * rather than thrown, so a caller can offer to create it.\n */\nexport async function readTemplateEmails(request: ReadTemplatesRequest): Promise<TemplateFolderResult> {\n const output = await runPowerShellJson(`${accountScript(request.account)}\n${DELIVERY_STORE_PS}\n$root = $store.GetRootFolder()\n${FIND_FOLDER_PS}\n$folder = Find-FolderByName $root ${psString(request.folder)} ${psInt(TEMPLATE_SEARCH_DEPTH)}\nif ($folder -eq $null) {\n $names = @()\n foreach ($f in $root.Folders) { $names += [string]$f.Name }\n ConvertTo-Json -Compress -Depth 3 -InputObject ([PSCustomObject]@{ folderFound = $false; folderPath = ''; templates = @(); availableFolders = @($names) })\n exit 0\n}\n$includeBody = ${psBool(request.includeBody)}\n$wanted = ${psString(request.subject ?? '')}\n$limit = ${psInt(request.limit)}\n$maxHtml = ${psInt(MAX_TEMPLATE_HTML)}\n$previewChars = ${psInt(TEMPLATE_PREVIEW_CHARS)}\n$items = $folder.Items\n$items.Sort('[LastModificationTime]', $true)\n$rows = @()\n$count = $items.Count\n# Without a subject the sort does the capping, newest first. With one, the whole\n# folder is scanned — the template wanted need not be among the newest.\nfor ($i = 1; $i -le $count -and $rows.Count -lt $limit; $i++) {\n $item = $null\n try { $item = $items.Item($i) } catch { continue }\n if ($item -eq $null) { continue }\n $class = 0\n try { $class = [int]$item.Class } catch {}\n if ($class -ne 43) { continue }\n $subject = ''\n try { $subject = ([string]$item.Subject).Trim() } catch {}\n if ($wanted -and $subject -ine $wanted) { continue }\n $html = ''\n $preview = ''\n $markers = ''\n if ($includeBody) {\n try { $html = [string]$item.HTMLBody } catch {}\n # Embedded (cid:) images are attachments of the TEMPLATE item, so they\n # would show as broken placeholders anywhere else.\n $html = [regex]::Replace($html, ${psString(EMBEDDED_IMAGE_SOURCE)}, '', [Text.RegularExpressions.RegexOptions]::IgnoreCase)\n if ($html.Length -gt $maxHtml) { $html = $html.Substring(0, $maxHtml) }\n } else {\n # No body asked for: a short preview, plus the section and placeholder\n # markers scanned here from the full plain text — so a caller can confirm\n # a template is intact without its body crossing stdout. Word can split a\n # marker across tags in the HTML but not in the plain text.\n $plain = ''\n try { $plain = [string]$item.Body } catch {}\n $found = @()\n foreach ($m in [regex]::Matches($plain, ${psString(MARKER_TOKEN_SOURCE)})) {\n $token = $m.Value -replace '\\\\s', ''\n if ($found -notcontains $token) { $found += $token }\n }\n $markers = $found -join ' '\n $preview = $plain.Trim()\n if ($preview.Length -gt $previewChars) { $preview = $preview.Substring(0, $previewChars) }\n }\n $modified = ''\n try { $modified = $item.LastModificationTime.ToString('yyyy-MM-dd HH:mm') } catch {}\n $rows += [PSCustomObject]@{\n entryId = [string]$item.EntryID\n subject = $subject\n htmlBody = $html\n bodyPreview = $preview\n markers = $markers\n lastModified = $modified\n }\n}\nConvertTo-Json -Depth 4 -InputObject ([PSCustomObject]@{\n folderFound = $true\n folderPath = [string]$folder.FolderPath\n templates = @($rows)\n availableFolders = @()\n})\n`, 'standard');\n const e = record(output);\n return {\n folderFound: bool(e.folderFound),\n folderPath: str(e.folderPath),\n templates: toArray(e.templates).map(row => {\n const t = record(row);\n const html = str(t.htmlBody);\n // With the HTML in hand it is authoritative (markers survive Word\n // splitting them across tags); without it, the markers the script\n // scanned out of the plain text stand in.\n const markers = findTemplateMarkers(request.includeBody ? html : str(t.markers));\n return {\n entryId: str(t.entryId),\n subject: str(t.subject),\n htmlBody: html,\n bodyPreview: str(t.bodyPreview),\n sections: markers.sections,\n placeholders: markers.placeholders,\n lastModified: str(t.lastModified),\n };\n }),\n availableFolders: toArray(e.availableFolders).map(str),\n };\n}\n\n/**\n * Save a new template email into a folder, creating the folder at the mailbox\n * root when absent. Always adds a new item — never overwrites one.\n */\nexport async function saveTemplateEmail(request: SaveTemplateRequest): Promise<SaveTemplateResult> {\n const body = scriptInput('template-body', request.htmlBody);\n try {\n const output = await runPowerShellJson(`${accountScript(request.account)}\n${DELIVERY_STORE_PS}\n$root = $store.GetRootFolder()\n${FIND_FOLDER_PS}\n$folderName = ${psString(request.folder)}\n$folder = Find-FolderByName $root $folderName ${psInt(TEMPLATE_SEARCH_DEPTH)}\n$folderCreated = $false\nif ($folder -eq $null) {\n $folder = $root.Folders.Add($folderName)\n $folderCreated = $true\n}\n$mail = $outlook.CreateItem(0)\n$mail.Subject = ${psString(request.subject)}\n$mail.HTMLBody = [IO.File]::ReadAllText(${psString(body.path)}, [Text.Encoding]::UTF8)\n$mail.Save()\n[void]$mail.Move($folder)\nConvertTo-Json -Compress -InputObject ([PSCustomObject]@{ folderPath = [string]$folder.FolderPath; folderCreated = $folderCreated })\n`, 'standard');\n const e = record(output);\n return { folderPath: str(e.folderPath), folderCreated: bool(e.folderCreated) };\n } finally {\n body.cleanup();\n }\n}\n\n/**\n * Open a compose window pre-filled with the HTML, wait for it to close, and\n * return what was saved (Ctrl+S) — or, failing a save, the body as it last\n * stood while the window was open. Leftover editor drafts are removed.\n */\nexport async function editEmailTemplate(request: EditTemplateRequest): Promise<string> {\n const input = scriptInput('template-input', request.html);\n const outputFile = tempFile('template-output', 'html');\n try {\n await runPowerShell(`${SESSION_PS}\n$subject = ${psString(`${request.label} - Save (Ctrl+S) and close when done`)}\n$outputPath = ${psString(outputFile)}\n$mail = $outlook.CreateItem(0)\n$mail.Subject = $subject\n$mail.HTMLBody = [IO.File]::ReadAllText(${psString(input.path)}, [Text.Encoding]::UTF8)\n$mail.Display()\nStart-Sleep -Seconds 2\n# Poll until the compose window closes, keeping the last live body as the\n# fallback for an edit that was never saved.\n$liveBody = ''\nwhile ($true) {\n Start-Sleep -Milliseconds 700\n $open = $false\n try {\n foreach ($inspector in $outlook.Inspectors) {\n $current = $null\n try { $current = $inspector.CurrentItem } catch {}\n if ($current -ne $null -and [string]$current.Subject -eq $subject) {\n $open = $true\n try { $liveBody = [string]$current.HTMLBody } catch {}\n break\n }\n }\n } catch {}\n if (-not $open) { break }\n}\n# Prefer the saved draft: it is what the person chose to keep, and it outlives\n# the window. Every editor draft is removed so none pile up in Drafts.\n$savedBody = ''\ntry {\n $draftItems = $ns.GetDefaultFolder(${psInt(FolderId.Drafts)}).Items\n for ($i = $draftItems.Count; $i -ge 1; $i--) {\n $draft = $draftItems.Item($i)\n if ([string]$draft.Subject -eq $subject) {\n if (-not $savedBody) { try { $savedBody = [string]$draft.HTMLBody } catch {} }\n try { $draft.Delete() } catch {}\n }\n }\n} catch {}\n$finalBody = if ($savedBody) { $savedBody } else { $liveBody }\nif ($finalBody) { [IO.File]::WriteAllText($outputPath, $finalBody, [Text.Encoding]::UTF8) }\n`, 'interactive');\n } finally {\n input.cleanup();\n }\n const saved = readScriptOutput(outputFile);\n if (!saved) {\n throw new NotFoundError('template', 'No template was saved. Save (Ctrl+S) before closing the window.');\n }\n return saved;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dawnlit/outlook-bridge",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Desktop Outlook automation for Node — read, send, reply, file, and template mail by driving the real Outlook client.",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Desktop Outlook automation for Node — read, search, send, reply, file, and template mail by driving the real Outlook client on Windows and macOS.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Dawnlit",
|
|
7
7
|
"homepage": "https://github.com/dawnlit-ai/outlook-bridge#readme",
|
|
@@ -39,12 +39,13 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
|
-
"
|
|
42
|
+
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
43
|
+
"build": "npm run clean && tsc -p .",
|
|
43
44
|
"test": "npm run build && node --test \"test/*.test.js\"",
|
|
44
45
|
"prepare": "npm run build"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^24.
|
|
48
|
+
"@types/node": "^24.19.2",
|
|
48
49
|
"typescript": "~6.0.3"
|
|
49
50
|
}
|
|
50
51
|
}
|
package/dist/OutlookService.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
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, storeId?: 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>, sendDrafts: (emailAccount: string, entryIds: string[]) => Promise<import("./types").SendDraftsResult>, 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>;
|
package/dist/OutlookService.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
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.sendDrafts = 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.sendDrafts = impl.sendDrafts, 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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OutlookService.js","sourceRoot":"","sources":["../src/OutlookService.ts"],"names":[],"mappings":"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"}
|