@dawnlit/outlook-bridge 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +150 -183
  2. package/dist/backend.d.ts +151 -0
  3. package/dist/backend.js +3 -0
  4. package/dist/backend.js.map +1 -0
  5. package/dist/bridge.d.ts +56 -0
  6. package/dist/bridge.js +507 -0
  7. package/dist/bridge.js.map +1 -0
  8. package/dist/errors.d.ts +81 -43
  9. package/dist/errors.js +98 -52
  10. package/dist/errors.js.map +1 -1
  11. package/dist/index.d.ts +10 -10
  12. package/dist/index.js +25 -52
  13. package/dist/index.js.map +1 -1
  14. package/dist/mac/accounts.d.ts +7 -2
  15. package/dist/mac/accounts.js +23 -6
  16. package/dist/mac/accounts.js.map +1 -1
  17. package/dist/mac/attachments.d.ts +5 -25
  18. package/dist/mac/attachments.js +40 -99
  19. package/dist/mac/attachments.js.map +1 -1
  20. package/dist/mac/bounces.d.ts +12 -27
  21. package/dist/mac/bounces.js +95 -112
  22. package/dist/mac/bounces.js.map +1 -1
  23. package/dist/mac/cleanup.d.ts +11 -25
  24. package/dist/mac/cleanup.js +50 -76
  25. package/dist/mac/cleanup.js.map +1 -1
  26. package/dist/mac/drafts.d.ts +13 -34
  27. package/dist/mac/drafts.js +95 -169
  28. package/dist/mac/drafts.js.map +1 -1
  29. package/dist/mac/folders.d.ts +10 -21
  30. package/dist/mac/folders.js +33 -47
  31. package/dist/mac/folders.js.map +1 -1
  32. package/dist/mac/index.d.ts +2 -22
  33. package/dist/mac/index.js +19 -81
  34. package/dist/mac/index.js.map +1 -1
  35. package/dist/mac/profile.d.ts +13 -0
  36. package/dist/mac/profile.js +149 -0
  37. package/dist/mac/profile.js.map +1 -0
  38. package/dist/mac/read.d.ts +18 -36
  39. package/dist/mac/read.js +154 -208
  40. package/dist/mac/read.js.map +1 -1
  41. package/dist/mac/run.d.ts +35 -39
  42. package/dist/mac/run.js +97 -102
  43. package/dist/mac/run.js.map +1 -1
  44. package/dist/mac/scripts.d.ts +78 -86
  45. package/dist/mac/scripts.js +125 -115
  46. package/dist/mac/scripts.js.map +1 -1
  47. package/dist/mac/send.d.ts +10 -20
  48. package/dist/mac/send.js +64 -86
  49. package/dist/mac/send.js.map +1 -1
  50. package/dist/mac/signatures.d.ts +2 -2
  51. package/dist/mac/signatures.js +9 -11
  52. package/dist/mac/signatures.js.map +1 -1
  53. package/dist/mac/templates.d.ts +14 -26
  54. package/dist/mac/templates.js +75 -113
  55. package/dist/mac/templates.js.map +1 -1
  56. package/dist/mail.d.ts +77 -45
  57. package/dist/mail.js +166 -73
  58. package/dist/mail.js.map +1 -1
  59. package/dist/runtime.d.ts +76 -43
  60. package/dist/runtime.js +103 -48
  61. package/dist/runtime.js.map +1 -1
  62. package/dist/shared/args.d.ts +48 -0
  63. package/dist/shared/args.js +216 -0
  64. package/dist/shared/args.js.map +1 -0
  65. package/dist/shared/attachmentMatch.d.ts +28 -16
  66. package/dist/shared/attachmentMatch.js +60 -22
  67. package/dist/shared/attachmentMatch.js.map +1 -1
  68. package/dist/shared/bounceReport.d.ts +11 -0
  69. package/dist/shared/bounceReport.js +45 -0
  70. package/dist/shared/bounceReport.js.map +1 -0
  71. package/dist/shared/bounceRules.d.ts +38 -10
  72. package/dist/shared/bounceRules.js +50 -32
  73. package/dist/shared/bounceRules.js.map +1 -1
  74. package/dist/shared/exec.d.ts +21 -0
  75. package/dist/shared/exec.js +47 -0
  76. package/dist/shared/exec.js.map +1 -0
  77. package/dist/shared/json.d.ts +12 -6
  78. package/dist/shared/json.js +29 -23
  79. package/dist/shared/json.js.map +1 -1
  80. package/dist/shared/locate.d.ts +39 -0
  81. package/dist/shared/locate.js +129 -0
  82. package/dist/shared/locate.js.map +1 -0
  83. package/dist/shared/replyBody.d.ts +42 -32
  84. package/dist/shared/replyBody.js +84 -71
  85. package/dist/shared/replyBody.js.map +1 -1
  86. package/dist/templateBody.d.ts +63 -0
  87. package/dist/{outlookTemplateSections.js → templateBody.js} +72 -72
  88. package/dist/templateBody.js.map +1 -0
  89. package/dist/types.d.ts +360 -165
  90. package/dist/types.js +8 -9
  91. package/dist/types.js.map +1 -1
  92. package/dist/windows/accounts.d.ts +10 -1
  93. package/dist/windows/accounts.js +25 -13
  94. package/dist/windows/accounts.js.map +1 -1
  95. package/dist/windows/attachments.d.ts +9 -24
  96. package/dist/windows/attachments.js +94 -119
  97. package/dist/windows/attachments.js.map +1 -1
  98. package/dist/windows/bounces.d.ts +13 -26
  99. package/dist/windows/bounces.js +169 -200
  100. package/dist/windows/bounces.js.map +1 -1
  101. package/dist/windows/cleanup.d.ts +19 -23
  102. package/dist/windows/cleanup.js +93 -111
  103. package/dist/windows/cleanup.js.map +1 -1
  104. package/dist/windows/drafts.d.ts +16 -35
  105. package/dist/windows/drafts.js +167 -253
  106. package/dist/windows/drafts.js.map +1 -1
  107. package/dist/windows/folders.d.ts +8 -13
  108. package/dist/windows/folders.js +45 -52
  109. package/dist/windows/folders.js.map +1 -1
  110. package/dist/windows/index.d.ts +2 -27
  111. package/dist/windows/index.js +11 -65
  112. package/dist/windows/index.js.map +1 -1
  113. package/dist/windows/read.d.ts +24 -45
  114. package/dist/windows/read.js +266 -279
  115. package/dist/windows/read.js.map +1 -1
  116. package/dist/windows/run.d.ts +39 -39
  117. package/dist/windows/run.js +151 -111
  118. package/dist/windows/run.js.map +1 -1
  119. package/dist/windows/scripts.d.ts +71 -38
  120. package/dist/windows/scripts.js +123 -71
  121. package/dist/windows/scripts.js.map +1 -1
  122. package/dist/windows/send.d.ts +6 -11
  123. package/dist/windows/send.js +70 -79
  124. package/dist/windows/send.js.map +1 -1
  125. package/dist/windows/signatures.d.ts +4 -10
  126. package/dist/windows/signatures.js +30 -37
  127. package/dist/windows/signatures.js.map +1 -1
  128. package/dist/windows/templates.d.ts +12 -18
  129. package/dist/windows/templates.js +126 -151
  130. package/dist/windows/templates.js.map +1 -1
  131. package/package.json +5 -4
  132. package/dist/OutlookService.d.ts +0 -43
  133. package/dist/OutlookService.js +0 -137
  134. package/dist/OutlookService.js.map +0 -1
  135. package/dist/outlookTemplateSections.d.ts +0 -62
  136. package/dist/outlookTemplateSections.js.map +0 -1
  137. package/dist/shared/capabilities.d.ts +0 -3
  138. package/dist/shared/capabilities.js +0 -9
  139. package/dist/shared/capabilities.js.map +0 -1
@@ -1,56 +1,89 @@
1
- import type { MailFolderRef } from '../types';
1
+ import type { EmailLocator, MailFolderRef } from '../types';
2
2
  /**
3
- * Session plus the account whose SMTP address matches; binds `$target` and
4
- * `$account`.
3
+ * Open the MAPI session, binding `$outlook` and `$ns`.
5
4
  *
6
- * Fails rather than falling back to the default account. A bad address must
7
- * never silently send from — or read — the wrong mailbox, and the thrown
8
- * sentence is the one `classifyRunFailure` recognises to raise
9
- * `AccountNotFoundError`, so the wording is load-bearing.
5
+ * `Logon()` is a no-op against an Outlook that is already running and starts
6
+ * one that isn't, which removes a class of "works only while Outlook is open"
7
+ * failure.
8
+ */
9
+ export declare const SESSION_PS = "\n$outlook = New-Object -ComObject Outlook.Application\n$ns = $outlook.GetNamespace('MAPI')\n$ns.Logon()\n";
10
+ /**
11
+ * The session plus the mailbox an address names; binds `$target`, `$account`
12
+ * and `$storeFolder`.
13
+ *
14
+ * An address can name a mailbox two ways, and only one is an Account. A mailbox
15
+ * mounted as a secondary store — a shared mailbox, or one added after Outlook
16
+ * started — has no Account object, so both are resolved and EITHER is enough:
17
+ * `$account` is null for a store-only mailbox, and the operations that need an
18
+ * identity to act as (sending) check for it themselves.
19
+ *
20
+ * Never falls back to the default account: a bad address must not silently
21
+ * read or send from the wrong mailbox.
22
+ *
23
+ * The store is matched on the address BEFORE the account's display name, so a
24
+ * profile where the two differ selects the same folders it always has.
10
25
  */
11
26
  export declare function accountScript(emailAccount: string): string;
12
- /** The account's own delivery store, as `$store`. Requires `accountScript`. */
13
- export declare const DELIVERY_STORE_PS = "\n$store = $account.DeliveryStore\n$storeId = $store.StoreID\n";
14
27
  /**
15
- * The account's store reached through the namespace's top-level folders, as
16
- * `$storeFolder` / `$store`.
28
+ * The mailbox's store as `$store` (and its id as `$storeId`), reached through
29
+ * the account's delivery store. Requires `accountScript`.
17
30
  *
18
- * Kept alongside `DELIVERY_STORE_PS` rather than replaced by it: the reading
19
- * operations resolve the store this way, and on a profile where a mailbox is
20
- * open under a display name that differs from the delivery store's, the two do
21
- * not select the same folders. Changing which one a reader uses changes what it
22
- * returns, so each keeps the route it was verified against.
31
+ * Falls back to the resolved store folder, because a store-only mailbox has no
32
+ * account to read a delivery store off.
23
33
  */
24
- export declare function namedStoreScript(emailAccount: string): string;
34
+ export declare const DELIVERY_STORE_PS = "\n$store = if ($account -ne $null) { $account.DeliveryStore } else { $storeFolder.Store }\n$storeId = $store.StoreID\n";
25
35
  /**
26
- * Resolve one item into `$item`. A StoreID disambiguates across mailboxes, so
27
- * pass it whenever the listing that produced the id carried one.
36
+ * The mailbox's store as `$store`, reached through the namespace's top-level
37
+ * folder for it. Requires `accountScript`.
38
+ *
39
+ * Kept beside DELIVERY_STORE_PS rather than replaced by it: the readers resolve
40
+ * their store this way, and on a profile where a mailbox is open under a display
41
+ * name that differs from its delivery store's, the two routes do not select the
42
+ * same folders. Each operation keeps the route it was verified against.
28
43
  */
29
- export declare function getItemScript(entryId: string, storeId?: string): string;
44
+ export declare const NAMED_STORE_PS: string;
30
45
  /**
31
- * The sender's real SMTP address, as `$senderSmtp`. Requires `$item`.
46
+ * Resolve one email into `$<variable>`, or fail as NOT_FOUND.
32
47
  *
33
- * An Exchange sender's `SenderEmailAddress` is an X500 DN rather than an
34
- * address; a caller that means to reply to it, or correlate it with anything,
35
- * needs the address it resolves to.
48
+ * The StoreID is tried first, since it lets an id from any mounted mailbox
49
+ * resolve; the bare lookup (default store) is the fallback for a caller holding
50
+ * a stale StoreID or none.
36
51
  */
37
- export declare const SENDER_SMTP_PS = "\n$senderSmtp = ''\ntry {\n if ($item.SenderEmailType -eq 'EX') { $senderSmtp = $item.Sender.GetExchangeUser().PrimarySmtpAddress }\n} catch {}\nif (-not $senderSmtp) { $senderSmtp = if ($item.SenderEmailAddress) { $item.SenderEmailAddress } else { '' } }\n";
52
+ export declare function itemLookupScript(email: EmailLocator, variable?: string): string;
38
53
  /**
39
- * Recursive folder-by-name search. Case-insensitive, depth-capped so a huge
40
- * mailbox tree can't hang the scan.
54
+ * The sender's SMTP address as `$senderSmtp`. Requires `$item`.
55
+ *
56
+ * An Exchange sender's SenderEmailAddress is an X.500 DN, not an address; a
57
+ * caller replying to it or matching it against anything needs the address.
41
58
  */
42
- export declare const FIND_FOLDER_PS = "\nfunction Find-FolderByName($root, $name, $depth) {\n foreach ($f in $root.Folders) {\n if ($f.Name -ieq $name) { return $f }\n }\n if ($depth -le 1) { return $null }\n foreach ($f in $root.Folders) {\n $hit = Find-FolderByName $f $name ($depth - 1)\n if ($hit -ne $null) { return $hit }\n }\n return $null\n}\n";
59
+ export declare const SENDER_SMTP_PS = "\n$senderSmtp = ''\ntry {\n if ($item.SenderEmailType -eq 'EX') { $senderSmtp = [string]$item.Sender.GetExchangeUser().PrimarySmtpAddress }\n} catch {}\nif (-not $senderSmtp) { try { $senderSmtp = [string]$item.SenderEmailAddress } catch {} }\n";
60
+ /** Recursive, case-insensitive folder search by name, depth-capped so a huge tree can't hang it. */
61
+ export declare const FIND_FOLDER_PS = "\nfunction Find-FolderByName($root, [string]$name, [int]$depth) {\n foreach ($f in $root.Folders) {\n if ($f.Name -ieq $name) { return $f }\n }\n if ($depth -le 1) { return $null }\n foreach ($f in $root.Folders) {\n $hit = Find-FolderByName $f $name ($depth - 1)\n if ($hit -ne $null) { return $hit }\n }\n return $null\n}\n";
43
62
  /**
44
- * Emit the PowerShell that resolves `$scope` from `$store`, walking a well-known
45
- * root down through any further segments. Also binds `$scopeCreated`.
63
+ * `$cutoff`, the moment `daysBack` days ago, and `$cutoffFilter`, that moment
64
+ * as a date string for an `Items.Restrict` filter.
46
65
  *
47
- * Split out so the emitted script can be parse-checked without an Outlook
48
- * session — the folder walk is the only part that varies per call, and a syntax
49
- * error in it would only ever surface as a failed live run.
66
+ * Restrict parses date strings in the machine's own regional format, so the
67
+ * string is formatted in it ('g': short date and time) rather than a fixed
68
+ * pattern — 'MM/dd/yyyy' reads as a different day on a day-first locale. Every
69
+ * reader re-checks each item against `$cutoff` too, so the window holds even
70
+ * where a store reads the filter loosely.
71
+ */
72
+ export declare function cutoffScript(daysBack: number): string;
73
+ /**
74
+ * `$<variable>` = the items of `$<folderVariable>` with `property` on or after
75
+ * `$cutoff`. Requires `cutoffScript`. A store that rejects the filter outright
76
+ * yields every item instead, which the per-item re-check then narrows.
77
+ */
78
+ export declare function itemsSinceScript(folderVariable: string, property: string, variable: string): string;
79
+ /**
80
+ * Resolve `$scope` from `$store`: a well-known root walked down through any
81
+ * further segments. Also binds `$scopeCreated`.
50
82
  *
51
- * `folderLabel` is the caller's original string, used verbatim in the error so
52
- * the message names what they typed rather than the parsed segments. Set
53
- * `createMissing` to build absent segments instead of throwing — the whole
54
- * chain, so a nested destination can be created in one call.
83
+ * Segments match direct children; a bare name that isn't a direct child falls
84
+ * back to a recursive search, so one folder string works across operations. A
85
+ * missing folder fails as NOT_FOUND naming what the caller typed and what the
86
+ * deepest folder reached does hold — never a silent fall back to the root. With
87
+ * `createMissing`, the whole missing chain is created instead.
55
88
  */
56
- export declare function mailScopeScript(ref: MailFolderRef, folderLabel?: string, createMissing?: boolean): string;
89
+ export declare function mailScopeScript(ref: MailFolderRef, folderLabel: string, createMissing?: boolean): string;
@@ -1,103 +1,132 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FIND_FOLDER_PS = exports.SENDER_SMTP_PS = exports.DELIVERY_STORE_PS = void 0;
3
+ exports.FIND_FOLDER_PS = exports.SENDER_SMTP_PS = exports.NAMED_STORE_PS = exports.DELIVERY_STORE_PS = exports.SESSION_PS = void 0;
4
4
  exports.accountScript = accountScript;
5
- exports.namedStoreScript = namedStoreScript;
6
- exports.getItemScript = getItemScript;
5
+ exports.itemLookupScript = itemLookupScript;
6
+ exports.cutoffScript = cutoffScript;
7
+ exports.itemsSinceScript = itemsSinceScript;
7
8
  exports.mailScopeScript = mailScopeScript;
8
9
  // The PowerShell fragments more than one Windows operation is built from.
9
10
  //
10
- // A fragment lives here once at least two modules emit it; one used by a single
11
- // operation stays beside that operation, where its rules are readable next to
12
- // the code that depends on them.
11
+ // A fragment lives here once two modules emit it; one used by a single
12
+ // operation stays beside that operation, where its rules read next to the code
13
+ // relying on them. Every fragment follows run.ts's escaping rule: caller text
14
+ // only ever appears as a psString literal.
13
15
  const run_1 = require("./run");
16
+ const errors_1 = require("../errors");
14
17
  /**
15
- * Open a MAPI session. `$outlook` and `$ns` are what every later fragment reads.
18
+ * Open the MAPI session, binding `$outlook` and `$ns`.
16
19
  *
17
- * `Logon()` is a no-op against an Outlook that is already running and starts one
18
- * that isn't, so it costs nothing and removes a class of "works only when
19
- * Outlook happens to be open" failure.
20
+ * `Logon()` is a no-op against an Outlook that is already running and starts
21
+ * one that isn't, which removes a class of "works only while Outlook is open"
22
+ * failure.
20
23
  */
21
- const PS_PRELUDE = `
22
- $ErrorActionPreference = 'Stop'
24
+ exports.SESSION_PS = `
23
25
  $outlook = New-Object -ComObject Outlook.Application
24
- $ns = $outlook.GetNamespace('mapi')
26
+ $ns = $outlook.GetNamespace('MAPI')
25
27
  $ns.Logon()
26
28
  `;
27
29
  /**
28
- * Session plus the account whose SMTP address matches; binds `$target` and
29
- * `$account`.
30
+ * The session plus the mailbox an address names; binds `$target`, `$account`
31
+ * and `$storeFolder`.
30
32
  *
31
- * Fails rather than falling back to the default account. A bad address must
32
- * never silently send from — or read — the wrong mailbox, and the thrown
33
- * sentence is the one `classifyRunFailure` recognises to raise
34
- * `AccountNotFoundError`, so the wording is load-bearing.
33
+ * An address can name a mailbox two ways, and only one is an Account. A mailbox
34
+ * mounted as a secondary store — a shared mailbox, or one added after Outlook
35
+ * started — has no Account object, so both are resolved and EITHER is enough:
36
+ * `$account` is null for a store-only mailbox, and the operations that need an
37
+ * identity to act as (sending) check for it themselves.
38
+ *
39
+ * Never falls back to the default account: a bad address must not silently
40
+ * read or send from the wrong mailbox.
41
+ *
42
+ * The store is matched on the address BEFORE the account's display name, so a
43
+ * profile where the two differ selects the same folders it always has.
35
44
  */
36
45
  function accountScript(emailAccount) {
37
- return `${PS_PRELUDE}
38
- $target = '${(0, run_1.psEscape)(emailAccount)}'
46
+ return `${exports.SESSION_PS}
47
+ $target = ${(0, run_1.psString)(emailAccount)}
39
48
  $account = $null
40
49
  foreach ($a in $ns.Accounts) {
41
50
  if ($a.SmtpAddress -ieq $target) { $account = $a; break }
42
51
  }
43
- if ($account -eq $null) { throw "Account '$target' not found" }
52
+ $storeFolder = $null
53
+ foreach ($f in $ns.Folders) {
54
+ if ($f.Name -ieq $target) { $storeFolder = $f; break }
55
+ }
56
+ if ($storeFolder -eq $null -and $account -ne $null) {
57
+ foreach ($f in $ns.Folders) {
58
+ if ($f.Name -ieq $account.DisplayName) { $storeFolder = $f; break }
59
+ }
60
+ }
61
+ if ($account -eq $null -and $storeFolder -eq $null) {
62
+ throw "${(0, errors_1.failureTag)('ACCOUNT_NOT_FOUND')}Account '$target' not found in this Outlook profile."
63
+ }
44
64
  `;
45
65
  }
46
- /** The account's own delivery store, as `$store`. Requires `accountScript`. */
66
+ /**
67
+ * The mailbox's store as `$store` (and its id as `$storeId`), reached through
68
+ * the account's delivery store. Requires `accountScript`.
69
+ *
70
+ * Falls back to the resolved store folder, because a store-only mailbox has no
71
+ * account to read a delivery store off.
72
+ */
47
73
  exports.DELIVERY_STORE_PS = `
48
- $store = $account.DeliveryStore
74
+ $store = if ($account -ne $null) { $account.DeliveryStore } else { $storeFolder.Store }
49
75
  $storeId = $store.StoreID
50
76
  `;
51
77
  /**
52
- * The account's store reached through the namespace's top-level folders, as
53
- * `$storeFolder` / `$store`.
78
+ * The mailbox's store as `$store`, reached through the namespace's top-level
79
+ * folder for it. Requires `accountScript`.
54
80
  *
55
- * Kept alongside `DELIVERY_STORE_PS` rather than replaced by it: the reading
56
- * operations resolve the store this way, and on a profile where a mailbox is
57
- * open under a display name that differs from the delivery store's, the two do
58
- * not select the same folders. Changing which one a reader uses changes what it
59
- * returns, so each keeps the route it was verified against.
81
+ * Kept beside DELIVERY_STORE_PS rather than replaced by it: the readers resolve
82
+ * their store this way, and on a profile where a mailbox is open under a display
83
+ * name that differs from its delivery store's, the two routes do not select the
84
+ * same folders. Each operation keeps the route it was verified against.
60
85
  */
61
- function namedStoreScript(emailAccount) {
62
- return `
63
- $storeFolder = $null
64
- foreach ($f in $ns.Folders) {
65
- if ($f.Name -ieq $account.DisplayName) { $storeFolder = $f; break }
86
+ exports.NAMED_STORE_PS = `
87
+ if ($storeFolder -eq $null) {
88
+ throw "${(0, errors_1.failureTag)('ACCOUNT_NOT_FOUND')}Account '$target' has no mailbox open in this Outlook profile."
66
89
  }
67
- if ($storeFolder -eq $null) { throw "Store folder not found for account '${(0, run_1.psEscape)(emailAccount)}'" }
68
90
  $store = $storeFolder.Store
69
91
  $storeId = $store.StoreID
70
92
  `;
71
- }
72
93
  /**
73
- * Resolve one item into `$item`. A StoreID disambiguates across mailboxes, so
74
- * pass it whenever the listing that produced the id carried one.
94
+ * Resolve one email into `$<variable>`, or fail as NOT_FOUND.
95
+ *
96
+ * The StoreID is tried first, since it lets an id from any mounted mailbox
97
+ * resolve; the bare lookup (default store) is the fallback for a caller holding
98
+ * a stale StoreID or none.
75
99
  */
76
- function getItemScript(entryId, storeId) {
77
- return storeId
78
- ? `$item = $ns.GetItemFromID('${(0, run_1.psEscape)(entryId)}', '${(0, run_1.psEscape)(storeId)}')`
79
- : `$item = $ns.GetItemFromID('${(0, run_1.psEscape)(entryId)}')`;
100
+ function itemLookupScript(email, variable = 'item') {
101
+ const byStore = email.storeId
102
+ ? `try { $${variable} = $ns.GetItemFromID($lookupId, ${(0, run_1.psString)(email.storeId)}) } catch { $${variable} = $null }`
103
+ : '';
104
+ return `
105
+ $lookupId = ${(0, run_1.psString)(email.entryId)}
106
+ $${variable} = $null
107
+ ${byStore}
108
+ if ($${variable} -eq $null) { try { $${variable} = $ns.GetItemFromID($lookupId) } catch { $${variable} = $null } }
109
+ if ($${variable} -eq $null) {
110
+ throw "${(0, errors_1.failureTag)('NOT_FOUND', 'email')}No email found for entry id '$lookupId'. It may have been moved or deleted - list the mail again for a current id."
111
+ }
112
+ `;
80
113
  }
81
114
  /**
82
- * The sender's real SMTP address, as `$senderSmtp`. Requires `$item`.
115
+ * The sender's SMTP address as `$senderSmtp`. Requires `$item`.
83
116
  *
84
- * An Exchange sender's `SenderEmailAddress` is an X500 DN rather than an
85
- * address; a caller that means to reply to it, or correlate it with anything,
86
- * needs the address it resolves to.
117
+ * An Exchange sender's SenderEmailAddress is an X.500 DN, not an address; a
118
+ * caller replying to it or matching it against anything needs the address.
87
119
  */
88
120
  exports.SENDER_SMTP_PS = `
89
121
  $senderSmtp = ''
90
122
  try {
91
- if ($item.SenderEmailType -eq 'EX') { $senderSmtp = $item.Sender.GetExchangeUser().PrimarySmtpAddress }
123
+ if ($item.SenderEmailType -eq 'EX') { $senderSmtp = [string]$item.Sender.GetExchangeUser().PrimarySmtpAddress }
92
124
  } catch {}
93
- if (-not $senderSmtp) { $senderSmtp = if ($item.SenderEmailAddress) { $item.SenderEmailAddress } else { '' } }
125
+ if (-not $senderSmtp) { try { $senderSmtp = [string]$item.SenderEmailAddress } catch {} }
94
126
  `;
95
- /**
96
- * Recursive folder-by-name search. Case-insensitive, depth-capped so a huge
97
- * mailbox tree can't hang the scan.
98
- */
127
+ /** Recursive, case-insensitive folder search by name, depth-capped so a huge tree can't hang it. */
99
128
  exports.FIND_FOLDER_PS = `
100
- function Find-FolderByName($root, $name, $depth) {
129
+ function Find-FolderByName($root, [string]$name, [int]$depth) {
101
130
  foreach ($f in $root.Folders) {
102
131
  if ($f.Name -ieq $name) { return $f }
103
132
  }
@@ -110,25 +139,50 @@ function Find-FolderByName($root, $name, $depth) {
110
139
  }
111
140
  `;
112
141
  /**
113
- * Emit the PowerShell that resolves `$scope` from `$store`, walking a well-known
114
- * root down through any further segments. Also binds `$scopeCreated`.
142
+ * `$cutoff`, the moment `daysBack` days ago, and `$cutoffFilter`, that moment
143
+ * as a date string for an `Items.Restrict` filter.
115
144
  *
116
- * Split out so the emitted script can be parse-checked without an Outlook
117
- * session — the folder walk is the only part that varies per call, and a syntax
118
- * error in it would only ever surface as a failed live run.
145
+ * Restrict parses date strings in the machine's own regional format, so the
146
+ * string is formatted in it ('g': short date and time) rather than a fixed
147
+ * pattern — 'MM/dd/yyyy' reads as a different day on a day-first locale. Every
148
+ * reader re-checks each item against `$cutoff` too, so the window holds even
149
+ * where a store reads the filter loosely.
150
+ */
151
+ function cutoffScript(daysBack) {
152
+ return `
153
+ $cutoff = (Get-Date).AddDays(-${(0, run_1.psInt)(daysBack)})
154
+ $cutoffFilter = $cutoff.ToString('g').Replace("'", "''")
155
+ `;
156
+ }
157
+ /**
158
+ * `$<variable>` = the items of `$<folderVariable>` with `property` on or after
159
+ * `$cutoff`. Requires `cutoffScript`. A store that rejects the filter outright
160
+ * yields every item instead, which the per-item re-check then narrows.
161
+ */
162
+ function itemsSinceScript(folderVariable, property, variable) {
163
+ return `
164
+ $${variable} = $null
165
+ try { $${variable} = $${folderVariable}.Items.Restrict("[${property}] >= '$cutoffFilter'") } catch { $${variable} = $${folderVariable}.Items }
166
+ `;
167
+ }
168
+ /**
169
+ * Resolve `$scope` from `$store`: a well-known root walked down through any
170
+ * further segments. Also binds `$scopeCreated`.
119
171
  *
120
- * `folderLabel` is the caller's original string, used verbatim in the error so
121
- * the message names what they typed rather than the parsed segments. Set
122
- * `createMissing` to build absent segments instead of throwing — the whole
123
- * chain, so a nested destination can be created in one call.
172
+ * Segments match direct children; a bare name that isn't a direct child falls
173
+ * back to a recursive search, so one folder string works across operations. A
174
+ * missing folder fails as NOT_FOUND naming what the caller typed and what the
175
+ * deepest folder reached does hold — never a silent fall back to the root. With
176
+ * `createMissing`, the whole missing chain is created instead.
124
177
  */
125
- function mailScopeScript(ref, folderLabel = '', createMissing = false) {
126
- const root = `$store.GetDefaultFolder(${ref.rootId})`;
178
+ function mailScopeScript(ref, folderLabel, createMissing = false) {
179
+ const root = `$store.GetDefaultFolder(${(0, run_1.psInt)(ref.rootId)})`;
127
180
  if (ref.segments.length === 0)
128
181
  return `$scope = ${root}\n$scopeCreated = $false`;
129
182
  return `
130
183
  ${exports.FIND_FOLDER_PS}
131
- $segments = @(${ref.segments.map(s => `'${(0, run_1.psEscape)(s)}'`).join(',')})
184
+ $folderLabel = ${(0, run_1.psString)(folderLabel)}
185
+ $segments = @(${ref.segments.map(run_1.psString).join(', ')})
132
186
  $scopeRoot = ${root}
133
187
  $scope = $scopeRoot
134
188
  $deepest = $scopeRoot
@@ -139,13 +193,11 @@ foreach ($seg in $segments) {
139
193
  if ($next -eq $null) { $deepest = $scope; $scope = $null; break }
140
194
  $scope = $next
141
195
  }
142
- # A bare name that isn't a direct child still resolves by recursive search, so one
143
- # folder string keeps working across tools.
144
196
  if ($scope -eq $null -and $segments.Count -eq 1) {
145
197
  $scope = Find-FolderByName $scopeRoot $segments[0] 3
146
198
  }
147
199
  if ($scope -eq $null -and ${createMissing ? '$true' : '$false'}) {
148
- # Rebuild the whole chain from the root, creating only what is genuinely absent.
200
+ # Rebuild the chain from the root, creating only what is genuinely absent.
149
201
  $scope = $scopeRoot
150
202
  foreach ($seg in $segments) {
151
203
  $next = $null
@@ -157,7 +209,7 @@ if ($scope -eq $null -and ${createMissing ? '$true' : '$false'}) {
157
209
  if ($scope -eq $null) {
158
210
  $names = @()
159
211
  foreach ($f in $deepest.Folders) { $names += $f.Name }
160
- throw "Folder '${(0, run_1.psEscape)(folderLabel)}' not found. Folders under '$($deepest.Name)': $($names -join ', ')"
212
+ throw "${(0, errors_1.failureTag)('NOT_FOUND', 'folder')}Folder '$folderLabel' not found. Folders under '$($deepest.Name)': $($names -join ', ')"
161
213
  }`;
162
214
  }
163
215
  //# sourceMappingURL=scripts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/windows/scripts.ts"],"names":[],"mappings":";;;AA+BA,sCASC;AAkBD,4CAUC;AAMD,sCAIC;AAgDD,0CAoCC;AAlKD,0EAA0E;AAC1E,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,iCAAiC;AACjC,+BAAiC;AAGjC;;;;;;GAMG;AACH,MAAM,UAAU,GAAG;;;;;CAKlB,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,aAAa,CAAC,YAAoB;IAC9C,OAAO,GAAG,UAAU;aACX,IAAA,cAAQ,EAAC,YAAY,CAAC;;;;;;CAMlC,CAAC;AACF,CAAC;AAED,+EAA+E;AAClE,QAAA,iBAAiB,GAAG;;;CAGhC,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,YAAoB;IACjD,OAAO;;;;;2EAKgE,IAAA,cAAQ,EAAC,YAAY,CAAC;;;CAGhG,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAAC,OAAe,EAAE,OAAgB;IAC3D,OAAO,OAAO;QACV,CAAC,CAAC,8BAA8B,IAAA,cAAQ,EAAC,OAAO,CAAC,OAAO,IAAA,cAAQ,EAAC,OAAO,CAAC,IAAI;QAC7E,CAAC,CAAC,8BAA8B,IAAA,cAAQ,EAAC,OAAO,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED;;;;;;GAMG;AACU,QAAA,cAAc,GAAG;;;;;;CAM7B,CAAC;AAEF;;;GAGG;AACU,QAAA,cAAc,GAAG;;;;;;;;;;;;CAY7B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAgB,eAAe,CAAC,GAAkB,EAAE,WAAW,GAAG,EAAE,EAAE,aAAa,GAAG,KAAK;IACvF,MAAM,IAAI,GAAG,2BAA2B,GAAG,CAAC,MAAM,GAAG,CAAC;IACtD,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,IAAI,0BAA0B,CAAC;IACjF,OAAO;EACT,sBAAc;gBACA,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAA,cAAQ,EAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;eACpD,IAAI;;;;;;;;;;;;;;;4BAeS,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;;;;;;;;;;;;;qBAazC,IAAA,cAAQ,EAAC,WAAW,CAAC;EACxC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/windows/scripts.ts"],"names":[],"mappings":";;;AAuCA,sCAoBC;AAsCD,4CAaC;AAyCD,oCAKC;AAOD,4CAKC;AAYD,0CAmCC;AAvND,0EAA0E;AAC1E,EAAE;AACF,uEAAuE;AACvE,+EAA+E;AAC/E,8EAA8E;AAC9E,2CAA2C;AAC3C,+BAAwC;AACxC,sCAAuC;AAGvC;;;;;;GAMG;AACU,QAAA,UAAU,GAAG;;;;CAIzB,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,aAAa,CAAC,YAAoB;IAC9C,OAAO,GAAG,kBAAU;YACZ,IAAA,cAAQ,EAAC,YAAY,CAAC;;;;;;;;;;;;;;;aAerB,IAAA,mBAAU,EAAC,mBAAmB,CAAC;;CAE3C,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACU,QAAA,iBAAiB,GAAG;;;CAGhC,CAAC;AAEF;;;;;;;;GAQG;AACU,QAAA,cAAc,GAAG;;aAEjB,IAAA,mBAAU,EAAC,mBAAmB,CAAC;;;;CAI3C,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,KAAmB,EAAE,QAAQ,GAAG,MAAM;IACnE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO;QACzB,CAAC,CAAC,UAAU,QAAQ,mCAAmC,IAAA,cAAQ,EAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,QAAQ,YAAY;QAClH,CAAC,CAAC,EAAE,CAAC;IACT,OAAO;cACG,IAAA,cAAQ,EAAC,KAAK,CAAC,OAAO,CAAC;GAClC,QAAQ;EACT,OAAO;OACF,QAAQ,wBAAwB,QAAQ,8CAA8C,QAAQ;OAC9F,QAAQ;aACF,IAAA,mBAAU,EAAC,WAAW,EAAE,OAAO,CAAC;;CAE5C,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACU,QAAA,cAAc,GAAG;;;;;;CAM7B,CAAC;AAEF,oGAAoG;AACvF,QAAA,cAAc,GAAG;;;;;;;;;;;;CAY7B,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,QAAgB;IACzC,OAAO;gCACqB,IAAA,WAAK,EAAC,QAAQ,CAAC;;CAE9C,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,cAAsB,EAAE,QAAgB,EAAE,QAAgB;IACvF,OAAO;GACR,QAAQ;SACF,QAAQ,OAAO,cAAc,qBAAqB,QAAQ,qCAAqC,QAAQ,OAAO,cAAc;CACpI,CAAC;AACF,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,eAAe,CAAC,GAAkB,EAAE,WAAmB,EAAE,aAAa,GAAG,KAAK;IAC1F,MAAM,IAAI,GAAG,2BAA2B,IAAA,WAAK,EAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;IAC7D,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,IAAI,0BAA0B,CAAC;IACjF,OAAO;EACT,sBAAc;iBACC,IAAA,cAAQ,EAAC,WAAW,CAAC;gBACtB,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;eACtC,IAAI;;;;;;;;;;;;;4BAaS,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;;;;;;;;;;;;;aAajD,IAAA,mBAAU,EAAC,WAAW,EAAE,QAAQ,CAAC;EAC5C,CAAC;AACH,CAAC","sourcesContent":["// The PowerShell fragments more than one Windows operation is built from.\n//\n// A fragment lives here once two modules emit it; one used by a single\n// operation stays beside that operation, where its rules read next to the code\n// relying on them. Every fragment follows run.ts's escaping rule: caller text\n// only ever appears as a psString literal.\nimport { psInt, psString } from './run';\nimport { failureTag } from '../errors';\nimport type { EmailLocator, MailFolderRef } from '../types';\n\n/**\n * Open the MAPI session, binding `$outlook` and `$ns`.\n *\n * `Logon()` is a no-op against an Outlook that is already running and starts\n * one that isn't, which removes a class of \"works only while Outlook is open\"\n * failure.\n */\nexport const SESSION_PS = `\n$outlook = New-Object -ComObject Outlook.Application\n$ns = $outlook.GetNamespace('MAPI')\n$ns.Logon()\n`;\n\n/**\n * The session plus the mailbox an address names; binds `$target`, `$account`\n * and `$storeFolder`.\n *\n * An address can name a mailbox two ways, and only one is an Account. A mailbox\n * mounted as a secondary store — a shared mailbox, or one added after Outlook\n * started — has no Account object, so both are resolved and EITHER is enough:\n * `$account` is null for a store-only mailbox, and the operations that need an\n * identity to act as (sending) check for it themselves.\n *\n * Never falls back to the default account: a bad address must not silently\n * read or send from the wrong mailbox.\n *\n * The store is matched on the address BEFORE the account's display name, so a\n * profile where the two differ selects the same folders it always has.\n */\nexport function accountScript(emailAccount: string): string {\n return `${SESSION_PS}\n$target = ${psString(emailAccount)}\n$account = $null\nforeach ($a in $ns.Accounts) {\n if ($a.SmtpAddress -ieq $target) { $account = $a; break }\n}\n$storeFolder = $null\nforeach ($f in $ns.Folders) {\n if ($f.Name -ieq $target) { $storeFolder = $f; break }\n}\nif ($storeFolder -eq $null -and $account -ne $null) {\n foreach ($f in $ns.Folders) {\n if ($f.Name -ieq $account.DisplayName) { $storeFolder = $f; break }\n }\n}\nif ($account -eq $null -and $storeFolder -eq $null) {\n throw \"${failureTag('ACCOUNT_NOT_FOUND')}Account '$target' not found in this Outlook profile.\"\n}\n`;\n}\n\n/**\n * The mailbox's store as `$store` (and its id as `$storeId`), reached through\n * the account's delivery store. Requires `accountScript`.\n *\n * Falls back to the resolved store folder, because a store-only mailbox has no\n * account to read a delivery store off.\n */\nexport const DELIVERY_STORE_PS = `\n$store = if ($account -ne $null) { $account.DeliveryStore } else { $storeFolder.Store }\n$storeId = $store.StoreID\n`;\n\n/**\n * The mailbox's store as `$store`, reached through the namespace's top-level\n * folder for it. Requires `accountScript`.\n *\n * Kept beside DELIVERY_STORE_PS rather than replaced by it: the readers resolve\n * their store this way, and on a profile where a mailbox is open under a display\n * name that differs from its delivery store's, the two routes do not select the\n * same folders. Each operation keeps the route it was verified against.\n */\nexport const NAMED_STORE_PS = `\nif ($storeFolder -eq $null) {\n throw \"${failureTag('ACCOUNT_NOT_FOUND')}Account '$target' has no mailbox open in this Outlook profile.\"\n}\n$store = $storeFolder.Store\n$storeId = $store.StoreID\n`;\n\n/**\n * Resolve one email into `$<variable>`, or fail as NOT_FOUND.\n *\n * The StoreID is tried first, since it lets an id from any mounted mailbox\n * resolve; the bare lookup (default store) is the fallback for a caller holding\n * a stale StoreID or none.\n */\nexport function itemLookupScript(email: EmailLocator, variable = 'item'): string {\n const byStore = email.storeId\n ? `try { $${variable} = $ns.GetItemFromID($lookupId, ${psString(email.storeId)}) } catch { $${variable} = $null }`\n : '';\n return `\n$lookupId = ${psString(email.entryId)}\n$${variable} = $null\n${byStore}\nif ($${variable} -eq $null) { try { $${variable} = $ns.GetItemFromID($lookupId) } catch { $${variable} = $null } }\nif ($${variable} -eq $null) {\n throw \"${failureTag('NOT_FOUND', 'email')}No email found for entry id '$lookupId'. It may have been moved or deleted - list the mail again for a current id.\"\n}\n`;\n}\n\n/**\n * The sender's SMTP address as `$senderSmtp`. Requires `$item`.\n *\n * An Exchange sender's SenderEmailAddress is an X.500 DN, not an address; a\n * caller replying to it or matching it against anything needs the address.\n */\nexport const SENDER_SMTP_PS = `\n$senderSmtp = ''\ntry {\n if ($item.SenderEmailType -eq 'EX') { $senderSmtp = [string]$item.Sender.GetExchangeUser().PrimarySmtpAddress }\n} catch {}\nif (-not $senderSmtp) { try { $senderSmtp = [string]$item.SenderEmailAddress } catch {} }\n`;\n\n/** Recursive, case-insensitive folder search by name, depth-capped so a huge tree can't hang it. */\nexport const FIND_FOLDER_PS = `\nfunction Find-FolderByName($root, [string]$name, [int]$depth) {\n foreach ($f in $root.Folders) {\n if ($f.Name -ieq $name) { return $f }\n }\n if ($depth -le 1) { return $null }\n foreach ($f in $root.Folders) {\n $hit = Find-FolderByName $f $name ($depth - 1)\n if ($hit -ne $null) { return $hit }\n }\n return $null\n}\n`;\n\n/**\n * `$cutoff`, the moment `daysBack` days ago, and `$cutoffFilter`, that moment\n * as a date string for an `Items.Restrict` filter.\n *\n * Restrict parses date strings in the machine's own regional format, so the\n * string is formatted in it ('g': short date and time) rather than a fixed\n * pattern — 'MM/dd/yyyy' reads as a different day on a day-first locale. Every\n * reader re-checks each item against `$cutoff` too, so the window holds even\n * where a store reads the filter loosely.\n */\nexport function cutoffScript(daysBack: number): string {\n return `\n$cutoff = (Get-Date).AddDays(-${psInt(daysBack)})\n$cutoffFilter = $cutoff.ToString('g').Replace(\"'\", \"''\")\n`;\n}\n\n/**\n * `$<variable>` = the items of `$<folderVariable>` with `property` on or after\n * `$cutoff`. Requires `cutoffScript`. A store that rejects the filter outright\n * yields every item instead, which the per-item re-check then narrows.\n */\nexport function itemsSinceScript(folderVariable: string, property: string, variable: string): string {\n return `\n$${variable} = $null\ntry { $${variable} = $${folderVariable}.Items.Restrict(\"[${property}] >= '$cutoffFilter'\") } catch { $${variable} = $${folderVariable}.Items }\n`;\n}\n\n/**\n * Resolve `$scope` from `$store`: a well-known root walked down through any\n * further segments. Also binds `$scopeCreated`.\n *\n * Segments match direct children; a bare name that isn't a direct child falls\n * back to a recursive search, so one folder string works across operations. A\n * missing folder fails as NOT_FOUND naming what the caller typed and what the\n * deepest folder reached does hold — never a silent fall back to the root. With\n * `createMissing`, the whole missing chain is created instead.\n */\nexport function mailScopeScript(ref: MailFolderRef, folderLabel: string, createMissing = false): string {\n const root = `$store.GetDefaultFolder(${psInt(ref.rootId)})`;\n if (ref.segments.length === 0) return `$scope = ${root}\\n$scopeCreated = $false`;\n return `\n${FIND_FOLDER_PS}\n$folderLabel = ${psString(folderLabel)}\n$segments = @(${ref.segments.map(psString).join(', ')})\n$scopeRoot = ${root}\n$scope = $scopeRoot\n$deepest = $scopeRoot\n$scopeCreated = $false\nforeach ($seg in $segments) {\n $next = $null\n foreach ($f in $scope.Folders) { if ($f.Name -ieq $seg) { $next = $f; break } }\n if ($next -eq $null) { $deepest = $scope; $scope = $null; break }\n $scope = $next\n}\nif ($scope -eq $null -and $segments.Count -eq 1) {\n $scope = Find-FolderByName $scopeRoot $segments[0] 3\n}\nif ($scope -eq $null -and ${createMissing ? '$true' : '$false'}) {\n # Rebuild the chain from the root, creating only what is genuinely absent.\n $scope = $scopeRoot\n foreach ($seg in $segments) {\n $next = $null\n foreach ($f in $scope.Folders) { if ($f.Name -ieq $seg) { $next = $f; break } }\n if ($next -eq $null) { $next = $scope.Folders.Add($seg); $scopeCreated = $true }\n $scope = $next\n }\n}\nif ($scope -eq $null) {\n $names = @()\n foreach ($f in $deepest.Folders) { $names += $f.Name }\n throw \"${failureTag('NOT_FOUND', 'folder')}Folder '$folderLabel' not found. Folders under '$($deepest.Name)': $($names -join ', ')\"\n}`;\n}\n"]}
@@ -1,11 +1,6 @@
1
- import type { ReplyEmailParams, ReplyEmailResult, SendEmailParams } from '../types';
2
- /** Send (or display for review) an email through Outlook COM. */
3
- export declare function sendOutlookEmail(params: SendEmailParams): Promise<void>;
4
- /**
5
- * Reply to an email, inserting the caller's HTML above the quoted original.
6
- *
7
- * The body may be given directly or named as a saved template — see
8
- * `composeReplyHtml`, which resolves the template, its section and its
9
- * placeholders before anything reaches Outlook.
10
- */
11
- export declare function replyOutlookEmail(params: ReplyEmailParams): Promise<ReplyEmailResult>;
1
+ import type { ReplyRequest, SendRequest } from '../backend';
2
+ import type { ReplyEmailResult } from '../types';
3
+ /** Send, display or file a new email. */
4
+ export declare function sendOutlookEmail(request: SendRequest): Promise<void>;
5
+ /** Reply to an email, with the composed HTML above the quoted original. */
6
+ export declare function replyOutlookEmail(request: ReplyRequest): Promise<ReplyEmailResult>;