使用MS Graph API从VBA发送邮件时遇400错误请求问题
问题分析与解决方案
错误原因
你遇到的400 错误请求是因为**/me端点仅支持委派身份验证流**,而你在VBA中使用的是客户端凭据流(通过Client ID+Client Secret获取令牌),这种流属于应用权限模式——应用本身拥有独立权限,无法用/me指代当前用户,必须明确指定要操作的用户账户。
解决步骤
1. 确认应用权限配置
确保你的Azure Entra ID应用已配置应用权限类型的Mail.Send权限,且已获得管理员同意:
- 进入Azure Entra ID应用的「API权限」页面
- 添加权限 → Microsoft Graph → 应用权限 → 搜索
Mail.Send并勾选 - 点击「授予管理员同意」(需要全局管理员或Exchange管理员权限)
2. 修改Graph API请求路径
将原来的/me/sendMail替换为/users/{目标用户邮箱或用户ID}/sendMail,比如目标邮箱是sender@yourdomain.com,则路径为/users/sender@yourdomain.com/sendMail。
3. VBA代码示例
以下是完整的VBA实现逻辑,包含令牌获取与邮件发送:
Sub SendMailWithGraphAPI() Dim tenantId As String Dim clientId As String Dim clientSecret As String Dim senderEmail As String Dim token As String Dim httpObj As Object ' 替换为你的实际信息 tenantId = "你的Tenant ID" clientId = "你的Client ID" clientSecret = "你的Client Secret" senderEmail = "发件人邮箱@你的域名.com" ' 1. 获取应用访问令牌 Set httpObj = CreateObject("MSXML2.XMLHTTP") httpObj.Open "POST", "https://login.microsoftonline.com/" & tenantId & "/oauth2/v2.0/token", False httpObj.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" httpObj.Send "grant_type=client_credentials&client_id=" & clientId & "&client_secret=" & clientSecret & "&scope=https://graph.microsoft.com/.default" ' 解析令牌 token = Split(Split(httpObj.responseText, """access_token"":""")(1), """")(0) ' 2. 构造邮件请求并发送 Dim mailPayload As String mailPayload = "{""message"": {" & _ """subject"": ""VBA测试邮件""," & _ """body"": {" & _ """contentType"": ""Text""," & _ """content"": ""这是通过Graph API从Word VBA发送的邮件。""}" & _ ",""toRecipients"": [{" & _ """emailAddress"": {" & _ """address"": ""收件人邮箱@example.com""" & _ "}" & _ "}]}" & _ "},""saveToSentItems"": true}" httpObj.Open "POST", "https://graph.microsoft.com/v1.0/users/" & senderEmail & "/sendMail", False httpObj.setRequestHeader "Authorization", "Bearer " & token httpObj.setRequestHeader "Content-Type", "application/json" httpObj.Send mailPayload ' 处理响应结果 If httpObj.Status = 202 Then MsgBox "邮件发送成功!" Else MsgBox "发送失败:" & vbCrLf & "状态码:" & httpObj.Status & vbCrLf & "详情:" & httpObj.responseText End If Set httpObj = Nothing End Sub
注意事项
- 确保VBA项目已启用「Microsoft XML, v6.0」引用(VBA编辑器→工具→引用→勾选对应选项)
- 发件人邮箱必须是当前租户内的有效用户,应用的
Mail.Send权限允许代表该用户发送邮件 - 若仍有权限报错,再次确认应用权限已添加并完成管理员同意操作
内容的提问来源于stack exchange,提问作者East Anglian Sailing Trust
相关产品推荐
相关产品推荐

