通过电子邮件发送附加字符串的最佳做法?

时间:2015-08-07 18:53:34

标签: powershell

我有一个Powershell脚本可以自动执行流程并通过电子邮件发送报告。

Send-MailMessage -To $toAddress -From "no-reply@domain.org" -subject "Automation status" -body $bodystr -SmtpServer SERVER1 -EA Stop

所以$bodystr本质上是整个脚本中的附加字符串,用于报告发生的事情并且有多行。比如:

$bodystr = $bodystr + "Line found: 305`n"
$bodystr = $bodystr + "Moving line 305 to 574`n"

Send-MailMessage命令位于任何函数之外的脚本底部。但是大多数其他代码都有各种不同的功能。

问题是$bodystr似乎无法在函数内部访问,因此电子邮件缺少大量信息。

我相信我可以使用Set-Variable或传递参数,但是有太多的参数似乎离每个函数添加一个新参数只是为了保持字符串更新的最佳实践。

处理此问题的最佳做法是什么?

1 个答案:

答案 0 :(得分:3)

作为一般规则,不要将数据写回函数范围之外的变量。

如果您是通过从多个来源收集数据来编译电子邮件,请将其抽象为多个函数,每个函数执行一项操作,并让它们返回带有相关输出的多行字符串。

在脚本结束时,收集不同的邮件正文部分,并在发送之前将它们连接到单个字符串。

在这个例子中,我们有一个脚本,它接受一个日志文件的路径,定义一个从日志文件中提取错误的函数,并发送一个包含正文错误的电子邮件:

param(
    [ValidateScript({Test-Path $_ -PathType Leaf })]
    [string]$LogPath = 'C:\Path\To\File.log',
    [string]$From    = 'noreply@company.example',
    [string]$To      = @('ceo@company.example','finance@company.example'),
    [string]$Subject = 'Super Important Weekly Report',
    [string]$SmtpServer = $PSEmailServer,
    [string]$Credential
)

# Define functions with a straight forward purpose 
# e.g. Searching a logfile for errors
function Parse-Logfile {
    param($LogPath)

    [string[]]$LogErrors = @()

    Get-Content $LogPath |ForEach-Object{
        if($_ -contains $Error){
             $LogErrors += $_
        }
    }

    # Create and return a custom object has the error details as properties
    New-Object psobject -Property @{
        ErrorCount  = $LogErrors.Count
        Errors = $LogErrors
    }
}

# Create a email template that's easy to maintain
# You could store this in a file and add a $TemplateFile parameter to the script ;-)
$EmailTemplate = @'
Hi there!

Found {0} errors in log file: {1}
{2}

Regards
Zeno
'@

# Use your function(s) to create and gather the details you need
$ErrorReport = Parse-Logfile -LogPath $LogPath

# If necessary, concatenate strings with -join
$ErrorString = $ErrorReport.Errors -join "`n"

# Use the format operator to the final Body string
$Body = $EmailTemplate -f $ErrorReport.ErrorCount, $LogPath, $ErrorString

# Set up a splatting table (Get-Help about_Splatting)
$MailParams = @{
    To         = $To
    From       = $From
    Subject    = $Subject
    Body       = $Body
    SmtpServer = $SmtpServer
}

if($PSBoundParameters.ContainsKey('Credential')){
    $MailParams['Credential'] = $Credential
}

# Send mail
Send-MailMessage @MailParams