@littlebearapps/outlook-assistant 3.11.2 → 3.12.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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Mailbox scoping helper.
3
+ *
4
+ * Every Graph path in this server is built as `${prefix}/...`. The prefix is
5
+ * `me` for the signed-in account, or `users/{email}` for a shared/delegated
6
+ * mailbox. Keeping the construction in one place is what lets the shared-mailbox
7
+ * parameter be threaded through readers, writers, and folder resolution without
8
+ * each call site re-deciding the shape.
9
+ */
10
+
11
+ // Pragmatic SMTP address / UPN shape — deliberately not full RFC 5322. The
12
+ // point is to keep caller input inside a single Graph path segment, so only
13
+ // printable ASCII is accepted: RFC 5322 `atext` in the local part minus `#`
14
+ // (a URL fragment delimiter), and dot-separated letters/digits/hyphens in the
15
+ // domain. No whitespace, control characters, `/ ? # % \`, or non-ASCII
16
+ // look-alikes (full-width `/`, zero-width spaces). The tool schemas advertise
17
+ // an email address only, so bare user GUIDs are not accepted.
18
+ const MAILBOX_PATTERN =
19
+ /^[A-Za-z0-9.!$&'*+=^_`{|}~-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)+$/;
20
+
21
+ const config = require('../config');
22
+
23
+ const SHARED_MAILBOX_DISABLED_MESSAGE =
24
+ 'Shared-mailbox support is turned off. It is opt-in and work/school only: ' +
25
+ 'set OUTLOOK_SHARED_MAILBOX=read (read) or OUTLOOK_SHARED_MAILBOX=true ' +
26
+ '(read and organise) in the MCP server environment, restart the server, then ' +
27
+ 're-authenticate with `auth action=authenticate force=true` so the token ' +
28
+ 'carries the shared-mailbox scopes.';
29
+
30
+ /**
31
+ * Validate a mailbox and build its Graph resource prefix, WITHOUT checking
32
+ * whether shared-mailbox support is enabled. Only for paths that worked
33
+ * before the opt-in flag existed (access-shared-mailbox's direct read).
34
+ * @param {string|null} [mailbox] - Shared mailbox email address, or null/empty for the signed-in user
35
+ * @returns {string} - `me` or `users/{mailbox}`
36
+ * @throws {Error} If `mailbox` is non-empty but not a plausible email address
37
+ */
38
+ function validateMailboxPrefix(mailbox) {
39
+ const trimmed = typeof mailbox === 'string' ? mailbox.trim() : mailbox;
40
+ if (!trimmed) {
41
+ return 'me';
42
+ }
43
+ if (trimmed === 'me') {
44
+ return 'me';
45
+ }
46
+ if (!MAILBOX_PATTERN.test(trimmed)) {
47
+ throw new Error(
48
+ `Invalid mailbox "${mailbox}" — expected a shared mailbox email address (e.g. "team@contoso.com").`
49
+ );
50
+ }
51
+ // Return the address raw: encoding happens exactly once, in the Graph
52
+ // client (`callGraphAPI` / `callGraphAPIRaw` encode each path segment).
53
+ // Pre-encoding here double-encoded addresses like `team+archive@…` into
54
+ // `%252B`. The pattern above already confines the value to one segment.
55
+ return `users/${trimmed}`;
56
+ }
57
+
58
+ /**
59
+ * Build the Graph resource prefix for a mailbox. A non-`me` mailbox requires
60
+ * shared-mailbox support to be enabled (OUTLOOK_SHARED_MAILBOX).
61
+ * @param {string|null} [mailbox] - Shared mailbox email address, or null/empty for the signed-in user
62
+ * @returns {string} - `me` or `users/{mailbox}`
63
+ * @throws {Error} If `mailbox` is invalid, or shared-mailbox support is off
64
+ */
65
+ function buildMailboxPrefix(mailbox) {
66
+ const prefix = validateMailboxPrefix(mailbox);
67
+ if (prefix !== 'me' && config.SHARED_MAILBOX_MODE === 'off') {
68
+ throw new Error(SHARED_MAILBOX_DISABLED_MESSAGE);
69
+ }
70
+ return prefix;
71
+ }
72
+
73
+ module.exports = {
74
+ buildMailboxPrefix,
75
+ validateMailboxPrefix,
76
+ SHARED_MAILBOX_DISABLED_MESSAGE,
77
+ };