Azure Runbook执行PowerShell发邮件报415 Unsupported Media Type错误
解决Azure Runbook中SendGrid发送HTML邮件报415 Unsupported Media Type的问题
你的问题核心是本地PowerShell运行正常,但Azure自动化Runbook中发送带链接的HTML邮件时返回415 Unsupported Media Type错误,移除HTML中的链接后脚本即可正常执行,这说明问题出在HTML内容格式或请求体的处理逻辑上。以下是具体的排查和修复方案:
1. 修复HTML链接的引号缺失问题
你当前的HTML链接写法没有给href属性值加双引号:
<p><a href=$Link1>Link 1</a></p>
这种写法在PowerShell Here-String中替换变量后,会生成href=http://www.google.com的不规范HTML代码,不仅不符合HTML标准,还会在转成JSON时引发意外的转义问题,被SendGrid API判定为非法请求体。
修改为标准带双引号的写法:
<p><a href="$Link1">Link 1</a></p> <p><a href="$Link2">Link 2</a></p> <p><a href="$Link3">Link 3</a></p> <p><a href="$LienBlob">Blob Portal Link</a></p>
2. 移除多余的HTTP请求头
你的脚本中添加了Content-transfer-encoding头,但SendGrid v3 API并不需要这个头,多余的请求头会干扰API对请求媒体类型的判断,进而触发415错误。
删除headers中的这一行:
'Content-transfer-encoding' = 'quoted-printable'
只保留必要的授权和内容类型头:
$headers = @{ 'Authorization' = 'Bearer ' + $apiKey 'Content-Type' = 'application/json' }
3. 显式指定Invoke-RestMethod的ContentType参数
即使请求头中已经设置了Content-Type,在Azure Runbook的PowerShell环境中,显式给Invoke-RestMethod添加-ContentType 'application/json'参数可以避免环境差异导致的媒体类型识别问题,双重保险确保请求格式正确:
Invoke-RestMethod -Uri https://api.sendgrid.com/v3/mail/send ` -Method Post ` -Headers $headers ` -Body $bodyJson ` -ContentType 'application/json'
4. 完整修正后的关键代码片段
修正后的HTML邮件体:
$htmlBody = @" <table> <tr> <td align="left"> <p>Hello,</p> <p>Test message</p> <p><a href="$Link1">Link 1</a></p> <p><a href="$Link2">Link 2</a></p> <p><a href="$Link3">Link 3</a></p> <p><a href="$LienBlob">Blob Portal Link</a></p> <p>Thank you,<br /><font size="-1"><i>Automatic message. Please do not reply.</i></font></p> </td> </tr> </table> "@
修正后的请求头与API调用部分:
$headers = @{ 'Authorization' = 'Bearer ' + $apiKey 'Content-Type' = 'application/json' } try { $bodyJson = $body | ConvertTo-Json -Depth 4 Write-Host "Generated JSON request body: $bodyJson" } catch { $ErrorMessage = $_.Exception.message write-error ('Error converting body to json ' + $ErrorMessage) Break } try { Invoke-RestMethod -Uri https://api.sendgrid.com/v3/mail/send ` -Method Post ` -Headers $headers ` -Body $bodyJson ` -ContentType 'application/json' } catch { # 保留原有的异常处理逻辑 $ErrorMessage = $_.Exception.message write-error ('Error with Invoke-RestMethod ' + $ErrorMessage) echo '### Inside catch ###' $ErrorMessage = $_.Exception.Message echo '## ErrorMessage ##' $ErrorMessage $FailedItem = $_.Exception.ItemName echo '## FailedItem ##' $FailedItem $result = $_.Exception.Response.GetResponseStream() echo '## result2 ##' $result $reader = New-Object System.IO.StreamReader($result) echo '## reader ##' $reader $responseBody = $reader.ReadToEnd(); echo '## responseBody ##' $responseBody Break }
问题根源总结
- 未加引号的链接导致HTML格式不合法,转JSON后产生语法错误,被SendGrid API拒绝。
- 多余的
Content-transfer-encoding头干扰了API对请求媒体类型的判断,触发415错误。 - Azure Runbook的PowerShell环境与本地存在细微差异,显式指定ContentType参数可以避免格式识别偏差。
内容的提问来源于stack exchange,提问作者mwa
相关产品推荐
相关产品推荐

