Azure自动化账户RunBook发送带附件邮件报错求助
问题描述
在Azure自动化账户中创建RunBook,通过Azure Resource Graph查询资源并导出为CSV文件发送邮件时,出现以下错误:
System.Management.Automation.RuntimeException: You cannot call a method on a null-valued expression.
at CallSite.Target(Closure , CallSite , Object , String )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
RunBook代码如下:
$IdentityAccountID = Get-AutomationVariable -Name "IdentityName" Connect-AzAccount -Identity -AccountId $IdentityAccountID -Tenant "<tenantName>" -SubscriptionId "1234-1234-1234-1234-1234" $query = @" resources | where type in ( 'microsoft.sql/servers/databases', 'microsoft.web/serverfarms' ) | join kind=inner ( resourcecontainers | where type =~ 'microsoft.resources/subscriptions' | project subscriptionId, subscriptionName=name ) on subscriptionId | where subscriptionId in ( '1234-1234-1234-1234-1234', '1234-1234-1234-1234-1234', '1234-1234-1234-1234-1234' ) | where name != 'master' | project subscriptionName, resourceType=type, resourceName=name, sku, resourceGroup | order by subscriptionName, resourceType, resourceName "@ #$csvpath = "$env:TEMP\ResourcesInventory.csv" # Execute the query $result = Search-AzGraph -Query $query $result.Data | Export-Csv -Path "$env:TEMP\ResourcesInventory.csv" -Notype $CredSmtp = Get-AutomationPSCredential -Name "smtpCred" # Sender and Recipient Info $MailFrom = "no-reply@email.com" $MailTo = "reciever@email.com" # Sender Credentials $Username = $CredSmtp.UserName $Password = $CredSmtp.GetNetworkCredential().Password $SmtpServer = "smtp.sendgrid.net" $SmtpPort = "587" # configure message $Message.Attachments.Add("$env:TEMP\ResourcesInventory.csv") $MessageSubject = "Azure resources Inventory Report" $Message = New-Object System.Net.Mail.MailMessage $MailFrom, $MailTo $Message.IsBodyHTML = $true $Message.Subject = $MessageSubject $Message.Body = @' <!DOCTYPE html> <html> <head> </head> <body> Hello, <p>Please Find attached the resources inventory report regarding the subscriptions assigned to you </p> Regards </body> </html> '@ # Construct the SMTP client object, credentials, and send $Smtp = New-Object Net.Mail.SmtpClient($SmtpServer,$SmtpPort) $Smtp.EnableSsl = $true $Smtp.Credentials = New-Object System.Net.NetworkCredential($Username,$Password) $Smtp.Send($Message)
问题原因及修复方案
1. 邮件对象初始化顺序错误
报错的直接原因是代码先调用$Message.Attachments.Add(),但此时$Message变量还未创建,属于对Null对象调用方法。
修复:
调整代码顺序,先创建$Message对象,再添加附件:
# configure message $MessageSubject = "Azure resources Inventory Report" $Message = New-Object System.Net.Mail.MailMessage $MailFrom, $MailTo # 先创建对象,再添加附件 $Message.Attachments.Add("$env:TEMP\ResourcesInventory.csv") $Message.IsBodyHTML = $true $Message.Subject = $MessageSubject $Message.Body = @' <!DOCTYPE html> <html> <head> </head> <body> Hello, <p>Please Find attached the resources inventory report regarding the subscriptions assigned to you </p> Regards </body> </html> '@
2. 处理查询结果为空的情况
如果Search-AzGraph返回无数据,$result.Data会是Null,执行Export-Csv时会触发报错,需要添加空值判断:
修复:
$result = Search-AzGraph -Query $query if ($result.Data) { $result.Data | Export-Csv -Path "$env:TEMP\ResourcesInventory.csv" -NoTypeInformation } else { Write-Output "No resources found from the query." # 可选:修改邮件内容说明无数据 }
3. 验证自动化资源配置
- 确认自动化账户中已创建名为
IdentityName的变量,值正确对应托管标识的ID - 确认名为
smtpCred的PS凭据已正确配置,包含有效的SMTP用户名和密码
4. 检查CSV文件存在性
添加文件存在检查,避免附件路径无效的问题:
$csvPath = "$env:TEMP\ResourcesInventory.csv" if (Test-Path $csvPath) { $Message.Attachments.Add($csvPath) } else { $Message.Body = $Message.Body.Replace("Please Find attached", "No resources report available (no data found)") }
内容的提问来源于stack exchange,提问作者Brayhan Castro

