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

PowerShell通过OAuth2向Exchange Online发送认证邮件失败求助

问题排查与解决方案

核心问题定位

你遇到的Authentication failed: * BYE Connection is closed. 13错误,核心原因是权限配置不匹配:当前仅配置了IMAP.AccessAsApp权限,该权限仅用于接收邮件,无法支持发送邮件操作,导致Exchange服务器拒绝后续连接。

分步修正方案

1. 修正应用权限配置

登录Azure AD门户,找到MyApp应用,添加对应发送邮件的应用权限并完成租户授权:

  • 若使用SMTP协议发送:添加Office 365 Exchange Online > SMTP.SendAsApp(应用权限)
  • 若改用Microsoft Graph API发送(更推荐,无需处理复杂的SMTP连接逻辑):添加Microsoft Graph > Mail.Send(应用权限)

2. 调整令牌获取逻辑

获取OAuth2令牌时,scope参数必须匹配你使用的服务:

  • 针对Exchange Online SMTP:scope设为https://outlook.office365.com/.default
  • 针对Microsoft Graph API:scope设为https://graph.microsoft.com/.default

示例令牌获取代码:

$tenantId = "你的租户ID"
$clientId = "MyApp的客户端ID"
$clientSecret = "MyApp的密钥"

$tokenUri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body = @{
    grant_type    = "client_credentials"
    client_id     = $clientId
    client_secret = $clientSecret
    scope         = "https://outlook.office365.com/.default" # 按需替换为Graph的scope
}

$tokenResponse = Invoke-RestMethod -Uri $tokenUri -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$accessToken = $tokenResponse.access_token

3. 发送邮件的两种实现方式

方式一:SMTP+OAuth2发送

$smtpServer = "smtp.office365.com"
$smtpPort = 587
$fromAddress = "你的邮箱地址"
$toAddress = "你的邮箱地址"

$mailMessage = New-Object System.Net.Mail.MailMessage($fromAddress, $toAddress)
$mailMessage.Subject = "OAuth2测试通知邮件"
$mailMessage.Body = "这是通过SMTP+OAuth2发送的测试内容"

$smtpClient = New-Object System.Net.Mail.SmtpClient($smtpServer, $smtpPort)
$smtpClient.EnableSsl = $true
$smtpClient.Credentials = New-Object System.Net.NetworkCredential($fromAddress, $accessToken)

try {
    $smtpClient.Send($mailMessage)
    Write-Host "邮件发送成功"
} catch {
    Write-Error "发送失败: $_"
}

方式二:Microsoft Graph API发送(更简洁)

$graphApiUri = "https://graph.microsoft.com/v1.0/users/你的邮箱地址/sendMail"
$mailPayload = @{
    message = @{
        subject = "Graph API测试通知邮件"
        body = @{
            contentType = "Text"
            content = "这是通过Graph API发送的测试内容"
        }
        toRecipients = @(
            @{
                emailAddress = @{ address = "你的邮箱地址" }
            }
        )
    }
    saveToSentItems = $true
} | ConvertTo-Json

Invoke-RestMethod -Uri $graphApiUri -Method Post -Headers @{Authorization = "Bearer $accessToken"} -Body $mailPayload -ContentType "application/json"
Write-Host "邮件发送成功"

4. 额外验证点

  • 确认已为MyApp服务主体授予目标邮箱的FullAccess权限(你之前的操作已完成,无需重复)
  • 可通过本地JWT解码工具验证获取的access_token,确认其包含对应发送权限的声明

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:39:57