使用Microsoft Graph API发送邮件遇权限及请求错误求助
调用Microsoft Graph API发送邮件时的权限与请求问题
我尝试用以下C#代码调用Microsoft Graph API发送邮件:
public static async Task SendEmailWithMicrosoftGraph() { // Set up the Microsoft Graph API endpoint and version string graphApiEndpoint = "https://graph.microsoft.com/v1.0"; // Set up the client application ID and secret string clientId = "CLIENT_ID_GOES_HERE"; string clientSecret = "CLIENT_SECRET_GOES_HERE"; string tenantId = "TENANT_ID_GOES_HERE"; // Set up the user's email address and message content string userEmail = "MY_EMAIL_HERE"; string messageSubject = "Test email"; string messageBody = "This is a test email sent via Microsoft Graph"; // Set up the authentication context and acquire a token var authBuilder = ConfidentialClientApplicationBuilder.Create(clientId) .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0") .WithClientSecret(clientSecret) .Build(); var authResult = await authBuilder.AcquireTokenForClient(new [] { "https://graph.microsoft.com/.default" }) .ExecuteAsync(); // Set up the HTTP client and add the access token to the authorization header var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); // Set up the email message var emailMessage = new { message = new { subject = messageSubject, body = new { contentType = "Text", content = messageBody }, toRecipients = new [] { new { emailAddress = new { address = userEmail } } } } }; // Convert the email message to a JSON string and send the email via Microsoft Graph var jsonMessage = JsonConvert.SerializeObject(emailMessage); var response = await httpClient.PostAsync($"{graphApiEndpoint}/users/{userEmail}/sendMail", new StringContent(jsonMessage, System.Text.Encoding.UTF8, "application/json")); if (response.IsSuccessStatusCode) { Console.WriteLine("Email sent successfully."); } else { Console.WriteLine("Failed to send email. Status code: " + response.StatusCode); } }
执行后返回response.StatusCode为FORBIDDEN。我已完成应用注册、创建客户端密钥,并配置了Mail.Send应用权限,不清楚遗漏了什么。
补充:我尝试将请求行从
var response = await httpClient.PostAsync($"{graphApiEndpoint}/users/{userEmail}/sendMail", new StringContent(jsonMessage, System.Text.Encoding.UTF8, "application/json"));
改为
var response = await httpClient.PostAsync($"{graphApiEndpoint}/me/sendMail", new StringContent(jsonMessage, System.Text.Encoding.UTF8, "application/json"));
现在错误变为Bad Request。根据文档,该错误仅在请求体包含格式错误的MIME内容时出现,但我使用的是application/json内容类型,请问该如何解决?
解决方法
针对FORBIDDEN错误的修复
确认权限已授予管理员同意
应用权限(如Mail.Send)需要租户管理员的明确同意才能生效。即使在应用注册页面添加了权限,若未点击授予管理员同意按钮,权限仍处于未激活状态。进入Azure门户的应用注册页面,找到权限配置区域,确认已完成管理员同意操作。验证请求路径的正确性
使用应用权限(客户端凭证流)时,必须使用/users/{userPrincipalName}/sendMail路径,不能用/me/sendMail——后者仅适用于用户登录的委托权限流,而客户端凭证流没有当前用户上下文,/me无法被解析。
针对Bad Request错误的说明
切换到/me/sendMail后出现Bad Request,本质是因为客户端凭证流无法使用/me端点。该端点需要用户上下文,而当前获取的是应用级别的token,没有关联具体用户,因此请求会被判定为格式无效(实际是上下文缺失导致的解析失败)。
额外优化建议
- 使用Microsoft Graph SDK替代原生HttpClient
直接调用Graph SDK可以避免手动构造JSON和处理HTTP请求的细节,减少出错概率。示例代码如下:var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); })); await graphClient.Users[userEmail].SendMail(emailMessage.message, saveToSentItems: true).Request().PostAsync(); - 检查用户邮箱的有效性
确保userEmail是租户内存在的有效用户主体名称(UPN),而非别名或其他格式的邮箱地址。
内容的提问来源于stack exchange,提问作者Michael S. Miller
相关产品推荐
相关产品推荐

