使用Outlook SMTP与应用密码的PowerShell Send-MailMessage失效求助
解决Outlook.com禁用基础认证后的PowerShell邮件通知问题
问题根源
Send-MailMessage cmdlet仅支持基础认证,而微软已全面禁用outlook.com的SMTP基础认证。你尝试的"应用密码"仅适用于本身支持现代认证但需适配旧设备的场景,并非用来给仅支持基础认证的工具绕过限制,因此无法解决问题。
解决方案
方案一:使用Microsoft Graph PowerShell模块(官方推荐)
这是微软官方支持的现代认证方案,无需依赖SMTP基础认证,步骤如下:
- 安装Microsoft Graph模块(仅需运行一次):
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force
- 首次运行授权(弹出浏览器登录你的Outlook账户,授予邮件发送权限,凭据会自动保存到本地):
Connect-MgGraph -Scopes "Mail.Send"
- 编写无人值守邮件脚本:
# 导入模块 Import-Module Microsoft.Graph.Mail # 配置邮件内容 $mailParams = @{ Message = @{ Subject = "PC rebooted" Body = @{ ContentType = "Text" Content = "PC has rebooted" } ToRecipients = @( @{ EmailAddress = @{ Address = "NN@outlook.com" } } ) } SaveToSentItems = $true } # 发送邮件 Send-MgUserMail -UserId "NN@outlook.com" -BodyParameter $mailParams
该脚本在无人值守环境下,会自动使用之前保存的授权凭据完成认证,无需手动输入密码。
方案二:使用.NET SmtpClient结合OAuth2(无需安装模块)
适合不想额外安装PowerShell模块的场景,需要先注册Azure AD公共客户端应用:
- 注册Azure AD公共客户端应用:
- 登录Azure管理平台,搜索"应用注册"服务
- 点击"新注册",填写自定义名称,支持账户类型选择"任何组织目录中的账户和个人Microsoft账户"
- 重定向URI选择"公共客户端/本机"类型,填写
http://localhost - 完成注册后,复制页面上的"应用程序(客户端)ID",这就是脚本中需要的
clientId
- 编写脚本:
# 配置参数 $clientId = "你的Azure应用ID" $tenantId = "consumers" # 个人Outlook账户固定填这个 $scopes = "https://outlook.office.com/SMTP.Send" $smtpServer = "smtp.office365.com" $smtpPort = 587 $fromAddr = "NN@outlook.com" $toAddr = "NN@outlook.com" # 获取OAuth2令牌(首次运行需按提示在浏览器完成授权) $deviceCodeReq = @{ client_id = $clientId; scope = $scopes } $deviceCodeResp = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/devicecode" -Method Post -Body $deviceCodeReq Write-Host "请在浏览器打开提示链接并输入代码:`n$($deviceCodeResp.message)" $tokenReq = @{ client_id = $clientId grant_type = "urn:ietf:params:oauth:grant-type:device_code" device_code = $deviceCodeResp.device_code } do { Start-Sleep -Seconds $deviceCodeResp.interval try { $tokenResp = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Method Post -Body $tokenReq break } catch { $err = $_.ErrorDetails.Message | ConvertFrom-Json if ($err.error -ne "authorization_pending") { throw $err.error_description } } } while ($true) # 发送邮件 $mail = New-Object System.Net.Mail.MailMessage($fromAddr, $toAddr) $mail.Subject = "PC rebooted" $mail.Body = "PC has rebooted" $smtp = New-Object System.Net.Mail.SmtpClient($smtpServer, $smtpPort) $smtp.EnableSsl = $true $smtp.UseDefaultCredentials = $false $smtp.Credentials = New-Object System.Net.NetworkCredential($fromAddr, $tokenResp.access_token) $smtp.Send($mail)
首次运行脚本会提示你在浏览器完成授权,后续无人值守运行时可自动复用令牌(令牌过期会自动刷新)。
内容的提问来源于stack exchange,提问作者ChrisHD
相关产品推荐
相关产品推荐

