@littlebearapps/outlook-assistant 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +22 -0
- package/LICENSE +21 -0
- package/README.md +422 -0
- package/advanced/index.js +652 -0
- package/auth/index.js +32 -0
- package/auth/oauth-server.js +233 -0
- package/auth/token-manager.js +105 -0
- package/auth/token-storage.js +359 -0
- package/auth/tools.js +159 -0
- package/calendar/accept.js +72 -0
- package/calendar/cancel.js +72 -0
- package/calendar/create.js +115 -0
- package/calendar/decline.js +72 -0
- package/calendar/delete.js +67 -0
- package/calendar/index.js +130 -0
- package/calendar/list.js +108 -0
- package/categories/index.js +955 -0
- package/config.js +95 -0
- package/contacts/index.js +754 -0
- package/email/attachments.js +365 -0
- package/email/conversations.js +666 -0
- package/email/delta.js +210 -0
- package/email/export.js +572 -0
- package/email/folder-utils.js +192 -0
- package/email/headers.js +344 -0
- package/email/index.js +537 -0
- package/email/list.js +136 -0
- package/email/mark-as-read.js +114 -0
- package/email/mime.js +286 -0
- package/email/read.js +161 -0
- package/email/search.js +628 -0
- package/email/send.js +169 -0
- package/folder/create.js +137 -0
- package/folder/delete.js +108 -0
- package/folder/index.js +112 -0
- package/folder/list.js +289 -0
- package/folder/move.js +186 -0
- package/folder/stats.js +322 -0
- package/index.js +162 -0
- package/llms.txt +76 -0
- package/outlook-auth-server.js +384 -0
- package/package.json +97 -0
- package/rules/create.js +273 -0
- package/rules/index.js +276 -0
- package/rules/list.js +216 -0
- package/settings/index.js +678 -0
- package/utils/field-presets.js +311 -0
- package/utils/graph-api.js +268 -0
- package/utils/mock-data.js +154 -0
- package/utils/odata-helpers.js +33 -0
- package/utils/response-formatter.js +457 -0
- package/utils/safety.js +123 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings module for Outlook Assistant server
|
|
3
|
+
*
|
|
4
|
+
* Manages mailbox settings, automatic replies (out-of-office),
|
|
5
|
+
* and working hours configuration.
|
|
6
|
+
*/
|
|
7
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
8
|
+
const { ensureAuthenticated } = require('../auth');
|
|
9
|
+
|
|
10
|
+
// Days of the week for working hours
|
|
11
|
+
const DAYS_OF_WEEK = [
|
|
12
|
+
'sunday',
|
|
13
|
+
'monday',
|
|
14
|
+
'tuesday',
|
|
15
|
+
'wednesday',
|
|
16
|
+
'thursday',
|
|
17
|
+
'friday',
|
|
18
|
+
'saturday',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Format time for display (HH:MM)
|
|
23
|
+
*/
|
|
24
|
+
function formatTime(timeString) {
|
|
25
|
+
if (!timeString) return 'Not set';
|
|
26
|
+
// Graph API returns time in ISO format like "08:00:00.0000000"
|
|
27
|
+
return timeString.substring(0, 5);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Format working hours for display
|
|
32
|
+
*/
|
|
33
|
+
function formatWorkingHours(workingHours) {
|
|
34
|
+
if (!workingHours) return 'Not configured';
|
|
35
|
+
|
|
36
|
+
const lines = [];
|
|
37
|
+
lines.push(`**Time Zone**: ${workingHours.timeZone?.name || 'Not set'}`);
|
|
38
|
+
lines.push(`**Start Time**: ${formatTime(workingHours.startTime)}`);
|
|
39
|
+
lines.push(`**End Time**: ${formatTime(workingHours.endTime)}`);
|
|
40
|
+
|
|
41
|
+
if (workingHours.daysOfWeek && workingHours.daysOfWeek.length > 0) {
|
|
42
|
+
const days = workingHours.daysOfWeek.map(
|
|
43
|
+
(d) => d.charAt(0).toUpperCase() + d.slice(1)
|
|
44
|
+
);
|
|
45
|
+
lines.push(`**Work Days**: ${days.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return lines.join('\n');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Format automatic replies for display
|
|
53
|
+
*/
|
|
54
|
+
function formatAutomaticReplies(settings) {
|
|
55
|
+
if (!settings) return 'Not configured';
|
|
56
|
+
|
|
57
|
+
const lines = [];
|
|
58
|
+
lines.push(
|
|
59
|
+
`**Status**: ${
|
|
60
|
+
settings.status === 'disabled'
|
|
61
|
+
? '🔴 Disabled'
|
|
62
|
+
: settings.status === 'alwaysEnabled'
|
|
63
|
+
? '🟢 Always Enabled'
|
|
64
|
+
: '📅 Scheduled'
|
|
65
|
+
}`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (settings.status !== 'disabled') {
|
|
69
|
+
if (settings.scheduledStartDateTime) {
|
|
70
|
+
lines.push(
|
|
71
|
+
`**Scheduled Start**: ${new Date(settings.scheduledStartDateTime.dateTime).toLocaleString()}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (settings.scheduledEndDateTime) {
|
|
75
|
+
lines.push(
|
|
76
|
+
`**Scheduled End**: ${new Date(settings.scheduledEndDateTime.dateTime).toLocaleString()}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (settings.internalReplyMessage) {
|
|
81
|
+
lines.push(
|
|
82
|
+
`\n**Internal Reply**:\n${settings.internalReplyMessage.substring(0, 500)}${settings.internalReplyMessage.length > 500 ? '...' : ''}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (settings.externalReplyMessage) {
|
|
87
|
+
lines.push(
|
|
88
|
+
`\n**External Reply**:\n${settings.externalReplyMessage.substring(0, 500)}${settings.externalReplyMessage.length > 500 ? '...' : ''}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
lines.push(
|
|
93
|
+
`\n**External Audience**: ${settings.externalAudience || 'none'}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return lines.join('\n');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get mailbox settings handler
|
|
102
|
+
*/
|
|
103
|
+
async function handleGetMailboxSettings(args) {
|
|
104
|
+
const section = args.section; // Optional: 'all', 'language', 'timezone', 'workingHours', 'automaticReplies'
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const accessToken = await ensureAuthenticated();
|
|
108
|
+
|
|
109
|
+
let endpoint = 'me/mailboxSettings';
|
|
110
|
+
if (section && section !== 'all') {
|
|
111
|
+
endpoint = `me/mailboxSettings/${section}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const settings = await callGraphAPI(accessToken, 'GET', endpoint);
|
|
115
|
+
|
|
116
|
+
let output = [];
|
|
117
|
+
output.push('# Mailbox Settings\n');
|
|
118
|
+
|
|
119
|
+
if (section && section !== 'all') {
|
|
120
|
+
// Single section — format based on section type
|
|
121
|
+
const sectionTitle = section.charAt(0).toUpperCase() + section.slice(1);
|
|
122
|
+
output.push(`## ${sectionTitle}\n`);
|
|
123
|
+
|
|
124
|
+
if (section === 'workingHours') {
|
|
125
|
+
output.push(formatWorkingHours(settings));
|
|
126
|
+
} else if (section === 'automaticRepliesSetting') {
|
|
127
|
+
output.push(formatAutomaticReplies(settings));
|
|
128
|
+
} else if (section === 'language') {
|
|
129
|
+
output.push(`**Locale**: ${settings.locale || 'Not set'}`);
|
|
130
|
+
output.push(`**Display Name**: ${settings.displayName || 'Not set'}`);
|
|
131
|
+
} else if (section === 'timeZone') {
|
|
132
|
+
output.push(`**Zone**: ${settings}`);
|
|
133
|
+
} else {
|
|
134
|
+
// Fallback for unknown sections
|
|
135
|
+
output.push('```json');
|
|
136
|
+
output.push(JSON.stringify(settings, null, 2));
|
|
137
|
+
output.push('```');
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
// All settings
|
|
141
|
+
if (settings.language) {
|
|
142
|
+
output.push('## Language');
|
|
143
|
+
output.push(`**Locale**: ${settings.language.locale || 'Not set'}`);
|
|
144
|
+
output.push(
|
|
145
|
+
`**Display Name**: ${settings.language.displayName || 'Not set'}`
|
|
146
|
+
);
|
|
147
|
+
output.push('');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (settings.timeZone) {
|
|
151
|
+
output.push('## Time Zone');
|
|
152
|
+
output.push(`**Zone**: ${settings.timeZone}`);
|
|
153
|
+
output.push('');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (settings.dateFormat) {
|
|
157
|
+
output.push('## Date/Time Format');
|
|
158
|
+
output.push(`**Date Format**: ${settings.dateFormat}`);
|
|
159
|
+
output.push(`**Time Format**: ${settings.timeFormat || 'Not set'}`);
|
|
160
|
+
output.push('');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (settings.workingHours) {
|
|
164
|
+
output.push('## Working Hours');
|
|
165
|
+
output.push(formatWorkingHours(settings.workingHours));
|
|
166
|
+
output.push('');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (settings.automaticRepliesSetting) {
|
|
170
|
+
output.push('## Automatic Replies (Out of Office)');
|
|
171
|
+
output.push(formatAutomaticReplies(settings.automaticRepliesSetting));
|
|
172
|
+
output.push('');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (settings.delegateMeetingMessageDeliveryOptions) {
|
|
176
|
+
output.push('## Delegate Settings');
|
|
177
|
+
output.push(
|
|
178
|
+
`**Meeting Message Delivery**: ${settings.delegateMeetingMessageDeliveryOptions}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
content: [
|
|
185
|
+
{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: output.join('\n'),
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
_meta: {
|
|
191
|
+
settings,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (error.message === 'Authentication required') {
|
|
196
|
+
return {
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
type: 'text',
|
|
200
|
+
text: "Authentication required. Please use the 'auth' tool with action=authenticate first.",
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
content: [
|
|
207
|
+
{
|
|
208
|
+
type: 'text',
|
|
209
|
+
text: `Error getting mailbox settings: ${error.message}`,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Set automatic replies (out of office) handler
|
|
218
|
+
*/
|
|
219
|
+
async function handleSetAutomaticReplies(args) {
|
|
220
|
+
const {
|
|
221
|
+
enabled,
|
|
222
|
+
startDateTime,
|
|
223
|
+
endDateTime,
|
|
224
|
+
internalReplyMessage,
|
|
225
|
+
externalReplyMessage,
|
|
226
|
+
externalAudience,
|
|
227
|
+
} = args;
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
const accessToken = await ensureAuthenticated();
|
|
231
|
+
|
|
232
|
+
// Build the settings object
|
|
233
|
+
const settings = {};
|
|
234
|
+
|
|
235
|
+
// Determine status
|
|
236
|
+
if (enabled === false) {
|
|
237
|
+
settings.status = 'disabled';
|
|
238
|
+
} else if (startDateTime && endDateTime) {
|
|
239
|
+
settings.status = 'scheduled';
|
|
240
|
+
settings.scheduledStartDateTime = {
|
|
241
|
+
dateTime: new Date(startDateTime).toISOString(),
|
|
242
|
+
timeZone: 'UTC',
|
|
243
|
+
};
|
|
244
|
+
settings.scheduledEndDateTime = {
|
|
245
|
+
dateTime: new Date(endDateTime).toISOString(),
|
|
246
|
+
timeZone: 'UTC',
|
|
247
|
+
};
|
|
248
|
+
} else if (enabled === true) {
|
|
249
|
+
settings.status = 'alwaysEnabled';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Reply messages
|
|
253
|
+
if (internalReplyMessage !== undefined) {
|
|
254
|
+
settings.internalReplyMessage = internalReplyMessage;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (externalReplyMessage !== undefined) {
|
|
258
|
+
settings.externalReplyMessage = externalReplyMessage;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// External audience
|
|
262
|
+
if (externalAudience) {
|
|
263
|
+
if (!['none', 'contactsOnly', 'all'].includes(externalAudience)) {
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: 'text',
|
|
268
|
+
text: "externalAudience must be 'none', 'contactsOnly', or 'all'.",
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
settings.externalAudience = externalAudience;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Apply settings
|
|
277
|
+
await callGraphAPI(accessToken, 'PATCH', 'me/mailboxSettings', {
|
|
278
|
+
automaticRepliesSetting: settings,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Get updated settings
|
|
282
|
+
const updated = await callGraphAPI(
|
|
283
|
+
accessToken,
|
|
284
|
+
'GET',
|
|
285
|
+
'me/mailboxSettings/automaticRepliesSetting'
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
let output = [];
|
|
289
|
+
output.push('Automatic replies updated!\n');
|
|
290
|
+
output.push(formatAutomaticReplies(updated));
|
|
291
|
+
|
|
292
|
+
// Warn if enabling without messages
|
|
293
|
+
if (
|
|
294
|
+
updated.status !== 'disabled' &&
|
|
295
|
+
!internalReplyMessage &&
|
|
296
|
+
!externalReplyMessage
|
|
297
|
+
) {
|
|
298
|
+
if (updated.internalReplyMessage || updated.externalReplyMessage) {
|
|
299
|
+
const preview = (
|
|
300
|
+
updated.internalReplyMessage || updated.externalReplyMessage
|
|
301
|
+
).substring(0, 100);
|
|
302
|
+
output.push(
|
|
303
|
+
`\n**Note**: Using previously configured message: "${preview}${preview.length >= 100 ? '...' : ''}"`
|
|
304
|
+
);
|
|
305
|
+
} else {
|
|
306
|
+
output.push(
|
|
307
|
+
'\n**Warning**: Auto-replies enabled with no message configured. Recipients will receive a blank reply.'
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: 'text',
|
|
316
|
+
text: output.join('\n'),
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
_meta: {
|
|
320
|
+
settings: updated,
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
} catch (error) {
|
|
324
|
+
if (error.message === 'Authentication required') {
|
|
325
|
+
return {
|
|
326
|
+
content: [
|
|
327
|
+
{
|
|
328
|
+
type: 'text',
|
|
329
|
+
text: "Authentication required. Please use the 'auth' tool with action=authenticate first.",
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
content: [
|
|
336
|
+
{
|
|
337
|
+
type: 'text',
|
|
338
|
+
text: `Error setting automatic replies: ${error.message}`,
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Set working hours handler
|
|
347
|
+
*/
|
|
348
|
+
async function handleSetWorkingHours(args) {
|
|
349
|
+
const { startTime, endTime, daysOfWeek, timeZone } = args;
|
|
350
|
+
|
|
351
|
+
// Validate inputs
|
|
352
|
+
if (!startTime && !endTime && !daysOfWeek && !timeZone) {
|
|
353
|
+
return {
|
|
354
|
+
content: [
|
|
355
|
+
{
|
|
356
|
+
type: 'text',
|
|
357
|
+
text: 'At least one of startTime, endTime, daysOfWeek, or timeZone is required.',
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Validate time format (HH:MM or HH:MM:SS)
|
|
364
|
+
const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
|
|
365
|
+
if (startTime && !timeRegex.test(startTime)) {
|
|
366
|
+
return {
|
|
367
|
+
content: [
|
|
368
|
+
{
|
|
369
|
+
type: 'text',
|
|
370
|
+
text: "startTime must be in HH:MM or HH:MM:SS format (e.g., '09:00' or '09:00:00').",
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (endTime && !timeRegex.test(endTime)) {
|
|
376
|
+
return {
|
|
377
|
+
content: [
|
|
378
|
+
{
|
|
379
|
+
type: 'text',
|
|
380
|
+
text: "endTime must be in HH:MM or HH:MM:SS format (e.g., '17:00' or '17:00:00').",
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Validate days of week
|
|
387
|
+
if (daysOfWeek) {
|
|
388
|
+
const invalidDays = daysOfWeek.filter(
|
|
389
|
+
(d) => !DAYS_OF_WEEK.includes(d.toLowerCase())
|
|
390
|
+
);
|
|
391
|
+
if (invalidDays.length > 0) {
|
|
392
|
+
return {
|
|
393
|
+
content: [
|
|
394
|
+
{
|
|
395
|
+
type: 'text',
|
|
396
|
+
text: `Invalid days: ${invalidDays.join(', ')}. Valid days: ${DAYS_OF_WEEK.join(', ')}`,
|
|
397
|
+
},
|
|
398
|
+
],
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const accessToken = await ensureAuthenticated();
|
|
405
|
+
|
|
406
|
+
// Get current settings first
|
|
407
|
+
const current = await callGraphAPI(
|
|
408
|
+
accessToken,
|
|
409
|
+
'GET',
|
|
410
|
+
'me/mailboxSettings/workingHours'
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
// Build update
|
|
414
|
+
const workingHours = {
|
|
415
|
+
startTime: startTime
|
|
416
|
+
? startTime.length === 5
|
|
417
|
+
? startTime + ':00.0000000'
|
|
418
|
+
: startTime + '.0000000'
|
|
419
|
+
: current.startTime,
|
|
420
|
+
endTime: endTime
|
|
421
|
+
? endTime.length === 5
|
|
422
|
+
? endTime + ':00.0000000'
|
|
423
|
+
: endTime + '.0000000'
|
|
424
|
+
: current.endTime,
|
|
425
|
+
daysOfWeek: daysOfWeek
|
|
426
|
+
? daysOfWeek.map((d) => d.toLowerCase())
|
|
427
|
+
: current.daysOfWeek,
|
|
428
|
+
timeZone: timeZone ? { name: timeZone } : current.timeZone,
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
// Apply settings
|
|
432
|
+
await callGraphAPI(accessToken, 'PATCH', 'me/mailboxSettings', {
|
|
433
|
+
workingHours,
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Get updated settings
|
|
437
|
+
const updated = await callGraphAPI(
|
|
438
|
+
accessToken,
|
|
439
|
+
'GET',
|
|
440
|
+
'me/mailboxSettings/workingHours'
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
let output = [];
|
|
444
|
+
output.push('Working hours updated!\n');
|
|
445
|
+
output.push(formatWorkingHours(updated));
|
|
446
|
+
|
|
447
|
+
return {
|
|
448
|
+
content: [
|
|
449
|
+
{
|
|
450
|
+
type: 'text',
|
|
451
|
+
text: output.join('\n'),
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
_meta: {
|
|
455
|
+
settings: updated,
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
} catch (error) {
|
|
459
|
+
if (error.message === 'Authentication required') {
|
|
460
|
+
return {
|
|
461
|
+
content: [
|
|
462
|
+
{
|
|
463
|
+
type: 'text',
|
|
464
|
+
text: "Authentication required. Please use the 'auth' tool with action=authenticate first.",
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
return {
|
|
470
|
+
content: [
|
|
471
|
+
{
|
|
472
|
+
type: 'text',
|
|
473
|
+
text: `Error setting working hours: ${error.message}`,
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Get automatic replies settings handler (standalone)
|
|
482
|
+
*/
|
|
483
|
+
async function handleGetAutomaticReplies() {
|
|
484
|
+
try {
|
|
485
|
+
const accessToken = await ensureAuthenticated();
|
|
486
|
+
const settings = await callGraphAPI(
|
|
487
|
+
accessToken,
|
|
488
|
+
'GET',
|
|
489
|
+
'me/mailboxSettings/automaticRepliesSetting'
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
let output = [];
|
|
493
|
+
output.push('# Automatic Replies\n');
|
|
494
|
+
output.push(formatAutomaticReplies(settings));
|
|
495
|
+
|
|
496
|
+
return {
|
|
497
|
+
content: [{ type: 'text', text: output.join('\n') }],
|
|
498
|
+
_meta: { settings },
|
|
499
|
+
};
|
|
500
|
+
} catch (error) {
|
|
501
|
+
if (error.message === 'Authentication required') {
|
|
502
|
+
return {
|
|
503
|
+
content: [
|
|
504
|
+
{
|
|
505
|
+
type: 'text',
|
|
506
|
+
text: "Authentication required. Please use the 'auth' tool with action=authenticate first.",
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
return {
|
|
512
|
+
content: [
|
|
513
|
+
{
|
|
514
|
+
type: 'text',
|
|
515
|
+
text: `Error getting automatic replies: ${error.message}`,
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Get working hours settings handler (standalone)
|
|
524
|
+
*/
|
|
525
|
+
async function handleGetWorkingHours() {
|
|
526
|
+
try {
|
|
527
|
+
const accessToken = await ensureAuthenticated();
|
|
528
|
+
const settings = await callGraphAPI(
|
|
529
|
+
accessToken,
|
|
530
|
+
'GET',
|
|
531
|
+
'me/mailboxSettings/workingHours'
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
let output = [];
|
|
535
|
+
output.push('# Working Hours\n');
|
|
536
|
+
output.push(formatWorkingHours(settings));
|
|
537
|
+
|
|
538
|
+
return {
|
|
539
|
+
content: [{ type: 'text', text: output.join('\n') }],
|
|
540
|
+
_meta: { settings },
|
|
541
|
+
};
|
|
542
|
+
} catch (error) {
|
|
543
|
+
if (error.message === 'Authentication required') {
|
|
544
|
+
return {
|
|
545
|
+
content: [
|
|
546
|
+
{
|
|
547
|
+
type: 'text',
|
|
548
|
+
text: "Authentication required. Please use the 'auth' tool with action=authenticate first.",
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
return {
|
|
554
|
+
content: [
|
|
555
|
+
{
|
|
556
|
+
type: 'text',
|
|
557
|
+
text: `Error getting working hours: ${error.message}`,
|
|
558
|
+
},
|
|
559
|
+
],
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Consolidated tool definition
|
|
565
|
+
const settingsTools = [
|
|
566
|
+
{
|
|
567
|
+
name: 'mailbox-settings',
|
|
568
|
+
description:
|
|
569
|
+
'Manage mailbox settings. action=get (default) retrieves settings (language, timezone, working hours, auto-replies). action=set-auto-replies configures out-of-office. action=set-working-hours configures work schedule.',
|
|
570
|
+
annotations: {
|
|
571
|
+
title: 'Mailbox Settings',
|
|
572
|
+
readOnlyHint: false,
|
|
573
|
+
destructiveHint: false,
|
|
574
|
+
idempotentHint: true,
|
|
575
|
+
},
|
|
576
|
+
inputSchema: {
|
|
577
|
+
type: 'object',
|
|
578
|
+
properties: {
|
|
579
|
+
action: {
|
|
580
|
+
type: 'string',
|
|
581
|
+
enum: ['get', 'set-auto-replies', 'set-working-hours'],
|
|
582
|
+
description: 'Action to perform (default: get)',
|
|
583
|
+
},
|
|
584
|
+
// get params
|
|
585
|
+
section: {
|
|
586
|
+
type: 'string',
|
|
587
|
+
enum: [
|
|
588
|
+
'all',
|
|
589
|
+
'language',
|
|
590
|
+
'timeZone',
|
|
591
|
+
'workingHours',
|
|
592
|
+
'automaticRepliesSetting',
|
|
593
|
+
],
|
|
594
|
+
description:
|
|
595
|
+
'Specific section to retrieve (action=get, default: all)',
|
|
596
|
+
},
|
|
597
|
+
// set-auto-replies params
|
|
598
|
+
enabled: {
|
|
599
|
+
type: 'boolean',
|
|
600
|
+
description:
|
|
601
|
+
'Enable (true) or disable (false) automatic replies (action=set-auto-replies)',
|
|
602
|
+
},
|
|
603
|
+
startDateTime: {
|
|
604
|
+
type: 'string',
|
|
605
|
+
description:
|
|
606
|
+
'Start date/time for scheduled mode, ISO 8601 format (action=set-auto-replies)',
|
|
607
|
+
},
|
|
608
|
+
endDateTime: {
|
|
609
|
+
type: 'string',
|
|
610
|
+
description:
|
|
611
|
+
'End date/time for scheduled mode, ISO 8601 format (action=set-auto-replies)',
|
|
612
|
+
},
|
|
613
|
+
internalReplyMessage: {
|
|
614
|
+
type: 'string',
|
|
615
|
+
description:
|
|
616
|
+
'Reply message for internal senders (action=set-auto-replies)',
|
|
617
|
+
},
|
|
618
|
+
externalReplyMessage: {
|
|
619
|
+
type: 'string',
|
|
620
|
+
description:
|
|
621
|
+
'Reply message for external senders (action=set-auto-replies)',
|
|
622
|
+
},
|
|
623
|
+
externalAudience: {
|
|
624
|
+
type: 'string',
|
|
625
|
+
enum: ['none', 'contactsOnly', 'all'],
|
|
626
|
+
description: 'Who receives external reply (action=set-auto-replies)',
|
|
627
|
+
},
|
|
628
|
+
// set-working-hours params
|
|
629
|
+
startTime: {
|
|
630
|
+
type: 'string',
|
|
631
|
+
description:
|
|
632
|
+
"Work start time in HH:MM format, e.g. '09:00' (action=set-working-hours)",
|
|
633
|
+
},
|
|
634
|
+
endTime: {
|
|
635
|
+
type: 'string',
|
|
636
|
+
description:
|
|
637
|
+
"Work end time in HH:MM format, e.g. '17:00' (action=set-working-hours)",
|
|
638
|
+
},
|
|
639
|
+
daysOfWeek: {
|
|
640
|
+
type: 'array',
|
|
641
|
+
items: {
|
|
642
|
+
type: 'string',
|
|
643
|
+
enum: DAYS_OF_WEEK,
|
|
644
|
+
},
|
|
645
|
+
description:
|
|
646
|
+
"Work days, e.g. ['monday','tuesday','wednesday','thursday','friday'] (action=set-working-hours)",
|
|
647
|
+
},
|
|
648
|
+
timeZone: {
|
|
649
|
+
type: 'string',
|
|
650
|
+
description:
|
|
651
|
+
"Time zone name, e.g. 'Australia/Melbourne' (action=set-working-hours)",
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
required: [],
|
|
655
|
+
},
|
|
656
|
+
handler: async (args) => {
|
|
657
|
+
const action = args.action || 'get';
|
|
658
|
+
switch (action) {
|
|
659
|
+
case 'set-auto-replies':
|
|
660
|
+
return handleSetAutomaticReplies(args);
|
|
661
|
+
case 'set-working-hours':
|
|
662
|
+
return handleSetWorkingHours(args);
|
|
663
|
+
case 'get':
|
|
664
|
+
default:
|
|
665
|
+
return handleGetMailboxSettings(args);
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
];
|
|
670
|
+
|
|
671
|
+
module.exports = {
|
|
672
|
+
settingsTools,
|
|
673
|
+
handleGetMailboxSettings,
|
|
674
|
+
handleGetAutomaticReplies,
|
|
675
|
+
handleSetAutomaticReplies,
|
|
676
|
+
handleGetWorkingHours,
|
|
677
|
+
handleSetWorkingHours,
|
|
678
|
+
};
|