@memberjunction/communication-ms-graph 3.4.0 → 4.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.
@@ -1,63 +1,65 @@
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
1
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
2
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
3
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
23
6
  };
24
- var __importStar = (this && this.__importStar) || function (mod) {
25
- if (mod && mod.__esModule) return mod;
26
- var result = {};
27
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
- __setModuleDefault(result, mod);
29
- return result;
30
- };
31
7
  var __metadata = (this && this.__metadata) || function (k, v) {
32
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
33
9
  };
34
- Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.LoadMSGraphProvider = exports.MSGraphProvider = void 0;
36
- const communication_types_1 = require("@memberjunction/communication-types");
37
- const microsoft_graph_client_1 = require("@microsoft/microsoft-graph-client");
38
- const identity_1 = require("@azure/identity");
39
- const azureTokenCredentials_1 = require("@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials");
40
- const global_1 = require("@memberjunction/global");
41
- const core_1 = require("@memberjunction/core");
42
- const html_to_text_1 = require("html-to-text");
43
- const Auth = __importStar(require("./auth"));
44
- const Config = __importStar(require("./config"));
45
- let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCommunicationProvider {
10
+ import { BaseCommunicationProvider, resolveCredentialValue, validateRequiredCredentials } from "@memberjunction/communication-types";
11
+ import { Client } from '@microsoft/microsoft-graph-client';
12
+ import { ClientSecretCredential } from '@azure/identity';
13
+ import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials";
14
+ import { RegisterClass } from "@memberjunction/global";
15
+ import { LogError, LogStatus } from "@memberjunction/core";
16
+ import { compile } from 'html-to-text';
17
+ import * as Auth from "./auth.js";
18
+ import * as Config from "./config.js";
19
+ /**
20
+ * Implementation of the MS Graph provider for sending and receiving messages.
21
+ *
22
+ * @remarks
23
+ * Microsoft Graph provides full mailbox access. This provider supports:
24
+ * - Sending messages
25
+ * - Fetching messages from inbox
26
+ * - Forwarding messages
27
+ * - Replying to messages
28
+ * - Creating drafts
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Using environment credentials (default)
33
+ * await engine.SendSingleMessage('Microsoft Graph', 'Standard Email', message);
34
+ *
35
+ * // Using per-request credentials
36
+ * await engine.SendSingleMessage('Microsoft Graph', 'Standard Email', message, undefined, false, {
37
+ * tenantId: 'customer-tenant-id',
38
+ * clientId: 'customer-client-id',
39
+ * clientSecret: 'customer-client-secret',
40
+ * accountEmail: 'customer@domain.com'
41
+ * });
42
+ * ```
43
+ */
44
+ let MSGraphProvider = class MSGraphProvider extends BaseCommunicationProvider {
46
45
  constructor() {
47
46
  super();
48
- this.ServiceAccount = null;
47
+ // Cache clients by credential hash for performance with per-request credentials
49
48
  this.clientCache = new Map();
50
- this.HTMLConverter = (0, html_to_text_1.compile)({
49
+ this.HTMLConverter = compile({
51
50
  wordwrap: 130
52
51
  });
53
52
  }
53
+ /**
54
+ * Resolves MS Graph credentials from request and environment.
55
+ */
54
56
  resolveCredentials(credentials) {
55
57
  const disableFallback = credentials?.disableEnvironmentFallback ?? false;
56
- const tenantId = (0, communication_types_1.resolveCredentialValue)(credentials?.tenantId, Config.AZURE_TENANT_ID, disableFallback);
57
- const clientId = (0, communication_types_1.resolveCredentialValue)(credentials?.clientId, Config.AZURE_CLIENT_ID, disableFallback);
58
- const clientSecret = (0, communication_types_1.resolveCredentialValue)(credentials?.clientSecret, Config.AZURE_CLIENT_SECRET, disableFallback);
59
- const accountEmail = (0, communication_types_1.resolveCredentialValue)(credentials?.accountEmail, Config.AZURE_ACCOUNT_EMAIL, disableFallback);
60
- (0, communication_types_1.validateRequiredCredentials)({ tenantId, clientId, clientSecret, accountEmail }, ['tenantId', 'clientId', 'clientSecret', 'accountEmail'], 'Microsoft Graph');
58
+ const tenantId = resolveCredentialValue(credentials?.tenantId, Config.AZURE_TENANT_ID, disableFallback);
59
+ const clientId = resolveCredentialValue(credentials?.clientId, Config.AZURE_CLIENT_ID, disableFallback);
60
+ const clientSecret = resolveCredentialValue(credentials?.clientSecret, Config.AZURE_CLIENT_SECRET, disableFallback);
61
+ const accountEmail = resolveCredentialValue(credentials?.accountEmail, Config.AZURE_ACCOUNT_EMAIL, disableFallback);
62
+ validateRequiredCredentials({ tenantId, clientId, clientSecret, accountEmail }, ['tenantId', 'clientId', 'clientSecret', 'accountEmail'], 'Microsoft Graph');
61
63
  return {
62
64
  tenantId: tenantId,
63
65
  clientId: clientId,
@@ -65,46 +67,55 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
65
67
  accountEmail: accountEmail
66
68
  };
67
69
  }
70
+ /**
71
+ * Gets or creates a Graph client for the given credentials.
72
+ * Uses cached client if credentials match environment (default case).
73
+ */
68
74
  getGraphClient(creds) {
75
+ // Check if using environment credentials (can use shared client)
69
76
  const isEnvCredentials = creds.tenantId === Config.AZURE_TENANT_ID &&
70
77
  creds.clientId === Config.AZURE_CLIENT_ID &&
71
78
  creds.clientSecret === Config.AZURE_CLIENT_SECRET;
72
79
  if (isEnvCredentials) {
80
+ // Use the shared Auth.GraphClient for environment credentials
73
81
  return Auth.GraphClient;
74
82
  }
83
+ // For per-request credentials, use cached client by credential key
75
84
  const cacheKey = `${creds.tenantId}:${creds.clientId}`;
76
85
  let client = this.clientCache.get(cacheKey);
77
86
  if (!client) {
78
- const credential = new identity_1.ClientSecretCredential(creds.tenantId, creds.clientId, creds.clientSecret);
79
- const authProvider = new azureTokenCredentials_1.TokenCredentialAuthenticationProvider(credential, {
87
+ const credential = new ClientSecretCredential(creds.tenantId, creds.clientId, creds.clientSecret);
88
+ const authProvider = new TokenCredentialAuthenticationProvider(credential, {
80
89
  scopes: ['https://graph.microsoft.com/.default'],
81
90
  });
82
- client = microsoft_graph_client_1.Client.initWithMiddleware({ authProvider });
91
+ client = Client.initWithMiddleware({ authProvider });
83
92
  this.clientCache.set(cacheKey, client);
84
93
  }
85
94
  return client;
86
95
  }
96
+ /**
97
+ * Gets the API URI for Graph API calls.
98
+ */
87
99
  getApiUri() {
88
100
  return Auth.ApiConfig.uri;
89
101
  }
102
+ /**
103
+ * Sends a single email message via MS Graph.
104
+ *
105
+ * @requires MS Graph Scope: Mail.Send (Application)
106
+ */
90
107
  async SendSingleMessage(message, credentials) {
91
108
  try {
109
+ // Resolve credentials
92
110
  const creds = this.resolveCredentials(credentials);
93
111
  const client = this.getGraphClient(creds);
112
+ // Smart selection: use message.From if provided and different from resolved accountEmail
94
113
  let senderEmail = creds.accountEmail;
95
114
  if (message.From &&
96
115
  message.From.trim() !== '' &&
97
116
  message.From !== creds.accountEmail) {
98
117
  senderEmail = message.From;
99
118
  }
100
- const user = await this.GetServiceAccountWithClient(client, senderEmail);
101
- if (!user) {
102
- return {
103
- Message: message,
104
- Success: false,
105
- Error: 'Service account not found'
106
- };
107
- }
108
119
  if (!message) {
109
120
  return {
110
121
  Message: message,
@@ -140,12 +151,14 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
140
151
  saveToSentItems: message.ContextData?.saveToSentItems ?? false
141
152
  };
142
153
  if (message.Headers) {
154
+ // Convert Headers (Record<string, string>) to internetMessageHeaders (Array[{key:value}])
143
155
  sendMail.message.internetMessageHeaders = Object.entries(message.Headers).map(([key, value]) => ({
144
156
  name: key.startsWith('X-') ? key : `X-${key}`,
145
157
  value: value
146
158
  }));
147
159
  }
148
- const sendMessagePath = `${this.getApiUri()}/${user.id}/sendMail`;
160
+ // Use email address directly in API path instead of looking up user ID
161
+ const sendMessagePath = `${this.getApiUri()}/${encodeURIComponent(senderEmail)}/sendMail`;
149
162
  await client.api(sendMessagePath).post(sendMail);
150
163
  return {
151
164
  Message: message,
@@ -154,7 +167,7 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
154
167
  };
155
168
  }
156
169
  catch (ex) {
157
- (0, core_1.LogError)(ex);
170
+ LogError(ex);
158
171
  return {
159
172
  Message: message,
160
173
  Success: false,
@@ -162,17 +175,15 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
162
175
  };
163
176
  }
164
177
  }
178
+ /**
179
+ * Replies to an email message via MS Graph.
180
+ *
181
+ * @requires MS Graph Scope: Mail.Send (Application)
182
+ */
165
183
  async ReplyToMessage(params, credentials) {
166
184
  try {
167
185
  const creds = this.resolveCredentials(credentials);
168
186
  const client = this.getGraphClient(creds);
169
- const user = await this.GetServiceAccountWithClient(client, creds.accountEmail);
170
- if (!user) {
171
- return {
172
- Success: false,
173
- ErrorMessage: 'Service account not found'
174
- };
175
- }
176
187
  const reply = {
177
188
  message: {
178
189
  toRecipients: [
@@ -195,7 +206,8 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
195
206
  },
196
207
  comment: params.Message.ProcessedBody || params.Message.ProcessedHTMLBody
197
208
  };
198
- const sendMessagePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/reply`;
209
+ // Use email address directly in API path
210
+ const sendMessagePath = `${this.getApiUri()}/${encodeURIComponent(creds.accountEmail)}/messages/${params.MessageID}/reply`;
199
211
  const result = await client.api(sendMessagePath).post(reply);
200
212
  return {
201
213
  Success: true,
@@ -203,25 +215,23 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
203
215
  };
204
216
  }
205
217
  catch (ex) {
206
- (0, core_1.LogError)(ex);
218
+ LogError(ex);
207
219
  return {
208
220
  Success: false,
209
221
  ErrorMessage: 'Error sending message'
210
222
  };
211
223
  }
212
224
  }
225
+ /**
226
+ * Retrieves email messages from a mailbox via MS Graph.
227
+ *
228
+ * @requires MS Graph Scope: Mail.Read (Application), or Mail.ReadWrite if using ContextData.MarkAsRead option
229
+ */
213
230
  async GetMessages(params, credentials) {
214
231
  const creds = this.resolveCredentials(credentials);
215
232
  const client = this.getGraphClient(creds);
216
233
  const contextData = params.ContextData;
217
234
  const emailToUse = params.Identifier || contextData?.Email || creds.accountEmail;
218
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
219
- if (!user || !user.id) {
220
- return {
221
- Success: false,
222
- Messages: []
223
- };
224
- }
225
235
  let filter = "";
226
236
  const top = params.NumMessages;
227
237
  if (params.UnreadOnly) {
@@ -230,7 +240,8 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
230
240
  if (contextData && contextData.Filter) {
231
241
  filter = contextData.Filter;
232
242
  }
233
- const messagesPath = `${this.getApiUri()}/${user.id}/messages`;
243
+ // Use email address directly in API path
244
+ const messagesPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages`;
234
245
  const response = await client.api(messagesPath)
235
246
  .filter(filter).top(top).get();
236
247
  if (!response) {
@@ -246,14 +257,19 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
246
257
  Messages: []
247
258
  };
248
259
  let headers = null;
260
+ // GetHeaders is an async function for one specific message. I need
261
+ // to resolve all of them into a structure, indexed by sourceMessage.id
262
+ // and then apply that in the mapped message below.
249
263
  if (params.IncludeHeaders) {
250
- const headersPromises = sourceMessages.map((message) => this.GetHeadersWithClient(client, params, user, message.id));
264
+ const headersPromises = sourceMessages.map((message) => this.GetHeadersWithEmail(client, emailToUse, params, message.id));
251
265
  headers = await Promise.all(headersPromises);
252
266
  }
253
267
  const messages = sourceMessages.map((message, index) => {
254
268
  const msgTyped = message;
255
269
  const replyTo = msgTyped.replyTo?.map((replyTo) => replyTo.emailAddress?.address || '') || [];
256
270
  const primaryToRecipient = replyTo.length > 0 ? replyTo[0] : '';
271
+ // the blow hokey thing with ReturnAsPlainTex without the t is to have
272
+ // back-compat with the old code when this typo existed
257
273
  return {
258
274
  From: msgTyped.from?.emailAddress?.address || '',
259
275
  To: primaryToRecipient,
@@ -272,11 +288,16 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
272
288
  messageResults.Messages = messages;
273
289
  if (contextData && contextData.MarkAsRead) {
274
290
  for (const message of messages) {
275
- this.MarkMessageAsReadWithClient(client, user.id, message.ExternalSystemRecordID);
291
+ this.MarkMessageAsReadWithEmail(client, emailToUse, message.ExternalSystemRecordID);
276
292
  }
277
293
  }
278
294
  return messageResults;
279
295
  }
296
+ /**
297
+ * Forwards an email message via MS Graph.
298
+ *
299
+ * @requires MS Graph Scope: Mail.Send (Application)
300
+ */
280
301
  async ForwardMessage(params, credentials) {
281
302
  try {
282
303
  if (!params.MessageID) {
@@ -287,13 +308,6 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
287
308
  }
288
309
  const creds = this.resolveCredentials(credentials);
289
310
  const client = this.getGraphClient(creds);
290
- const user = await this.GetServiceAccountWithClient(client, creds.accountEmail);
291
- if (!user) {
292
- return {
293
- Success: false,
294
- ErrorMessage: 'Service account not found'
295
- };
296
- }
297
311
  const forward = {
298
312
  comment: params.Message,
299
313
  toRecipients: params.ToRecipients.map((recipient) => ({
@@ -312,7 +326,8 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
312
326
  }
313
327
  }))
314
328
  };
315
- const sendMessagePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/forward`;
329
+ // Use email address directly in API path
330
+ const sendMessagePath = `${this.getApiUri()}/${encodeURIComponent(creds.accountEmail)}/messages/${params.MessageID}/forward`;
316
331
  const forwardResult = await client.api(sendMessagePath).post(forward);
317
332
  return {
318
333
  Success: true,
@@ -320,16 +335,23 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
320
335
  };
321
336
  }
322
337
  catch (ex) {
323
- (0, core_1.LogError)(ex);
338
+ LogError(ex);
324
339
  return {
325
340
  ErrorMessage: 'An Error occurred while forwarding the message',
326
341
  Success: false
327
342
  };
328
343
  }
329
344
  }
330
- async GetHeadersWithClient(client, params, user, messageID) {
345
+ /**
346
+ * Gets headers for a specific message using email address directly.
347
+ * This is the preferred method for new code as it avoids an extra API call to look up the user.
348
+ *
349
+ * @protected
350
+ * @requires MS Graph Scope: Mail.Read (Application)
351
+ */
352
+ async GetHeadersWithEmail(client, emailAddress, params, messageID) {
331
353
  if (params.IncludeHeaders && messageID) {
332
- const messageHeaderPath = `${this.getApiUri()}/${user.id}/messages/${messageID}?$select=internetMessageHeaders`;
354
+ const messageHeaderPath = `${this.getApiUri()}/${encodeURIComponent(emailAddress)}/messages/${messageID}?$select=internetMessageHeaders`;
333
355
  const messageHeaderResponse = await client.api(messageHeaderPath).get();
334
356
  return messageHeaderResponse.internetMessageHeaders?.map((header) => ({
335
357
  [header.name]: header.value
@@ -337,69 +359,144 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
337
359
  }
338
360
  return {};
339
361
  }
340
- async GetHeaders(params, user, messageID) {
341
- return this.GetHeadersWithClient(Auth.GraphClient, params, user, messageID);
362
+ /**
363
+ * Marks a message as read using email address directly.
364
+ * This is the preferred method for new code as it avoids an extra API call to look up the user.
365
+ *
366
+ * @protected
367
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
368
+ */
369
+ async MarkMessageAsReadWithEmail(client, emailAddress, messageID) {
370
+ try {
371
+ const updatePath = `${this.getApiUri()}/${encodeURIComponent(emailAddress)}/messages/${messageID}`;
372
+ const updatedMessage = {
373
+ isRead: true
374
+ };
375
+ await client.api(updatePath).update(updatedMessage);
376
+ LogStatus(`Message ${messageID} marked as read`);
377
+ return true;
378
+ }
379
+ catch (ex) {
380
+ LogError(ex);
381
+ return false;
382
+ }
342
383
  }
384
+ /**
385
+ * Gets the user account information by making an API call to MS Graph.
386
+ * This method looks up the full User object from the Graph API.
387
+ *
388
+ * @protected
389
+ * @requires MS Graph Scope: User.Read.All (Application) - Required to look up user information
390
+ */
343
391
  async GetServiceAccountWithClient(client, email) {
344
- const endpoint = `${this.getApiUri()}/${email}`;
345
- const user = await client.api(endpoint).get();
346
- if (!user) {
347
- (0, core_1.LogError)('Error: could not get user info');
348
- return null;
392
+ try {
393
+ const endpoint = `${this.getApiUri()}/${encodeURIComponent(email)}`;
394
+ const user = await client.api(endpoint).get();
395
+ if (!user) {
396
+ LogError('Error: could not get user info');
397
+ return null;
398
+ }
399
+ const userID = user.id;
400
+ if (!userID) {
401
+ LogError('Error: userID not set for user');
402
+ return null;
403
+ }
404
+ return user;
349
405
  }
350
- const userID = user.id;
351
- if (!userID) {
352
- (0, core_1.LogError)('Error: userID not set for user');
406
+ catch (ex) {
407
+ LogError('Error getting service account', undefined, ex);
353
408
  return null;
354
409
  }
355
- return user;
356
410
  }
411
+ /**
412
+ * Gets the service account using default client.
413
+ * Caches the result for subsequent calls.
414
+ *
415
+ * @protected
416
+ * @requires MS Graph Scope: User.Read.All (Application) - Required to look up user information
417
+ */
357
418
  async GetServiceAccount(email) {
358
- if (this.ServiceAccount) {
359
- return this.ServiceAccount;
360
- }
361
419
  const accountEmail = email || Config.AZURE_ACCOUNT_EMAIL;
362
- const user = await this.GetServiceAccountWithClient(Auth.GraphClient, accountEmail);
363
- if (user) {
364
- this.ServiceAccount = user;
420
+ return this.GetServiceAccountWithClient(Auth.GraphClient, accountEmail);
421
+ }
422
+ /**
423
+ * Gets headers for a message using User object (requires prior user lookup).
424
+ * For better performance, consider using GetHeadersWithEmail() instead.
425
+ *
426
+ * @protected
427
+ * @requires MS Graph Scope: Mail.Read (Application)
428
+ */
429
+ async GetHeadersWithClient(client, params, user, messageID) {
430
+ const userId = user.id || user.userPrincipalName;
431
+ if (!userId) {
432
+ return {};
433
+ }
434
+ if (params.IncludeHeaders && messageID) {
435
+ const messageHeaderPath = `${this.getApiUri()}/${encodeURIComponent(userId)}/messages/${messageID}?$select=internetMessageHeaders`;
436
+ const messageHeaderResponse = await client.api(messageHeaderPath).get();
437
+ return messageHeaderResponse.internetMessageHeaders?.map((header) => ({
438
+ [header.name]: header.value
439
+ })) || {};
365
440
  }
366
- return user;
441
+ return {};
442
+ }
443
+ /**
444
+ * Gets headers using default client.
445
+ *
446
+ * @protected
447
+ * @requires MS Graph Scope: Mail.Read (Application)
448
+ */
449
+ async GetHeaders(params, user, messageID) {
450
+ return this.GetHeadersWithClient(Auth.GraphClient, params, user, messageID);
367
451
  }
452
+ /**
453
+ * Marks a message as read using User ID.
454
+ * For better performance, consider using MarkMessageAsReadWithEmail() instead.
455
+ *
456
+ * @protected
457
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
458
+ */
368
459
  async MarkMessageAsReadWithClient(client, userID, messageID) {
369
460
  try {
370
- const updatePath = `${this.getApiUri()}/${userID}/messages/${messageID}`;
461
+ const updatePath = `${this.getApiUri()}/${encodeURIComponent(userID)}/messages/${messageID}`;
371
462
  const updatedMessage = {
372
463
  isRead: true
373
464
  };
374
465
  await client.api(updatePath).update(updatedMessage);
375
- (0, core_1.LogStatus)(`Message ${messageID} marked as read`);
466
+ LogStatus(`Message ${messageID} marked as read`);
376
467
  return true;
377
468
  }
378
469
  catch (ex) {
379
- (0, core_1.LogError)(ex);
470
+ LogError(ex);
380
471
  return false;
381
472
  }
382
473
  }
474
+ /**
475
+ * Marks a message as read using default client.
476
+ *
477
+ * @protected
478
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
479
+ */
383
480
  async MarkMessageAsRead(userID, messageID) {
384
481
  return this.MarkMessageAsReadWithClient(Auth.GraphClient, userID, messageID);
385
482
  }
483
+ /**
484
+ * Creates a draft email message via MS Graph.
485
+ *
486
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
487
+ */
386
488
  async CreateDraft(params, credentials) {
387
489
  try {
388
490
  const creds = this.resolveCredentials(credentials);
389
491
  const client = this.getGraphClient(creds);
492
+ // Smart selection: use message.From if provided and different from resolved accountEmail
390
493
  let senderEmail = creds.accountEmail;
391
494
  if (params.Message.From &&
392
495
  params.Message.From.trim() !== '' &&
393
496
  params.Message.From !== creds.accountEmail) {
394
497
  senderEmail = params.Message.From;
395
498
  }
396
- const user = await this.GetServiceAccountWithClient(client, senderEmail);
397
- if (!user) {
398
- return {
399
- Success: false,
400
- ErrorMessage: 'Service account not found'
401
- };
402
- }
499
+ // Build message object (similar to SendSingleMessage but saved as draft)
403
500
  const draftMessage = {
404
501
  subject: params.Message.ProcessedSubject,
405
502
  body: {
@@ -417,15 +514,17 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
417
514
  }))
418
515
  };
419
516
  if (params.Message.Headers) {
517
+ // Convert Headers (Record<string, string>) to internetMessageHeaders (Array[{key:value}])
420
518
  draftMessage.internetMessageHeaders = Object.entries(params.Message.Headers)
421
519
  .map(([key, value]) => ({
422
520
  name: key.startsWith('X-') ? key : `X-${key}`,
423
521
  value: value
424
522
  }));
425
523
  }
426
- const createDraftPath = `${this.getApiUri()}/${user.id}/messages`;
524
+ // Create draft by POSTing to messages endpoint (not sendMail) - use email address directly
525
+ const createDraftPath = `${this.getApiUri()}/${encodeURIComponent(senderEmail)}/messages`;
427
526
  const result = await client.api(createDraftPath).post(draftMessage);
428
- (0, core_1.LogStatus)(`Draft created via MS Graph: ${result.id}`);
527
+ LogStatus(`Draft created via MS Graph: ${result.id}`);
429
528
  return {
430
529
  Success: true,
431
530
  DraftID: result.id,
@@ -433,13 +532,20 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
433
532
  };
434
533
  }
435
534
  catch (ex) {
436
- (0, core_1.LogError)('Error creating draft via MS Graph', undefined, ex);
535
+ LogError('Error creating draft via MS Graph', undefined, ex);
437
536
  return {
438
537
  Success: false,
439
538
  ErrorMessage: 'Error creating draft'
440
539
  };
441
540
  }
442
541
  }
542
+ // ========================================================================
543
+ // EXTENDED OPERATIONS - MS Graph supports full mailbox access
544
+ // ========================================================================
545
+ /**
546
+ * Returns the list of operations supported by MS Graph provider.
547
+ * MS Graph supports all mailbox operations.
548
+ */
443
549
  getSupportedOperations() {
444
550
  return [
445
551
  'SendSingleMessage',
@@ -458,19 +564,18 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
458
564
  'DownloadAttachment'
459
565
  ];
460
566
  }
567
+ /**
568
+ * Gets a single message by ID from MS Graph.
569
+ *
570
+ * @requires MS Graph Scope: Mail.Read (Application)
571
+ */
461
572
  async GetSingleMessage(params, credentials) {
462
573
  try {
463
574
  const creds = this.resolveCredentials(credentials);
464
575
  const client = this.getGraphClient(creds);
465
576
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
466
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
467
- if (!user || !user.id) {
468
- return {
469
- Success: false,
470
- ErrorMessage: 'Service account not found'
471
- };
472
- }
473
- const messagePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}`;
577
+ // Use email address directly in API path
578
+ const messagePath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}`;
474
579
  const msgResponse = await client.api(messagePath).get();
475
580
  if (!msgResponse) {
476
581
  return {
@@ -499,68 +604,70 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
499
604
  };
500
605
  }
501
606
  catch (ex) {
502
- (0, core_1.LogError)('Error getting single message via MS Graph', undefined, ex);
607
+ LogError('Error getting single message via MS Graph', undefined, ex);
503
608
  return {
504
609
  Success: false,
505
610
  ErrorMessage: `Error getting message: ${ex instanceof Error ? ex.message : String(ex)}`
506
611
  };
507
612
  }
508
613
  }
614
+ /**
615
+ * Deletes a message using MS Graph.
616
+ * If PermanentDelete is false, moves to Deleted Items folder.
617
+ *
618
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
619
+ */
509
620
  async DeleteMessage(params, credentials) {
510
621
  try {
511
622
  const creds = this.resolveCredentials(credentials);
512
623
  const client = this.getGraphClient(creds);
513
624
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
514
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
515
- if (!user || !user.id) {
516
- return {
517
- Success: false,
518
- ErrorMessage: 'Service account not found'
519
- };
520
- }
521
- const messagePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}`;
625
+ // Use email address directly in API path
626
+ const messagePath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}`;
522
627
  if (params.PermanentDelete) {
628
+ // Permanently delete the message
523
629
  await client.api(messagePath).delete();
524
630
  }
525
631
  else {
526
- const deletedItemsFolder = await this.findSystemFolder(client, user.id, 'deleteditems');
632
+ // Move to Deleted Items (soft delete)
633
+ const deletedItemsFolder = await this.findSystemFolder(client, emailToUse, 'deleteditems');
527
634
  if (deletedItemsFolder) {
528
635
  await client.api(`${messagePath}/move`).post({
529
636
  destinationId: deletedItemsFolder
530
637
  });
531
638
  }
532
639
  else {
640
+ // Fall back to permanent delete if we can't find Deleted Items
533
641
  await client.api(messagePath).delete();
534
642
  }
535
643
  }
536
- (0, core_1.LogStatus)(`Message ${params.MessageID} deleted via MS Graph`);
644
+ LogStatus(`Message ${params.MessageID} deleted via MS Graph`);
537
645
  return { Success: true };
538
646
  }
539
647
  catch (ex) {
540
- (0, core_1.LogError)('Error deleting message via MS Graph', undefined, ex);
648
+ LogError('Error deleting message via MS Graph', undefined, ex);
541
649
  return {
542
650
  Success: false,
543
651
  ErrorMessage: `Error deleting message: ${ex instanceof Error ? ex.message : String(ex)}`
544
652
  };
545
653
  }
546
654
  }
655
+ /**
656
+ * Moves a message to a different folder using MS Graph.
657
+ *
658
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
659
+ */
547
660
  async MoveMessage(params, credentials) {
548
661
  try {
549
662
  const creds = this.resolveCredentials(credentials);
550
663
  const client = this.getGraphClient(creds);
551
664
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
552
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
553
- if (!user || !user.id) {
554
- return {
555
- Success: false,
556
- ErrorMessage: 'Service account not found'
557
- };
558
- }
559
- const movePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/move`;
665
+ // Use email address directly in API path
666
+ const movePath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}/move`;
560
667
  const result = await client.api(movePath).post({
561
668
  destinationId: params.DestinationFolderID
562
669
  });
563
- (0, core_1.LogStatus)(`Message ${params.MessageID} moved to folder ${params.DestinationFolderID}`);
670
+ LogStatus(`Message ${params.MessageID} moved to folder ${params.DestinationFolderID}`);
564
671
  return {
565
672
  Success: true,
566
673
  NewMessageID: result?.id,
@@ -568,31 +675,30 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
568
675
  };
569
676
  }
570
677
  catch (ex) {
571
- (0, core_1.LogError)('Error moving message via MS Graph', undefined, ex);
678
+ LogError('Error moving message via MS Graph', undefined, ex);
572
679
  return {
573
680
  Success: false,
574
681
  ErrorMessage: `Error moving message: ${ex instanceof Error ? ex.message : String(ex)}`
575
682
  };
576
683
  }
577
684
  }
685
+ /**
686
+ * Lists mail folders using MS Graph.
687
+ *
688
+ * @requires MS Graph Scope: Mail.Read (Application)
689
+ */
578
690
  async ListFolders(params, credentials) {
579
691
  try {
580
692
  const creds = this.resolveCredentials(credentials);
581
693
  const client = this.getGraphClient(creds);
582
694
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
583
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
584
- if (!user || !user.id) {
585
- return {
586
- Success: false,
587
- ErrorMessage: 'Service account not found'
588
- };
589
- }
695
+ // Use email address directly in API path
590
696
  let foldersPath;
591
697
  if (params.ParentFolderID) {
592
- foldersPath = `${this.getApiUri()}/${user.id}/mailFolders/${params.ParentFolderID}/childFolders`;
698
+ foldersPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/mailFolders/${params.ParentFolderID}/childFolders`;
593
699
  }
594
700
  else {
595
- foldersPath = `${this.getApiUri()}/${user.id}/mailFolders`;
701
+ foldersPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/mailFolders`;
596
702
  }
597
703
  const response = await client.api(foldersPath).get();
598
704
  if (!response?.value) {
@@ -617,56 +723,55 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
617
723
  };
618
724
  }
619
725
  catch (ex) {
620
- (0, core_1.LogError)('Error listing folders via MS Graph', undefined, ex);
726
+ LogError('Error listing folders via MS Graph', undefined, ex);
621
727
  return {
622
728
  Success: false,
623
729
  ErrorMessage: `Error listing folders: ${ex instanceof Error ? ex.message : String(ex)}`
624
730
  };
625
731
  }
626
732
  }
733
+ /**
734
+ * Marks messages as read or unread using MS Graph.
735
+ *
736
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
737
+ */
627
738
  async MarkAsRead(params, credentials) {
628
739
  try {
629
740
  const creds = this.resolveCredentials(credentials);
630
741
  const client = this.getGraphClient(creds);
631
742
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
632
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
633
- if (!user || !user.id) {
634
- return {
635
- Success: false,
636
- ErrorMessage: 'Service account not found'
637
- };
638
- }
743
+ // Use email address directly in API path - update each message
639
744
  const updatePromises = params.MessageIDs.map(async (messageId) => {
640
- const updatePath = `${this.getApiUri()}/${user.id}/messages/${messageId}`;
745
+ const updatePath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${messageId}`;
641
746
  return client.api(updatePath).update({ isRead: params.IsRead });
642
747
  });
643
748
  await Promise.all(updatePromises);
644
- (0, core_1.LogStatus)(`Marked ${params.MessageIDs.length} message(s) as ${params.IsRead ? 'read' : 'unread'}`);
749
+ LogStatus(`Marked ${params.MessageIDs.length} message(s) as ${params.IsRead ? 'read' : 'unread'}`);
645
750
  return { Success: true };
646
751
  }
647
752
  catch (ex) {
648
- (0, core_1.LogError)('Error marking messages as read via MS Graph', undefined, ex);
753
+ LogError('Error marking messages as read via MS Graph', undefined, ex);
649
754
  return {
650
755
  Success: false,
651
756
  ErrorMessage: `Error marking messages: ${ex instanceof Error ? ex.message : String(ex)}`
652
757
  };
653
758
  }
654
759
  }
760
+ /**
761
+ * Archives a message by moving it to the Archive folder using MS Graph.
762
+ *
763
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
764
+ */
655
765
  async ArchiveMessage(params, credentials) {
656
766
  try {
657
767
  const creds = this.resolveCredentials(credentials);
658
768
  const client = this.getGraphClient(creds);
659
769
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
660
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
661
- if (!user || !user.id) {
662
- return {
663
- Success: false,
664
- ErrorMessage: 'Service account not found'
665
- };
666
- }
667
- let archiveFolderId = await this.findSystemFolder(client, user.id, 'archive');
770
+ // Find or create the Archive folder - use email address directly
771
+ let archiveFolderId = await this.findSystemFolder(client, emailToUse, 'archive');
668
772
  if (!archiveFolderId) {
669
- archiveFolderId = await this.createMailFolder(client, user.id, 'Archive');
773
+ // Try to create an Archive folder
774
+ archiveFolderId = await this.createMailFolder(client, emailToUse, 'Archive');
670
775
  }
671
776
  if (!archiveFolderId) {
672
777
  return {
@@ -674,41 +779,43 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
674
779
  ErrorMessage: 'Could not find or create Archive folder'
675
780
  };
676
781
  }
677
- const movePath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/move`;
782
+ // Move the message to Archive - use email address directly in API path
783
+ const movePath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}/move`;
678
784
  await client.api(movePath).post({
679
785
  destinationId: archiveFolderId
680
786
  });
681
- (0, core_1.LogStatus)(`Message ${params.MessageID} archived`);
787
+ LogStatus(`Message ${params.MessageID} archived`);
682
788
  return { Success: true };
683
789
  }
684
790
  catch (ex) {
685
- (0, core_1.LogError)('Error archiving message via MS Graph', undefined, ex);
791
+ LogError('Error archiving message via MS Graph', undefined, ex);
686
792
  return {
687
793
  Success: false,
688
794
  ErrorMessage: `Error archiving message: ${ex instanceof Error ? ex.message : String(ex)}`
689
795
  };
690
796
  }
691
797
  }
798
+ /**
799
+ * Searches messages using MS Graph search or filter.
800
+ *
801
+ * @requires MS Graph Scope: Mail.Read (Application)
802
+ */
692
803
  async SearchMessages(params, credentials) {
693
804
  try {
694
805
  const creds = this.resolveCredentials(credentials);
695
806
  const client = this.getGraphClient(creds);
696
807
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
697
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
698
- if (!user || !user.id) {
699
- return {
700
- Success: false,
701
- ErrorMessage: 'Service account not found'
702
- };
703
- }
808
+ // Build search path - use email address directly in API path
704
809
  let messagesPath;
705
810
  if (params.FolderID) {
706
- messagesPath = `${this.getApiUri()}/${user.id}/mailFolders/${params.FolderID}/messages`;
811
+ messagesPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/mailFolders/${params.FolderID}/messages`;
707
812
  }
708
813
  else {
709
- messagesPath = `${this.getApiUri()}/${user.id}/messages`;
814
+ messagesPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages`;
710
815
  }
816
+ // Build filter conditions
711
817
  const filters = [];
818
+ // Date range filters
712
819
  if (params.FromDate) {
713
820
  filters.push(`receivedDateTime ge ${params.FromDate.toISOString()}`);
714
821
  }
@@ -716,6 +823,7 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
716
823
  filters.push(`receivedDateTime le ${params.ToDate.toISOString()}`);
717
824
  }
718
825
  let apiRequest = client.api(messagesPath);
826
+ // Use $search for text queries (MS Graph supports KQL)
719
827
  if (params.Query) {
720
828
  apiRequest = apiRequest.search(`"${params.Query}"`);
721
829
  }
@@ -750,26 +858,25 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
750
858
  };
751
859
  }
752
860
  catch (ex) {
753
- (0, core_1.LogError)('Error searching messages via MS Graph', undefined, ex);
861
+ LogError('Error searching messages via MS Graph', undefined, ex);
754
862
  return {
755
863
  Success: false,
756
864
  ErrorMessage: `Error searching messages: ${ex instanceof Error ? ex.message : String(ex)}`
757
865
  };
758
866
  }
759
867
  }
868
+ /**
869
+ * Lists attachments on a message using MS Graph.
870
+ *
871
+ * @requires MS Graph Scope: Mail.Read (Application)
872
+ */
760
873
  async ListAttachments(params, credentials) {
761
874
  try {
762
875
  const creds = this.resolveCredentials(credentials);
763
876
  const client = this.getGraphClient(creds);
764
877
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
765
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
766
- if (!user || !user.id) {
767
- return {
768
- Success: false,
769
- ErrorMessage: 'Service account not found'
770
- };
771
- }
772
- const attachmentsPath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/attachments`;
878
+ // Use email address directly in API path
879
+ const attachmentsPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}/attachments`;
773
880
  const response = await client.api(attachmentsPath).get();
774
881
  if (!response?.value) {
775
882
  return {
@@ -792,26 +899,25 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
792
899
  };
793
900
  }
794
901
  catch (ex) {
795
- (0, core_1.LogError)('Error listing attachments via MS Graph', undefined, ex);
902
+ LogError('Error listing attachments via MS Graph', undefined, ex);
796
903
  return {
797
904
  Success: false,
798
905
  ErrorMessage: `Error listing attachments: ${ex instanceof Error ? ex.message : String(ex)}`
799
906
  };
800
907
  }
801
908
  }
909
+ /**
910
+ * Downloads an attachment from a message using MS Graph.
911
+ *
912
+ * @requires MS Graph Scope: Mail.Read (Application)
913
+ */
802
914
  async DownloadAttachment(params, credentials) {
803
915
  try {
804
916
  const creds = this.resolveCredentials(credentials);
805
917
  const client = this.getGraphClient(creds);
806
918
  const emailToUse = params.ContextData?.Email || creds.accountEmail;
807
- const user = await this.GetServiceAccountWithClient(client, emailToUse);
808
- if (!user || !user.id) {
809
- return {
810
- Success: false,
811
- ErrorMessage: 'Service account not found'
812
- };
813
- }
814
- const attachmentPath = `${this.getApiUri()}/${user.id}/messages/${params.MessageID}/attachments/${params.AttachmentID}`;
919
+ // Use email address directly in API path
920
+ const attachmentPath = `${this.getApiUri()}/${encodeURIComponent(emailToUse)}/messages/${params.MessageID}/attachments/${params.AttachmentID}`;
815
921
  const response = await client.api(attachmentPath).get();
816
922
  if (!response) {
817
923
  return {
@@ -819,6 +925,7 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
819
925
  ErrorMessage: 'Attachment not found'
820
926
  };
821
927
  }
928
+ // MS Graph returns file attachments with contentBytes as base64
822
929
  const contentBase64 = response.contentBytes;
823
930
  return {
824
931
  Success: true,
@@ -830,15 +937,25 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
830
937
  };
831
938
  }
832
939
  catch (ex) {
833
- (0, core_1.LogError)('Error downloading attachment via MS Graph', undefined, ex);
940
+ LogError('Error downloading attachment via MS Graph', undefined, ex);
834
941
  return {
835
942
  Success: false,
836
943
  ErrorMessage: `Error downloading attachment: ${ex instanceof Error ? ex.message : String(ex)}`
837
944
  };
838
945
  }
839
946
  }
840
- async findSystemFolder(client, userId, folderName) {
947
+ // ========================================================================
948
+ // HELPER METHODS
949
+ // ========================================================================
950
+ /**
951
+ * Finds a system folder by well-known name.
952
+ *
953
+ * @private
954
+ * @requires MS Graph Scope: Mail.Read (Application)
955
+ */
956
+ async findSystemFolder(client, emailAddress, folderName) {
841
957
  try {
958
+ // MS Graph well-known folder names
842
959
  const wellKnownNames = {
843
960
  'inbox': 'inbox',
844
961
  'sent': 'sentitems',
@@ -851,13 +968,15 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
851
968
  };
852
969
  const normalizedName = folderName.toLowerCase();
853
970
  const graphFolderName = wellKnownNames[normalizedName] || normalizedName;
854
- const folderPath = `${this.getApiUri()}/${userId}/mailFolders/${graphFolderName}`;
971
+ // Try well-known folder endpoint first - use email address directly
972
+ const folderPath = `${this.getApiUri()}/${encodeURIComponent(emailAddress)}/mailFolders/${graphFolderName}`;
855
973
  const folder = await client.api(folderPath).get();
856
974
  return folder?.id || null;
857
975
  }
858
976
  catch {
977
+ // Folder not found or access denied - try search
859
978
  try {
860
- const foldersPath = `${this.getApiUri()}/${userId}/mailFolders`;
979
+ const foldersPath = `${this.getApiUri()}/${encodeURIComponent(emailAddress)}/mailFolders`;
861
980
  const response = await client.api(foldersPath)
862
981
  .filter(`displayName eq '${folderName}'`)
863
982
  .get();
@@ -866,24 +985,35 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
866
985
  }
867
986
  }
868
987
  catch {
988
+ // Ignore search errors
869
989
  }
870
990
  return null;
871
991
  }
872
992
  }
873
- async createMailFolder(client, userId, folderName) {
993
+ /**
994
+ * Creates a new mail folder.
995
+ *
996
+ * @private
997
+ * @requires MS Graph Scope: Mail.ReadWrite (Application)
998
+ */
999
+ async createMailFolder(client, emailAddress, folderName) {
874
1000
  try {
875
- const foldersPath = `${this.getApiUri()}/${userId}/mailFolders`;
1001
+ // Use email address directly in API path
1002
+ const foldersPath = `${this.getApiUri()}/${encodeURIComponent(emailAddress)}/mailFolders`;
876
1003
  const result = await client.api(foldersPath).post({
877
1004
  displayName: folderName
878
1005
  });
879
- (0, core_1.LogStatus)(`Created mail folder '${folderName}' with ID: ${result.id}`);
1006
+ LogStatus(`Created mail folder '${folderName}' with ID: ${result.id}`);
880
1007
  return result.id;
881
1008
  }
882
1009
  catch (ex) {
883
- (0, core_1.LogError)(`Error creating mail folder '${folderName}'`, undefined, ex);
1010
+ LogError(`Error creating mail folder '${folderName}'`, undefined, ex);
884
1011
  return null;
885
1012
  }
886
1013
  }
1014
+ /**
1015
+ * Checks if a folder name is a system folder.
1016
+ */
887
1017
  isSystemFolder(displayName) {
888
1018
  const systemFolders = [
889
1019
  'inbox', 'sent items', 'drafts', 'deleted items', 'junk email',
@@ -891,6 +1021,9 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
891
1021
  ];
892
1022
  return systemFolders.includes(displayName.toLowerCase());
893
1023
  }
1024
+ /**
1025
+ * Maps folder display name to system folder type.
1026
+ */
894
1027
  mapSystemFolderType(displayName) {
895
1028
  const mapping = {
896
1029
  'inbox': 'inbox',
@@ -903,12 +1036,9 @@ let MSGraphProvider = class MSGraphProvider extends communication_types_1.BaseCo
903
1036
  return mapping[displayName.toLowerCase()] || 'other';
904
1037
  }
905
1038
  };
906
- exports.MSGraphProvider = MSGraphProvider;
907
- exports.MSGraphProvider = MSGraphProvider = __decorate([
908
- (0, global_1.RegisterClass)(communication_types_1.BaseCommunicationProvider, 'Microsoft Graph'),
1039
+ MSGraphProvider = __decorate([
1040
+ RegisterClass(BaseCommunicationProvider, 'Microsoft Graph'),
909
1041
  __metadata("design:paramtypes", [])
910
1042
  ], MSGraphProvider);
911
- function LoadMSGraphProvider() {
912
- }
913
- exports.LoadMSGraphProvider = LoadMSGraphProvider;
1043
+ export { MSGraphProvider };
914
1044
  //# sourceMappingURL=MSGraphProvider.js.map