m365-agent-cli 1.2.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/LICENSE +22 -0
- package/README.md +916 -0
- package/package.json +50 -0
- package/src/cli.ts +100 -0
- package/src/commands/auto-reply.ts +182 -0
- package/src/commands/calendar.ts +576 -0
- package/src/commands/counter.ts +87 -0
- package/src/commands/create-event.ts +544 -0
- package/src/commands/delegates.ts +286 -0
- package/src/commands/delete-event.ts +321 -0
- package/src/commands/drafts.ts +502 -0
- package/src/commands/files.ts +532 -0
- package/src/commands/find.ts +195 -0
- package/src/commands/findtime.ts +270 -0
- package/src/commands/folders.ts +177 -0
- package/src/commands/forward-event.ts +49 -0
- package/src/commands/graph-calendar.ts +217 -0
- package/src/commands/login.ts +195 -0
- package/src/commands/mail.ts +950 -0
- package/src/commands/oof.ts +263 -0
- package/src/commands/outlook-categories.ts +173 -0
- package/src/commands/outlook-graph.ts +880 -0
- package/src/commands/planner.ts +1678 -0
- package/src/commands/respond.ts +291 -0
- package/src/commands/rooms.ts +210 -0
- package/src/commands/rules.ts +511 -0
- package/src/commands/schedule.ts +109 -0
- package/src/commands/send.ts +204 -0
- package/src/commands/serve.ts +14 -0
- package/src/commands/sharepoint.ts +179 -0
- package/src/commands/site-pages.ts +163 -0
- package/src/commands/subscribe.ts +103 -0
- package/src/commands/subscriptions.ts +29 -0
- package/src/commands/suggest.ts +155 -0
- package/src/commands/todo.ts +2092 -0
- package/src/commands/update-event.ts +608 -0
- package/src/commands/update.ts +88 -0
- package/src/commands/verify-token.ts +62 -0
- package/src/commands/whoami.ts +74 -0
- package/src/index.ts +190 -0
- package/src/lib/atomic-write.ts +20 -0
- package/src/lib/attach-link-spec.test.ts +24 -0
- package/src/lib/attach-link-spec.ts +70 -0
- package/src/lib/attachments.ts +79 -0
- package/src/lib/auth.ts +192 -0
- package/src/lib/calendar-range.test.ts +41 -0
- package/src/lib/calendar-range.ts +103 -0
- package/src/lib/dates.test.ts +74 -0
- package/src/lib/dates.ts +137 -0
- package/src/lib/delegate-client.test.ts +74 -0
- package/src/lib/delegate-client.ts +322 -0
- package/src/lib/ews-client.ts +3418 -0
- package/src/lib/git-commit.ts +4 -0
- package/src/lib/glitchtip-eligibility.ts +220 -0
- package/src/lib/glitchtip.ts +253 -0
- package/src/lib/global-env.ts +3 -0
- package/src/lib/graph-auth.ts +223 -0
- package/src/lib/graph-calendar-client.test.ts +118 -0
- package/src/lib/graph-calendar-client.ts +112 -0
- package/src/lib/graph-client.test.ts +107 -0
- package/src/lib/graph-client.ts +1058 -0
- package/src/lib/graph-constants.ts +12 -0
- package/src/lib/graph-directory.ts +116 -0
- package/src/lib/graph-event.ts +134 -0
- package/src/lib/graph-schedule.ts +173 -0
- package/src/lib/graph-subscriptions.ts +94 -0
- package/src/lib/graph-user-path.ts +13 -0
- package/src/lib/jwt-utils.ts +34 -0
- package/src/lib/markdown.test.ts +21 -0
- package/src/lib/markdown.ts +174 -0
- package/src/lib/mime-type.ts +106 -0
- package/src/lib/oof-client.test.ts +59 -0
- package/src/lib/oof-client.ts +122 -0
- package/src/lib/outlook-graph-client.test.ts +146 -0
- package/src/lib/outlook-graph-client.ts +649 -0
- package/src/lib/outlook-master-categories.ts +145 -0
- package/src/lib/package-info.ts +59 -0
- package/src/lib/places-client.ts +144 -0
- package/src/lib/planner-client.ts +1226 -0
- package/src/lib/rules-client.ts +178 -0
- package/src/lib/sharepoint-client.ts +101 -0
- package/src/lib/site-pages-client.ts +73 -0
- package/src/lib/todo-client.test.ts +298 -0
- package/src/lib/todo-client.ts +1309 -0
- package/src/lib/url-validation.ts +40 -0
- package/src/lib/utils.ts +45 -0
- package/src/lib/webhook-server.ts +51 -0
- package/src/test/auth.test.ts +104 -0
- package/src/test/cli.integration.test.ts +1083 -0
- package/src/test/ews-client.test.ts +268 -0
- package/src/test/mocks/index.ts +375 -0
- package/src/test/mocks/responses.ts +861 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// Delegate management via EWS SOAP (AddDelegate / GetDelegate / UpdateDelegate / RemoveDelegate)
|
|
2
|
+
// No Microsoft Graph equivalent — only available via EWS.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
callEws,
|
|
6
|
+
EWS_USERNAME,
|
|
7
|
+
ewsError,
|
|
8
|
+
ewsResult,
|
|
9
|
+
extractBlocks,
|
|
10
|
+
extractTag,
|
|
11
|
+
soapEnvelope,
|
|
12
|
+
xmlEscape
|
|
13
|
+
} from './ews-client.js';
|
|
14
|
+
|
|
15
|
+
// ─── Types ───
|
|
16
|
+
|
|
17
|
+
export type DelegateFolderPermissionLevel =
|
|
18
|
+
| 'None'
|
|
19
|
+
| 'Owner'
|
|
20
|
+
| 'PublishingEditor'
|
|
21
|
+
| 'Editor'
|
|
22
|
+
| 'PublishingAuthor'
|
|
23
|
+
| 'Author'
|
|
24
|
+
| 'Reviewer'
|
|
25
|
+
| 'NonEditingAuthor'
|
|
26
|
+
| 'FolderVisible';
|
|
27
|
+
|
|
28
|
+
export type DeliverMeetingRequests =
|
|
29
|
+
| 'DelegatesAndMe'
|
|
30
|
+
| 'DelegatesOnly'
|
|
31
|
+
| 'DelegatesAndSendInformationToMe'
|
|
32
|
+
| 'NoForward';
|
|
33
|
+
|
|
34
|
+
export interface DelegatePermissions {
|
|
35
|
+
calendar?: DelegateFolderPermissionLevel;
|
|
36
|
+
inbox?: DelegateFolderPermissionLevel;
|
|
37
|
+
contacts?: DelegateFolderPermissionLevel;
|
|
38
|
+
tasks?: DelegateFolderPermissionLevel;
|
|
39
|
+
notes?: DelegateFolderPermissionLevel;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface DelegateInfo {
|
|
43
|
+
userId: string;
|
|
44
|
+
displayName?: string;
|
|
45
|
+
primaryEmail?: string;
|
|
46
|
+
permissions: DelegatePermissions;
|
|
47
|
+
viewPrivateItems: boolean;
|
|
48
|
+
deliverMeetingRequests: DeliverMeetingRequests;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AddDelegateOptions {
|
|
52
|
+
token: string;
|
|
53
|
+
delegateEmail: string;
|
|
54
|
+
delegateName?: string;
|
|
55
|
+
permissions: DelegatePermissions;
|
|
56
|
+
viewPrivateItems?: boolean;
|
|
57
|
+
deliverMeetingRequests?: DeliverMeetingRequests;
|
|
58
|
+
mailbox?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface UpdateDelegateOptions {
|
|
62
|
+
token: string;
|
|
63
|
+
delegateEmail: string;
|
|
64
|
+
permissions?: DelegatePermissions;
|
|
65
|
+
viewPrivateItems?: boolean;
|
|
66
|
+
deliverMeetingRequests?: DeliverMeetingRequests;
|
|
67
|
+
mailbox?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface RemoveDelegateOptions {
|
|
71
|
+
token: string;
|
|
72
|
+
delegateEmail: string;
|
|
73
|
+
mailbox?: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ─── Helpers ───
|
|
77
|
+
|
|
78
|
+
const FOLDER_PERMISSION_ELEMENT_MAP: Record<string, string> = {
|
|
79
|
+
calendar: 'CalendarFolderPermissionLevel',
|
|
80
|
+
inbox: 'InboxFolderPermissionLevel',
|
|
81
|
+
contacts: 'ContactsFolderPermissionLevel',
|
|
82
|
+
tasks: 'TasksFolderPermissionLevel',
|
|
83
|
+
notes: 'NotesFolderPermissionLevel'
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
function buildDelegatePermissionsXml(permissions: DelegatePermissions): string {
|
|
87
|
+
const entries = Object.entries(permissions).filter(([, level]) => level !== undefined);
|
|
88
|
+
|
|
89
|
+
if (entries.length === 0) return '';
|
|
90
|
+
|
|
91
|
+
return entries
|
|
92
|
+
.map(([folder, level]) => {
|
|
93
|
+
const elementName = FOLDER_PERMISSION_ELEMENT_MAP[folder];
|
|
94
|
+
if (!elementName) return '';
|
|
95
|
+
return `<t:${elementName}>${level}</t:${elementName}>`;
|
|
96
|
+
})
|
|
97
|
+
.join('\n ');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parseDelegateInfo(block: string, globalDeliver?: DeliverMeetingRequests): DelegateInfo {
|
|
101
|
+
const primaryEmail = extractTag(block, 'PrimarySmtpAddress') || undefined;
|
|
102
|
+
const smtpAddress = extractTag(block, 'SmtpAddress') || undefined;
|
|
103
|
+
const userId = primaryEmail || smtpAddress || '';
|
|
104
|
+
const displayName = extractTag(block, 'DisplayName') || undefined;
|
|
105
|
+
|
|
106
|
+
const viewPrivateStr = extractTag(block, 'ViewPrivateItems').toLowerCase();
|
|
107
|
+
const viewPrivateItems = viewPrivateStr === 'true';
|
|
108
|
+
|
|
109
|
+
const deliverStr = globalDeliver || extractTag(block, 'DeliverMeetingRequests');
|
|
110
|
+
const deliverMeetingRequests = (deliverStr || 'DelegatesAndMe') as DeliverMeetingRequests;
|
|
111
|
+
|
|
112
|
+
// Parse per-folder permissions
|
|
113
|
+
const permissions: DelegatePermissions = {};
|
|
114
|
+
const permissionsBlock = extractBlocks(block, 'DelegatePermissions')[0] || block;
|
|
115
|
+
|
|
116
|
+
for (const [folder, elementName] of Object.entries(FOLDER_PERMISSION_ELEMENT_MAP)) {
|
|
117
|
+
const level = extractTag(permissionsBlock, elementName) as DelegateFolderPermissionLevel | '';
|
|
118
|
+
if (level) {
|
|
119
|
+
(permissions as Record<string, string>)[folder] = level;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
userId,
|
|
125
|
+
displayName,
|
|
126
|
+
primaryEmail,
|
|
127
|
+
permissions,
|
|
128
|
+
viewPrivateItems,
|
|
129
|
+
deliverMeetingRequests
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ─── Operations ───
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get all delegates (and their permissions) on a mailbox.
|
|
137
|
+
* https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/getdelegate-operation
|
|
138
|
+
*/
|
|
139
|
+
export async function getDelegates(
|
|
140
|
+
token: string,
|
|
141
|
+
mailbox?: string
|
|
142
|
+
): Promise<{ ok: boolean; status: number; data?: DelegateInfo[]; error?: { code: string; message: string } }> {
|
|
143
|
+
try {
|
|
144
|
+
const address = mailbox || EWS_USERNAME;
|
|
145
|
+
const envelope = soapEnvelope(`
|
|
146
|
+
<m:GetDelegate IncludePermissions="true">
|
|
147
|
+
<m:Mailbox>
|
|
148
|
+
<t:EmailAddress>${xmlEscape(address)}</t:EmailAddress>
|
|
149
|
+
</m:Mailbox>
|
|
150
|
+
<m:UserIds />
|
|
151
|
+
</m:GetDelegate>`);
|
|
152
|
+
|
|
153
|
+
const xml = await callEws(token, envelope, address);
|
|
154
|
+
|
|
155
|
+
const delegateBlocks = extractBlocks(xml, 'DelegateUser');
|
|
156
|
+
const globalDeliverStr = extractTag(xml, 'DeliverMeetingRequests');
|
|
157
|
+
const globalDeliver = globalDeliverStr ? (globalDeliverStr as DeliverMeetingRequests) : undefined;
|
|
158
|
+
const delegates = delegateBlocks.map((block) => parseDelegateInfo(block, globalDeliver));
|
|
159
|
+
|
|
160
|
+
return ewsResult(delegates);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
return ewsError(err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Add a delegate with per-folder permissions.
|
|
168
|
+
* https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/adddelegate-operation
|
|
169
|
+
*/
|
|
170
|
+
export async function addDelegate(
|
|
171
|
+
options: AddDelegateOptions
|
|
172
|
+
): Promise<{ ok: boolean; status: number; data?: DelegateInfo; error?: { code: string; message: string } }> {
|
|
173
|
+
try {
|
|
174
|
+
const {
|
|
175
|
+
token,
|
|
176
|
+
delegateEmail,
|
|
177
|
+
delegateName,
|
|
178
|
+
permissions,
|
|
179
|
+
viewPrivateItems = false,
|
|
180
|
+
deliverMeetingRequests = 'DelegatesAndMe',
|
|
181
|
+
mailbox
|
|
182
|
+
} = options;
|
|
183
|
+
|
|
184
|
+
const address = mailbox || EWS_USERNAME;
|
|
185
|
+
|
|
186
|
+
const delegateUserXml = `
|
|
187
|
+
<t:DelegateUser>
|
|
188
|
+
<t:UserId>
|
|
189
|
+
<t:PrimarySmtpAddress>${xmlEscape(delegateEmail)}</t:PrimarySmtpAddress>
|
|
190
|
+
${delegateName ? `<t:DisplayName>${xmlEscape(delegateName)}</t:DisplayName>` : ''}
|
|
191
|
+
</t:UserId>
|
|
192
|
+
<t:DelegatePermissions>
|
|
193
|
+
${buildDelegatePermissionsXml(permissions)}
|
|
194
|
+
</t:DelegatePermissions>
|
|
195
|
+
<t:ViewPrivateItems>${viewPrivateItems}</t:ViewPrivateItems>
|
|
196
|
+
</t:DelegateUser>`.trim();
|
|
197
|
+
|
|
198
|
+
const envelope = soapEnvelope(`
|
|
199
|
+
<m:AddDelegate>
|
|
200
|
+
<m:Mailbox>
|
|
201
|
+
<t:EmailAddress>${xmlEscape(address)}</t:EmailAddress>
|
|
202
|
+
</m:Mailbox>
|
|
203
|
+
<m:DelegateUsers>
|
|
204
|
+
${delegateUserXml}
|
|
205
|
+
</m:DelegateUsers>
|
|
206
|
+
<m:DeliverMeetingRequests>${deliverMeetingRequests}</m:DeliverMeetingRequests>
|
|
207
|
+
</m:AddDelegate>`);
|
|
208
|
+
|
|
209
|
+
const xml = await callEws(token, envelope, address);
|
|
210
|
+
const delegateBlock = extractBlocks(xml, 'DelegateUser')[0] || '';
|
|
211
|
+
const globalDeliverStr = extractTag(xml, 'DeliverMeetingRequests');
|
|
212
|
+
const globalDeliver = globalDeliverStr ? (globalDeliverStr as DeliverMeetingRequests) : undefined;
|
|
213
|
+
|
|
214
|
+
return ewsResult(parseDelegateInfo(delegateBlock, globalDeliver));
|
|
215
|
+
} catch (err) {
|
|
216
|
+
return ewsError(err);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Update an existing delegate's permissions.
|
|
222
|
+
* https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/updatedelegate-operation
|
|
223
|
+
*/
|
|
224
|
+
export async function updateDelegate(
|
|
225
|
+
options: UpdateDelegateOptions
|
|
226
|
+
): Promise<{ ok: boolean; status: number; data?: DelegateInfo; error?: { code: string; message: string } }> {
|
|
227
|
+
try {
|
|
228
|
+
const { token, delegateEmail, permissions, viewPrivateItems, deliverMeetingRequests, mailbox } = options;
|
|
229
|
+
|
|
230
|
+
const address = mailbox || EWS_USERNAME;
|
|
231
|
+
|
|
232
|
+
// Build update elements — only include fields that are defined
|
|
233
|
+
const permissionsParts: string[] = [];
|
|
234
|
+
const delegateUserParts: string[] = [];
|
|
235
|
+
let deliverMeetingRequestsXml = '';
|
|
236
|
+
|
|
237
|
+
if (permissions !== undefined) {
|
|
238
|
+
const permXml = buildDelegatePermissionsXml(permissions);
|
|
239
|
+
if (permXml) {
|
|
240
|
+
permissionsParts.push(permXml);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (viewPrivateItems !== undefined) {
|
|
245
|
+
delegateUserParts.push(`<t:ViewPrivateItems>${viewPrivateItems}</t:ViewPrivateItems>`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (deliverMeetingRequests !== undefined) {
|
|
249
|
+
deliverMeetingRequestsXml = `<m:DeliverMeetingRequests>${deliverMeetingRequests}</m:DeliverMeetingRequests>`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (permissionsParts.length === 0 && delegateUserParts.length === 0 && !deliverMeetingRequestsXml) {
|
|
253
|
+
return { ok: false, status: 400, error: { code: 'NO_UPDATES', message: 'No fields to update' } };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const delegatePermissionsXml =
|
|
257
|
+
permissionsParts.length > 0
|
|
258
|
+
? `<t:DelegatePermissions>
|
|
259
|
+
${permissionsParts.join('\n')}
|
|
260
|
+
</t:DelegatePermissions>`
|
|
261
|
+
: '';
|
|
262
|
+
|
|
263
|
+
const delegateUserXml = `
|
|
264
|
+
<t:DelegateUser>
|
|
265
|
+
<t:UserId>
|
|
266
|
+
<t:PrimarySmtpAddress>${xmlEscape(delegateEmail)}</t:PrimarySmtpAddress>
|
|
267
|
+
</t:UserId>
|
|
268
|
+
${delegatePermissionsXml}
|
|
269
|
+
${delegateUserParts.join('\n ')}
|
|
270
|
+
</t:DelegateUser>`.trim();
|
|
271
|
+
|
|
272
|
+
const envelope = soapEnvelope(`
|
|
273
|
+
<m:UpdateDelegate>
|
|
274
|
+
<m:Mailbox>
|
|
275
|
+
<t:EmailAddress>${xmlEscape(address)}</t:EmailAddress>
|
|
276
|
+
</m:Mailbox>
|
|
277
|
+
<m:DelegateUsers>
|
|
278
|
+
${delegateUserXml}
|
|
279
|
+
</m:DelegateUsers>
|
|
280
|
+
${deliverMeetingRequestsXml}
|
|
281
|
+
</m:UpdateDelegate>`);
|
|
282
|
+
|
|
283
|
+
const xml = await callEws(token, envelope, address);
|
|
284
|
+
const delegateBlock = extractBlocks(xml, 'DelegateUser')[0] || '';
|
|
285
|
+
const globalDeliverStr = extractTag(xml, 'DeliverMeetingRequests');
|
|
286
|
+
const globalDeliver = globalDeliverStr ? (globalDeliverStr as DeliverMeetingRequests) : undefined;
|
|
287
|
+
|
|
288
|
+
return ewsResult(parseDelegateInfo(delegateBlock, globalDeliver));
|
|
289
|
+
} catch (err) {
|
|
290
|
+
return ewsError(err);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Remove a delegate from a mailbox.
|
|
296
|
+
* https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/removedelegate-operation
|
|
297
|
+
*/
|
|
298
|
+
export async function removeDelegate(
|
|
299
|
+
options: RemoveDelegateOptions
|
|
300
|
+
): Promise<{ ok: boolean; status: number; error?: { code: string; message: string } }> {
|
|
301
|
+
try {
|
|
302
|
+
const { token, delegateEmail, mailbox } = options;
|
|
303
|
+
const address = mailbox || EWS_USERNAME;
|
|
304
|
+
|
|
305
|
+
const envelope = soapEnvelope(`
|
|
306
|
+
<m:RemoveDelegate>
|
|
307
|
+
<m:Mailbox>
|
|
308
|
+
<t:EmailAddress>${xmlEscape(address)}</t:EmailAddress>
|
|
309
|
+
</m:Mailbox>
|
|
310
|
+
<m:UserIds>
|
|
311
|
+
<t:UserId>
|
|
312
|
+
<t:PrimarySmtpAddress>${xmlEscape(delegateEmail)}</t:PrimarySmtpAddress>
|
|
313
|
+
</t:UserId>
|
|
314
|
+
</m:UserIds>
|
|
315
|
+
</m:RemoveDelegate>`);
|
|
316
|
+
|
|
317
|
+
await callEws(token, envelope, address);
|
|
318
|
+
return { ok: true, status: 200 };
|
|
319
|
+
} catch (err) {
|
|
320
|
+
return ewsError(err);
|
|
321
|
+
}
|
|
322
|
+
}
|