You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Azure Function中使用Graph API(SDK5.35)的FindMeetingTimes遇错误求助

解决Azure Function中使用Graph SDK调用FindMeetingTimes的两个问题

问题1:/me request is only valid with delegated authentication flow 错误

  • 原因:你当前使用客户端凭证(Client Credentials)认证流,这是应用级权限,没有关联具体用户上下文。而/me端点需要依托用户的委托权限(如Authorization Code流),因为/me指向"当前登录用户",客户端凭证流不存在该上下文,因此无法使用。
  • 解决方案:必须切换到指定具体用户ID的调用方式,即使用graphClient.Users[userId].FindMeetingTimes,同时确保应用已被授予对应的应用权限。

问题2:Invalid user address 错误

  • 原因:
    1. 请求体类型不匹配:你当前使用的Microsoft.Graph.Me.FindMeetingTimes.FindMeetingTimesPostRequestBody是专为/me端点设计的,调用/users/{id}端点时,必须使用对应的Microsoft.Graph.Users.Item.FindMeetingTimes.FindMeetingTimesPostRequestBody类型。
    2. 应用权限不足:客户端凭证流需要授予应用Calendars.Read.Shared或Calendars.ReadWrite.Shared权限(按需选择),且需管理员同意。
    3. 参会者邮箱无效:确保参会者邮箱是租户内有效用户邮箱,或外部邮箱已被允许访问。
  • 解决方案:
    • 替换请求体类型为Users端点对应的类型;
    • 检查并授予正确的应用权限;
    • 验证参会者邮箱的有效性。

修正后的完整代码

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;

namespace Company.Function
{
    public class HttpTrigger0
    {
        private readonly ILogger _logger;

        public HttpTrigger0(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<HttpTrigger0>(); // 修正日志类名称与当前类一致
        }

        [Function("HttpTrigger0")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestData req)
        {
            _logger.LogInformation("C# HTTP trigger function processed a request.");

            // 替换为目标用户的实际Object ID
            var userId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";

            var scopes = new[] { "https://graph.microsoft.com/.default" };
            var tenantId = Environment.GetEnvironmentVariable("TENANT_ID");
            var clientId = Environment.GetEnvironmentVariable("CLIENT_ID");
            var clientSecret = Environment.GetEnvironmentVariable("CLIENT_SECRET");
            var options = new ClientSecretCredentialOptions  
            {  
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud  
            }; 
            var clientSecretCredential = new ClientSecretCredential(
                tenantId, clientId, clientSecret, options);
            var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
            
            // 使用Users端点对应的请求体类型
            var requestBody = new Microsoft.Graph.Users.Item.FindMeetingTimes.FindMeetingTimesPostRequestBody
            {
                Attendees = new List<AttendeeBase>
                {
                    new AttendeeBase
                    {
                        EmailAddress = new EmailAddress
                        {
                            Name = "User1",
                            Address = "user1@test.onmicrosoft.com",
                        },
                    },
                    new AttendeeBase
                    {
                        EmailAddress = new EmailAddress
                        {
                            Name = "User2",
                            Address = "user2@test.onmicrosoft.com",
                        },
                    },
                    new AttendeeBase
                    {
                        EmailAddress = new EmailAddress
                        {
                            Name = "User3",
                            Address = "user3@test.onmicrosoft.com",
                        },
                    },
                },
                // 可选:添加时间约束,避免因缺少必要参数导致的额外错误
                TimeConstraint = new TimeConstraint
                {
                    Timeslots = new List<TimeSlot>
                    {
                        new TimeSlot
                        {
                            Start = new DateTimeTimeZone
                            {
                                DateTime = DateTime.UtcNow.AddDays(1).ToString("yyyy-MM-ddTHH:mm:ss"),
                                TimeZone = "UTC"
                            },
                            End = new DateTimeTimeZone
                            {
                                DateTime = DateTime.UtcNow.AddDays(1).AddHours(1).ToString("yyyy-MM-ddTHH:mm:ss"),
                                TimeZone = "UTC"
                            }
                        }
                    }
                }
            };
            try {
                var result = await graphClient.Users[userId].FindMeetingTimes.PostAsync(requestBody);
                return new OkObjectResult(result);
            } catch (Exception e) {
                _logger.LogError(e, "调用FindMeetingTimes失败");
                return new BadRequestObjectResult(new { Error = e.Message, StackTrace = e.StackTrace });
           }
        }
    }
}

额外注意事项

  • 确保Azure AD应用已授予Calendars.Read.Shared或更高权限,且已获得管理员同意;
  • 验证userId是目标用户的正确Object ID(而非用户主体名称);
  • 若参会者包含外部用户,需确保租户允许外部日历访问。

内容的提问来源于stack exchange,提问作者takaaki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:34:58