使用Python msgraph API获取会议室日历的技术问题求助
使用新版Python Microsoft Graph SDK获取会议室日历(应用权限模式)
问题背景
已完成操作:
- 在Azure AD中为应用配置了
Bookings.Read.All、Calendars.Read、Calendars.ReadBasic.All、Group.Read.All、Place.Read.All、User.Read应用权限并获得管理员同意 - 通过证书认证成功登录Microsoft Graph,已获取到会议室列表
需求: - 获取每个会议室过去一周的日历事件,包含已预订会议及参会人员
遇到的问题: - 使用
graph_client.users.by_user_id(room_id).calendar.events.get()无法获取数据,且教程中client.me端点不适用于应用权限模式
解决方案
核心要点
- 会议室的本质是资源账户:在Microsoft Graph中,会议室属于特殊的用户(资源账户),因此可以通过
users端点访问其日历,使用会议室的ID或邮箱地址均可作为user_id参数。 - 添加时间筛选条件:通过
$filter参数筛选过去一周的事件,避免返回全部历史数据。 - 处理分页结果:Graph API默认返回最多100条数据,需循环获取所有分页结果。
- 权限验证:确保
Calendars.Read应用权限已被管理员同意(此权限足够读取会议室日历)。
修改后的代码
#!/usr/bin/env python3 import asyncio from datetime import datetime, timedelta from msgraph.generated.models.room import Room from msgraph import GraphServiceClient from azure.identity import CertificateCredential config = { 'client_id': '<your-client-id>', 'tenant_id': '<your-tenant-id>', 'certificate_path': 'msal_crt_n_key.pem', 'scope': ['https://graph.microsoft.com/.default'], } async def get_schedule_for_room(graph_client, room_identifier): # 计算过去一周的UTC时间范围 one_week_ago = (datetime.utcnow() - timedelta(weeks=1)).isoformat() + 'Z' now = datetime.utcnow().isoformat() + 'Z' # 构建请求参数:筛选时间范围+展开参会人员信息 query_params = { '$filter': f"start/dateTime ge '{one_week_ago}' and end/dateTime le '{now}'", '$expand': 'attendees' } all_events = [] result = await graph_client.users.by_user_id(room_identifier).calendar.events.get(query_parameters=query_params) # 处理分页,获取所有事件 while result: if result.value: all_events.extend(result.value) if result.odata_next_link: result = await graph_client.users.by_user_id(room_identifier).calendar.events.get(url=result.odata_next_link) else: break return all_events async def get_rooms(graph_client): return await graph_client.places.graph_room.get() async def main(): print("Login using certificate") credential = CertificateCredential( tenant_id=config['tenant_id'], client_id=config['client_id'], certificate_path=config['certificate_path'] ) graph_client = GraphServiceClient(credential, config['scope']) print("Get list of rooms") rooms = await get_rooms(graph_client) print(f"Found {len(rooms.value) if rooms.value else 0} rooms") if rooms.value: for room in rooms.value: print(f"\nProcessing room: {room.display_name} ({room.email_address})") # 使用会议室邮箱地址作为标识符(也可替换为room.id) events = await get_schedule_for_room(graph_client, room.email_address) print(f"Found {len(events)} events in the past week:") for event in events: attendee_count = len(event.attendees) if event.attendees else 0 print(f"- {event.subject} | Start: {event.start.date_time} | Attendees: {attendee_count}") asyncio.run(main())
关键修改说明
- 时间筛选:用UTC时间格式限定过去一周的事件范围,避免时区偏差导致的筛选错误。
- 参会人员展开:通过
$expand=attendees直接获取参会人员数据,无需额外接口请求。 - 分页处理:循环读取所有分页结果,确保不会遗漏超出默认返回数量的事件。
- 变量修复:修正了原代码中
print(calendars)的变量名错误,改用会议室邮箱作为请求标识符(比ID更直观)。 - 日志优化:增加了结构化的输出信息,便于快速查看会议室的预订情况。
内容的提问来源于stack exchange,提问作者Kodsama
相关产品推荐
相关产品推荐

