@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.
Files changed (142) hide show
  1. package/README.md +152 -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 +79 -43
  9. package/dist/errors.js +93 -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 +96 -117
  22. package/dist/mac/bounces.js.map +1 -1
  23. package/dist/mac/cleanup.d.ts +11 -25
  24. package/dist/mac/cleanup.js +44 -107
  25. package/dist/mac/cleanup.js.map +1 -1
  26. package/dist/mac/drafts.d.ts +15 -34
  27. package/dist/mac/drafts.js +113 -186
  28. package/dist/mac/drafts.js.map +1 -1
  29. package/dist/mac/folders.d.ts +12 -21
  30. package/dist/mac/folders.js +44 -59
  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 +21 -37
  39. package/dist/mac/read.js +198 -216
  40. package/dist/mac/read.js.map +1 -1
  41. package/dist/mac/run.d.ts +51 -38
  42. package/dist/mac/run.js +138 -103
  43. package/dist/mac/run.js.map +1 -1
  44. package/dist/mac/scripts.d.ts +90 -91
  45. package/dist/mac/scripts.js +167 -126
  46. package/dist/mac/scripts.js.map +1 -1
  47. package/dist/mac/send.d.ts +10 -20
  48. package/dist/mac/send.js +99 -89
  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 +79 -120
  55. package/dist/mac/templates.js.map +1 -1
  56. package/dist/mail.d.ts +80 -46
  57. package/dist/mail.js +179 -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 +26 -20
  66. package/dist/shared/attachmentMatch.js +60 -23
  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 +17 -6
  78. package/dist/shared/json.js +35 -24
  79. package/dist/shared/json.js.map +1 -1
  80. package/dist/shared/locate.d.ts +31 -0
  81. package/dist/shared/locate.js +128 -0
  82. package/dist/shared/locate.js.map +1 -0
  83. package/dist/shared/replyBody.d.ts +31 -36
  84. package/dist/shared/replyBody.js +83 -72
  85. package/dist/shared/replyBody.js.map +1 -1
  86. package/dist/shared/templateLimits.d.ts +14 -0
  87. package/dist/shared/templateLimits.js +21 -0
  88. package/dist/shared/templateLimits.js.map +1 -0
  89. package/dist/templateBody.d.ts +69 -0
  90. package/dist/{outlookTemplateSections.js → templateBody.js} +80 -73
  91. package/dist/templateBody.js.map +1 -0
  92. package/dist/types.d.ts +381 -168
  93. package/dist/types.js +8 -9
  94. package/dist/types.js.map +1 -1
  95. package/dist/windows/accounts.d.ts +7 -12
  96. package/dist/windows/accounts.js +19 -34
  97. package/dist/windows/accounts.js.map +1 -1
  98. package/dist/windows/attachments.d.ts +9 -24
  99. package/dist/windows/attachments.js +94 -119
  100. package/dist/windows/attachments.js.map +1 -1
  101. package/dist/windows/bounces.d.ts +13 -26
  102. package/dist/windows/bounces.js +168 -200
  103. package/dist/windows/bounces.js.map +1 -1
  104. package/dist/windows/cleanup.d.ts +23 -23
  105. package/dist/windows/cleanup.js +99 -113
  106. package/dist/windows/cleanup.js.map +1 -1
  107. package/dist/windows/drafts.d.ts +16 -35
  108. package/dist/windows/drafts.js +156 -253
  109. package/dist/windows/drafts.js.map +1 -1
  110. package/dist/windows/folders.d.ts +8 -13
  111. package/dist/windows/folders.js +44 -52
  112. package/dist/windows/folders.js.map +1 -1
  113. package/dist/windows/index.d.ts +2 -27
  114. package/dist/windows/index.js +11 -66
  115. package/dist/windows/index.js.map +1 -1
  116. package/dist/windows/read.d.ts +24 -60
  117. package/dist/windows/read.js +265 -306
  118. package/dist/windows/read.js.map +1 -1
  119. package/dist/windows/run.d.ts +38 -40
  120. package/dist/windows/run.js +151 -112
  121. package/dist/windows/run.js.map +1 -1
  122. package/dist/windows/scripts.d.ts +65 -55
  123. package/dist/windows/scripts.js +109 -85
  124. package/dist/windows/scripts.js.map +1 -1
  125. package/dist/windows/send.d.ts +9 -9
  126. package/dist/windows/send.js +76 -88
  127. package/dist/windows/send.js.map +1 -1
  128. package/dist/windows/signatures.d.ts +4 -10
  129. package/dist/windows/signatures.js +30 -37
  130. package/dist/windows/signatures.js.map +1 -1
  131. package/dist/windows/templates.d.ts +12 -18
  132. package/dist/windows/templates.js +117 -150
  133. package/dist/windows/templates.js.map +1 -1
  134. package/package.json +5 -4
  135. package/dist/OutlookService.d.ts +0 -43
  136. package/dist/OutlookService.js +0 -137
  137. package/dist/OutlookService.js.map +0 -1
  138. package/dist/outlookTemplateSections.d.ts +0 -62
  139. package/dist/outlookTemplateSections.js.map +0 -1
  140. package/dist/shared/capabilities.d.ts +0 -3
  141. package/dist/shared/capabilities.js +0 -9
  142. package/dist/shared/capabilities.js.map +0 -1
package/dist/mac/send.js CHANGED
@@ -5,90 +5,106 @@ exports.replyOutlookEmail = replyOutlookEmail;
5
5
  // Composing outgoing mail on macOS: a new email, and a reply to an existing one.
6
6
  const run_1 = require("./run");
7
7
  const scripts_1 = require("./scripts");
8
- const replyBody_1 = require("../shared/replyBody");
9
- const signatures_1 = require("./signatures");
10
- const templates_1 = require("./templates");
11
- /** Split a To/CC string the way the Windows contract accepts it. */
12
- function splitAddresses(s) {
13
- return s.split(/[,;]+/).map(x => x.trim()).filter(Boolean);
14
- }
8
+ const args_1 = require("../shared/args");
15
9
  /**
16
- * What to do with a composed item.
10
+ * What to do with a composed message. A filed draft leaves its id in
11
+ * `filedDraftId` ("" for the other dispositions, or when it can't be told).
12
+ *
13
+ * A new outgoing message lands in Temporary Items, not Drafts — `open` only
14
+ * shows it — so a windowless draft is moved into Drafts explicitly. `move`
15
+ * reports success even where it silently does nothing, so the folder is
16
+ * confirmed to hold a message it didn't before rather than report a draft that
17
+ * doesn't exist.
17
18
  *
18
- * A new outgoing message lands in Temporary Items, not Drafts — `open` is what
19
- * surfaces it, so a windowless draft has to be moved into the Drafts folder
20
- * explicitly. (`save` is no help: it demands a file destination, not a folder.)
21
- * `move` reports success even where it silently does nothing, so the folder is
22
- * confirmed to have grown rather than risk reporting a draft that doesn't exist.
19
+ * Moving rewrites a message's id, so the draft's id is the one Drafts gained.
20
+ * Another draft can land in the same moment — an autosave of a compose window,
21
+ * a sync — and then the subject tells them apart; a tie is left unnamed rather
22
+ * than guessed, since a caller that keeps the id may later send by it.
23
23
  */
24
- function composeAction(variable, sendImmediately, openDraftWindow) {
25
- if (sendImmediately)
26
- return { prelude: '', action: ` send ${variable}` };
27
- if (openDraftWindow !== false)
28
- return { prelude: '', action: ` open ${variable}` };
29
- return {
30
- prelude: ` set draftsFolder to drafts of targetAcct
31
- set draftsBefore to count of messages of draftsFolder`,
32
- action: ` move ${variable} to draftsFolder
33
- if (count of messages of draftsFolder) is not greater than draftsBefore then error "Outlook did not file the draft in the Drafts folder."`,
34
- };
24
+ function dispose(variable, disposition) {
25
+ switch (disposition) {
26
+ case 'send':
27
+ return { prelude: ' set filedDraftId to ""', action: ` send ${variable}` };
28
+ case 'display':
29
+ return { prelude: ' set filedDraftId to ""', action: ` open ${variable}` };
30
+ case 'save':
31
+ return {
32
+ prelude: ` set filedDraftId to ""
33
+ set draftsFolder to drafts of targetAcct
34
+ set draftIdsBefore to id of every message of draftsFolder`,
35
+ action: ` set filedSubject to ""
36
+ try
37
+ set filedSubject to (subject of ${variable}) as string
38
+ end try
39
+ move ${variable} to draftsFolder
40
+ -- Bound before the loop, so it walks a local list rather than asking
41
+ -- Outlook for each item in turn.
42
+ set draftIdsAfter to id of every message of draftsFolder
43
+ set newIds to {}
44
+ repeat with anId in draftIdsAfter
45
+ if draftIdsBefore does not contain (contents of anId) then set end of newIds to (contents of anId)
46
+ end repeat
47
+ if (count of newIds) is 0 then error "Outlook did not file the draft in the Drafts folder."
48
+ if (count of newIds) is 1 then
49
+ set filedDraftId to (item 1 of newIds) as string
50
+ else
51
+ set sameSubject to {}
52
+ repeat with anId in newIds
53
+ try
54
+ if ((subject of message id (contents of anId)) as string) is filedSubject then set end of sameSubject to (contents of anId)
55
+ end try
56
+ end repeat
57
+ if (count of sameSubject) is 1 then set filedDraftId to (item 1 of sameSubject) as string
58
+ end if`,
59
+ };
60
+ }
35
61
  }
36
- /**
37
- * Create an Outlook email as a draft window (or send it) via AppleScript.
38
- * Mirrors the Windows COM contract from windows/send.ts.
39
- */
40
- async function sendOutlookEmail(params) {
41
- // Same safety property as Windows: never silently send from the wrong mailbox.
42
- // The account lookup raises when the address doesn't resolve, so there's no
43
- // pre-flight getOutlookAccounts() round-trip — it cost an extra osascript
44
- // launch on every email in a batch.
45
- const recipientLines = [
46
- ...splitAddresses(params.to).map(addr => ` make new to recipient at newMsg with properties {email address:{address:"${(0, run_1.asEscape)(addr)}"}}`),
47
- ...splitAddresses(params.cc || '').map(addr => ` make new cc recipient at newMsg with properties {email address:{address:"${(0, run_1.asEscape)(addr)}"}}`),
48
- ].join('\n');
49
- const attachLine = params.attachmentPath
50
- ? ` make new attachment at newMsg with properties {file:POSIX file "${(0, run_1.asEscape)(params.attachmentPath)}"}`
51
- : '';
52
- const { prelude, action } = composeAction('newMsg', params.sendImmediately, params.openDraftWindow);
53
- const script = `
62
+ /** One `make new … recipient` line per entry, keeping a display name when given. */
63
+ function recipientLines(kind, entries) {
64
+ return entries.map(entry => {
65
+ const { name, address } = (0, args_1.parseRecipient)(entry);
66
+ const emailAddress = name
67
+ ? `{name:${(0, run_1.asString)(name)}, address:${(0, run_1.asString)(address)}}`
68
+ : `{address:${(0, run_1.asString)(address)}}`;
69
+ return ` make new ${kind} recipient at newMsg with properties {email address:${emailAddress}}`;
70
+ });
71
+ }
72
+ /** Send, display or file a new email; a filed draft reports its id. */
73
+ async function sendOutlookEmail(request) {
74
+ const acct = await (0, scripts_1.resolveMacAccount)(request.account);
75
+ const { prelude, action } = dispose('newMsg', request.disposition);
76
+ const lines = [
77
+ ...recipientLines('to', request.to),
78
+ ...recipientLines('cc', request.cc),
79
+ ...recipientLines('bcc', request.bcc),
80
+ ...request.attachments.map(file => ` make new attachment at newMsg with properties {file:POSIX file ${(0, run_1.asString)(file)}}`),
81
+ ];
82
+ const raw = await (0, run_1.runOsaScript)(`
54
83
  tell application "Microsoft Outlook"
55
- ${(0, scripts_1.accountLookupSnippet)(params.emailAccount)}
84
+ ${(0, scripts_1.accountLookupSnippet)(acct, true)}
56
85
  ${prelude}
57
- set newMsg to make new outgoing message with properties {subject:"${(0, run_1.asEscape)(params.subject)}", content:"${(0, run_1.asEscape)(params.htmlBody)}"}
58
- ${recipientLines}
86
+ set newMsg to make new outgoing message with properties {subject:${(0, run_1.asString)(request.subject)}, content:${(0, run_1.asString)(request.htmlBody)}}
87
+ ${lines.join('\n')}
59
88
  set account of newMsg to targetAcct
60
- ${attachLine}
61
89
  ${action}
62
- end tell`;
63
- await (0, run_1.runOsaScript)(script, 120000);
90
+ return filedDraftId
91
+ end tell`, 'standard');
92
+ return { draftEntryId: raw.trim() };
64
93
  }
65
94
  /**
66
- * Reply to an email, inserting the caller's HTML above the quoted original.
95
+ * Reply to an email with the composed HTML above the quoted original.
67
96
  *
68
- * `entryId` is Outlook for Mac's small integer message id (see readInboxEmails),
69
- * not a Windows MAPI EntryID; `storeId` is accepted for signature parity and
70
- * ignored, since macOS has no StoreID and `message id N` resolves against the
71
- * application rather than one folder.
72
- *
73
- * `reply to` builds the quoted body Outlook itself would have — the same thing
74
- * COM's Reply() returns — so the insertion point is the one place the two
75
- * platforms have to agree, and both look for WordSection1 then `<body>`.
76
- *
77
- * The `to` line is the reply's resolved recipient addresses rather than the
78
- * display-name string Windows reports: Outlook for Mac exposes recipients as
79
- * records, and an address is the more useful half to verify against.
97
+ * `reply to` builds the same quoted body COM's Reply() returns, so the insertion
98
+ * point is the one thing the platforms must agree on (see WORD_SECTION_ANCHOR).
99
+ * `to` comes back as the reply's resolved addresses: Outlook for Mac exposes
100
+ * recipients as records, and the address is the half worth checking.
80
101
  */
81
- async function replyOutlookEmail(params) {
82
- const id = (0, scripts_1.macMessageId)(params.entryId);
83
- const insertHtml = await (0, replyBody_1.composeReplyHtml)(params, {
84
- readTemplateEmails: templates_1.readTemplateEmails,
85
- readOutlookSignatureHtml: signatures_1.readOutlookSignatureHtml,
86
- listOutlookSignatures: signatures_1.listOutlookSignatures,
87
- });
88
- const { prelude, action } = composeAction('theReply', params.sendImmediately, params.openDraftWindow);
89
- const replyAll = params.replyAll ? 'reply to all true' : 'without reply to all';
90
- const script = `tell application "Microsoft Outlook"
91
- ${(0, scripts_1.accountLookupSnippet)(params.emailAccount)}
102
+ async function replyOutlookEmail(request) {
103
+ const id = (0, scripts_1.macMessageId)(request.email.entryId);
104
+ const acct = await (0, scripts_1.resolveMacAccount)(request.account);
105
+ const { prelude, action } = dispose('theReply', request.disposition);
106
+ const raw = await (0, run_1.runOsaScript)(`tell application "Microsoft Outlook"
107
+ ${(0, scripts_1.accountLookupSnippet)(acct, true)}
92
108
  ${(0, scripts_1.messageLookupSnippet)(id)}
93
109
  set repliedTo to ""
94
110
  try
@@ -98,16 +114,14 @@ ${(0, scripts_1.messageLookupSnippet)(id)}
98
114
  set repliedTo to (address of origSender) as string
99
115
  end try
100
116
  ${prelude}
101
- set theReply to reply to theMsg opening window false ${replyAll}
102
- -- Neither of these is wrapped in a try, and both would read more defensively
103
- -- if they were. A swallowed account assignment sends from whichever mailbox
104
- -- Outlook considers default, and a swallowed insertion files a reply with the
105
- -- caller's text missing — the two failures this package exists to prevent,
106
- -- both of them invisible to the caller if tolerated here.
117
+ set theReply to reply to theMsg opening window false ${request.replyAll ? 'reply to all true' : 'without reply to all'}
118
+ -- Neither of these is wrapped in a try. A swallowed account assignment sends
119
+ -- from the default mailbox, and a swallowed insertion files a reply missing
120
+ -- its text — both invisible to the caller if tolerated here.
107
121
  set account of theReply to targetAcct
108
- set content of theReply to my insertAboveQuoted(content of theReply, "${(0, run_1.asEscape)(insertHtml)}")
109
- -- Read the outgoing fields BEFORE acting: sending moves the item, after which
110
- -- the reference is no longer readable.
122
+ set content of theReply to my insertAboveQuoted(content of theReply, ${(0, run_1.asString)(request.html)})
123
+ -- Read the outgoing fields BEFORE acting: sending moves the item, and the
124
+ -- reference can't be read afterwards.
111
125
  set toList to {}
112
126
  try
113
127
  repeat with r in (every to recipient of theReply)
@@ -123,13 +137,9 @@ ${prelude}
123
137
  set subj to (subject of theReply) as string
124
138
  end try
125
139
  ${action}
126
- return my sanitize(toLine) & (character id 31) & my sanitize(subj) & (character id 31) & my sanitize(repliedTo)
127
- end tell`;
128
- const parts = (0, run_1.splitFields)(await (0, run_1.runOsaScript)(script, 120000));
129
- return {
130
- to: (0, run_1.field)(parts, 0),
131
- subject: (0, run_1.field)(parts, 1),
132
- repliedToSender: (0, run_1.field)(parts, 2),
133
- };
140
+ return ${(0, run_1.asRow)(['toLine', 'subj', 'repliedTo'])}
141
+ end tell`, 'standard');
142
+ const parts = (0, run_1.summaryFields)(raw);
143
+ return { to: (0, run_1.field)(parts, 0), subject: (0, run_1.field)(parts, 1), repliedToSender: (0, run_1.field)(parts, 2) };
134
144
  }
135
145
  //# sourceMappingURL=send.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/mac/send.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/mac/send.ts"],"names":[],"mappings":"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","sourcesContent":["// Composing outgoing mail on macOS: a new email, and a reply to an existing one.\nimport { asRow, asString, field, runOsaScript, summaryFields } from './run';\nimport { accountLookupSnippet, macMessageId, messageLookupSnippet, resolveMacAccount } from './scripts';\nimport { parseRecipient } from '../shared/args';\nimport type { Disposition, ReplyRequest, SendRequest } from '../backend';\nimport type { ReplyEmailResult, SendEmailResult } from '../types';\n\n/**\n * What to do with a composed message. A filed draft leaves its id in\n * `filedDraftId` (\"\" for the other dispositions, or when it can't be told).\n *\n * A new outgoing message lands in Temporary Items, not Drafts — `open` only\n * shows it — so a windowless draft is moved into Drafts explicitly. `move`\n * reports success even where it silently does nothing, so the folder is\n * confirmed to hold a message it didn't before rather than report a draft that\n * doesn't exist.\n *\n * Moving rewrites a message's id, so the draft's id is the one Drafts gained.\n * Another draft can land in the same moment — an autosave of a compose window,\n * a sync — and then the subject tells them apart; a tie is left unnamed rather\n * than guessed, since a caller that keeps the id may later send by it.\n */\nfunction dispose(variable: string, disposition: Disposition): { prelude: string; action: string } {\n switch (disposition) {\n case 'send':\n return { prelude: ' set filedDraftId to \"\"', action: ` send ${variable}` };\n case 'display':\n return { prelude: ' set filedDraftId to \"\"', action: ` open ${variable}` };\n case 'save':\n return {\n prelude: ` set filedDraftId to \"\"\n set draftsFolder to drafts of targetAcct\n set draftIdsBefore to id of every message of draftsFolder`,\n action: ` set filedSubject to \"\"\n try\n set filedSubject to (subject of ${variable}) as string\n end try\n move ${variable} to draftsFolder\n -- Bound before the loop, so it walks a local list rather than asking\n -- Outlook for each item in turn.\n set draftIdsAfter to id of every message of draftsFolder\n set newIds to {}\n repeat with anId in draftIdsAfter\n if draftIdsBefore does not contain (contents of anId) then set end of newIds to (contents of anId)\n end repeat\n if (count of newIds) is 0 then error \"Outlook did not file the draft in the Drafts folder.\"\n if (count of newIds) is 1 then\n set filedDraftId to (item 1 of newIds) as string\n else\n set sameSubject to {}\n repeat with anId in newIds\n try\n if ((subject of message id (contents of anId)) as string) is filedSubject then set end of sameSubject to (contents of anId)\n end try\n end repeat\n if (count of sameSubject) is 1 then set filedDraftId to (item 1 of sameSubject) as string\n end if`,\n };\n }\n}\n\n/** One `make new … recipient` line per entry, keeping a display name when given. */\nfunction recipientLines(kind: 'to' | 'cc' | 'bcc', entries: readonly string[]): string[] {\n return entries.map(entry => {\n const { name, address } = parseRecipient(entry);\n const emailAddress = name\n ? `{name:${asString(name)}, address:${asString(address)}}`\n : `{address:${asString(address)}}`;\n return ` make new ${kind} recipient at newMsg with properties {email address:${emailAddress}}`;\n });\n}\n\n/** Send, display or file a new email; a filed draft reports its id. */\nexport async function sendOutlookEmail(request: SendRequest): Promise<SendEmailResult> {\n const acct = await resolveMacAccount(request.account);\n const { prelude, action } = dispose('newMsg', request.disposition);\n const lines = [\n ...recipientLines('to', request.to),\n ...recipientLines('cc', request.cc),\n ...recipientLines('bcc', request.bcc),\n ...request.attachments.map(file => ` make new attachment at newMsg with properties {file:POSIX file ${asString(file)}}`),\n ];\n const raw = await runOsaScript(`\ntell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct, true)}\n${prelude}\n set newMsg to make new outgoing message with properties {subject:${asString(request.subject)}, content:${asString(request.htmlBody)}}\n${lines.join('\\n')}\n set account of newMsg to targetAcct\n${action}\n return filedDraftId\nend tell`, 'standard');\n return { draftEntryId: raw.trim() };\n}\n\n/**\n * Reply to an email with the composed HTML above the quoted original.\n *\n * `reply to` builds the same quoted body COM's Reply() returns, so the insertion\n * point is the one thing the platforms must agree on (see WORD_SECTION_ANCHOR).\n * `to` comes back as the reply's resolved addresses: Outlook for Mac exposes\n * recipients as records, and the address is the half worth checking.\n */\nexport async function replyOutlookEmail(request: ReplyRequest): Promise<ReplyEmailResult> {\n const id = macMessageId(request.email.entryId);\n const acct = await resolveMacAccount(request.account);\n const { prelude, action } = dispose('theReply', request.disposition);\n const raw = await runOsaScript(`tell application \"Microsoft Outlook\"\n${accountLookupSnippet(acct, true)}\n${messageLookupSnippet(id)}\n set repliedTo to \"\"\n try\n -- Bind the record before reading its field: a nested\n -- 'address of (sender of theMsg)' does not coerce.\n set origSender to sender of theMsg\n set repliedTo to (address of origSender) as string\n end try\n${prelude}\n set theReply to reply to theMsg opening window false ${request.replyAll ? 'reply to all true' : 'without reply to all'}\n -- Neither of these is wrapped in a try. A swallowed account assignment sends\n -- from the default mailbox, and a swallowed insertion files a reply missing\n -- its text — both invisible to the caller if tolerated here.\n set account of theReply to targetAcct\n set content of theReply to my insertAboveQuoted(content of theReply, ${asString(request.html)})\n -- Read the outgoing fields BEFORE acting: sending moves the item, and the\n -- reference can't be read afterwards.\n set toList to {}\n try\n repeat with r in (every to recipient of theReply)\n try\n set ea to email address of r\n set end of toList to (address of ea) as string\n end try\n end repeat\n end try\n set toLine to my joinList(toList, \", \")\n set subj to \"\"\n try\n set subj to (subject of theReply) as string\n end try\n${action}\n return ${asRow(['toLine', 'subj', 'repliedTo'])}\nend tell`, 'standard');\n const parts = summaryFields(raw);\n return { to: field(parts, 0), subject: field(parts, 1), repliedToSender: field(parts, 2) };\n}\n"]}
@@ -1,4 +1,4 @@
1
- /** Names of the user's Outlook signatures. */
1
+ /** The signature names, sorted. */
2
2
  export declare function listOutlookSignatures(): Promise<string[]>;
3
- /** Read a named signature's HTML. Returns '' if the signature can't be found. */
3
+ /** A signature's HTML; '' when there is no signature by that name. */
4
4
  export declare function readOutlookSignatureHtml(name: string): Promise<string>;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listOutlookSignatures = listOutlookSignatures;
4
4
  exports.readOutlookSignatureHtml = readOutlookSignatureHtml;
5
- // Unlike Windows (files on disk), Outlook for Mac serves signature content
6
- // directly through AppleScript, images included (inline data or remote refs).
5
+ // Outlook for Mac serves signatures through AppleScript, images included
6
+ // (inline data or remote references), where Windows keeps them as files.
7
7
  const run_1 = require("./run");
8
- /** Names of the user's Outlook signatures. */
8
+ /** The signature names, sorted. */
9
9
  async function listOutlookSignatures() {
10
- const script = `
10
+ const raw = await (0, run_1.runOsaScript)(`
11
11
  set sigNames to {}
12
12
  tell application "Microsoft Outlook"
13
13
  try
@@ -17,20 +17,18 @@ tell application "Microsoft Outlook"
17
17
  end try
18
18
  end tell
19
19
  set AppleScript's text item delimiters to linefeed
20
- return sigNames as string`;
21
- const raw = await (0, run_1.runOsaScript)(script, 15000);
20
+ return sigNames as string`, 'quick');
22
21
  return raw.split('\n').map(s => s.trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));
23
22
  }
24
- /** Read a named signature's HTML. Returns '' if the signature can't be found. */
23
+ /** A signature's HTML; '' when there is no signature by that name. */
25
24
  async function readOutlookSignatureHtml(name) {
26
- const script = `
25
+ return (0, run_1.runOsaScript)(`
27
26
  tell application "Microsoft Outlook"
28
27
  try
29
- return content of (first signature whose name is "${(0, run_1.asEscape)(name)}")
28
+ return content of (first signature whose name is ${(0, run_1.asString)(name)})
30
29
  on error
31
30
  return ""
32
31
  end try
33
- end tell`;
34
- return (0, run_1.runOsaScript)(script, 15000);
32
+ end tell`, 'quick');
35
33
  }
36
34
  //# sourceMappingURL=signatures.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signatures.js","sourceRoot":"","sources":["../../src/mac/signatures.ts"],"names":[],"mappings":";;AAKA,sDAcC;AAGD,4DAUC;AAhCD,2EAA2E;AAC3E,8EAA8E;AAC9E,+BAA+C;AAE/C,8CAA8C;AACvC,KAAK,UAAU,qBAAqB;IACvC,MAAM,MAAM,GAAG;;;;;;;;;;0BAUO,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,IAAA,kBAAY,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC;AAED,iFAAiF;AAC1E,KAAK,UAAU,wBAAwB,CAAC,IAAY;IACvD,MAAM,MAAM,GAAG;;;4DAGyC,IAAA,cAAQ,EAAC,IAAI,CAAC;;;;SAIjE,CAAC;IACN,OAAO,IAAA,kBAAY,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"signatures.js","sourceRoot":"","sources":["../../src/mac/signatures.ts"],"names":[],"mappings":";;AAKA,sDAaC;AAGD,4DASC;AA9BD,yEAAyE;AACzE,yEAAyE;AACzE,+BAA+C;AAE/C,mCAAmC;AAC5B,KAAK,UAAU,qBAAqB;IACvC,MAAM,GAAG,GAAG,MAAM,IAAA,kBAAY,EAAC;;;;;;;;;;0BAUT,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC;AAED,sEAAsE;AAC/D,KAAK,UAAU,wBAAwB,CAAC,IAAY;IACvD,OAAO,IAAA,kBAAY,EAAC;;;2DAGmC,IAAA,cAAQ,EAAC,IAAI,CAAC;;;;SAIhE,EAAE,OAAO,CAAC,CAAC;AACpB,CAAC","sourcesContent":["// Outlook for Mac serves signatures through AppleScript, images included\n// (inline data or remote references), where Windows keeps them as files.\nimport { asString, runOsaScript } from './run';\n\n/** The signature names, sorted. */\nexport async function listOutlookSignatures(): Promise<string[]> {\n const raw = await runOsaScript(`\nset sigNames to {}\ntell application \"Microsoft Outlook\"\n try\n repeat with s in signatures\n set end of sigNames to (name of s as string)\n end repeat\n end try\nend tell\nset AppleScript's text item delimiters to linefeed\nreturn sigNames as string`, 'quick');\n return raw.split('\\n').map(s => s.trim()).filter(Boolean).sort((a, b) => a.localeCompare(b));\n}\n\n/** A signature's HTML; '' when there is no signature by that name. */\nexport async function readOutlookSignatureHtml(name: string): Promise<string> {\n return runOsaScript(`\ntell application \"Microsoft Outlook\"\n try\n return content of (first signature whose name is ${asString(name)})\n on error\n return \"\"\n end try\nend tell`, 'quick');\n}\n"]}
@@ -1,34 +1,22 @@
1
+ import type { EditTemplateRequest, ReadTemplatesRequest, SaveTemplateRequest } from '../backend';
1
2
  import type { SaveTemplateResult, TemplateFolderResult } from '../types';
2
3
  /**
3
- * Read the template emails saved in a mailbox folder (default "Templates"),
4
- * returning each item's full HTML body. When the folder doesn't exist, returns
5
- * folderFound:false plus the mailbox's folder names instead of throwing, so the
6
- * caller can ask the user whether to create it rather than fail.
4
+ * The template emails in a mailbox folder, newest first; a missing folder is
5
+ * reported as folderFound:false with the mailbox's top-level folder names.
7
6
  *
8
- * Bodies are read in a second pass, for the chosen templates only. That is not
9
- * a micro-optimisation: a folder of Word-sized templates is megabytes, and
10
- * pulling all of them through stdout on a call that wanted one is what overruns
11
- * the buffer — the same reason the Windows reader filters before reading.
7
+ * Bodies are read in a second pass, for the chosen templates only: a folder of
8
+ * Word-sized templates is megabytes, and pulling all of them through stdout on
9
+ * a call that wanted one is what overruns the output limit.
12
10
  */
13
- export declare function readTemplateEmails(emailAccount: string, folderName?: string, limit?: number, includeBody?: boolean, subject?: string): Promise<TemplateFolderResult>;
11
+ export declare function readTemplateEmails(request: ReadTemplatesRequest): Promise<TemplateFolderResult>;
14
12
  /**
15
- * Save a new template email into a mailbox folder (default "Templates"),
16
- * creating the folder at the mailbox root if it doesn't exist. The item is a
17
- * plain unsent mail (subject + HTML body) that can be edited in Outlook.
18
- * Never overwrites an existing item — it always adds a new one, so check with
19
- * readTemplateEmails first and only call after the user has agreed to create it.
13
+ * Save a new template email into a folder, creating the folder at the mailbox
14
+ * root when absent. Always adds a new item — never overwrites one.
20
15
  */
21
- export declare function saveTemplateEmail(emailAccount: string, subject: string, htmlBody: string, folderName?: string): Promise<SaveTemplateResult>;
16
+ export declare function saveTemplateEmail(request: SaveTemplateRequest): Promise<SaveTemplateResult>;
22
17
  /**
23
- * Open an Outlook compose window pre-filled with `currentHtml`, wait for the
24
- * user to close it, and return the HTML they saved.
25
- *
26
- * Deliberately unbounded: the run lasts as long as the person is editing. Give
27
- * it an AbortSignal (`bridge.withOptions({ signal })`) if the caller needs a way
28
- * to give up on them.
29
- *
30
- * The macOS half of the round trip differs from Windows in one visible way: an
31
- * edited draft is filed by answering Outlook's own "save this message?" prompt
32
- * on close, so the subject tells the user to save rather than to press a key.
18
+ * Open a compose window pre-filled with the HTML, wait for it to close, and
19
+ * return the saved draft's HTML. On macOS the edit is kept by answering
20
+ * Outlook's own "save this message?" prompt on close.
33
21
  */
34
- export declare function editEmailTemplate(label: string, currentHtml: string): Promise<string>;
22
+ export declare function editEmailTemplate(request: EditTemplateRequest): Promise<string>;