how to collect all servers meeting criteria into email message??

This topic contains 3 replies, has 3 voices, and was last updated by  tommls 4 weeks, 1 day ago.

  • Author
    Posts
  • #82507

    tommls
    Participant

    Hello, I am modifying this script, I know it is reading the array properly, but it is not putting all the array values into the email body, only the very last array value, corresponding to x8.

    How do I fix the foreach or subsequent code such that all the table rows created by the foreach are written / appended into the $HTMLmessage variable, which becomes the email body — such that in this example, there's four rows contained in the $HTMLmessage variable after the foreach loop finishes??

    # Set free disk space threshold below in percent (default at 10%)
    # use 15% for testing
    [decimal]$thresholdspace = 15
    
    $servers = @('x5','x6','x7','x8') # list of servers to report
    
    foreach ($server in $servers) {
    
    # assemble free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above
    $tableFragment= Get-WMIObject  -ComputerName $computer Win32_LogicalDisk `
    | select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
    | Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `
    | ConvertTo-HTML -fragment
    
    # assemble the HTML for our body of the email report.
    $HTMLmessage = @"
    
    Disk Space Storage Report
    This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed.
    
    body{font: .8em ""Lucida Grande"", Tahoma, Arial, Helvetica, sans-serif;}
    ol{margin:0;padding: 0 1.5em;}
    table{color:#FFF;background:#C00;border-collapse:collapse;width:647px;border:5px solid #900;}
    thead{}
    thead th{padding:1em 1em .5em;border-bottom:1px dotted #FFF;font-size:120%;text-align:left;}
    thead tr{}
    td{padding:.5em 1em;}
    tfoot{}
    tfoot td{padding-bottom:1.5em;}
    tfoot tr{}
    #middle{background-color:#900;}
    
    
    $tableFragment
    
    "@ 
     
    } #end foreach
    
    # Set up a regex search and match to look for any  tags in our body. These would only be present if the script above found disks below the threshold of free space.
    # We use this regex matching method to determine whether or not we should send the email and report.
    $regexsubject = $HTMLmessage
    $regex = [regex] '(?im)'
     
    # if there was any row at all, send the email
    if ($regex.IsMatch($regexsubject)) {
                            send-mailmessage -from $fromemail -to $users -subject "Disk Space Monitoring Report" -BodyAsHTML -body $HTMLmessage -priority High -smtpServer $mailserver
    }
    

    I know the foreach does work properly b/c I put in a write-host to output the foreach lines.

    Thank you, Tom

  • #82522

    Matt Howard
    Participant

    It is only showing the last value due to the fact that the $HTMLMessage is overwritten as it loops through the servers. You will need to split your HTML body into at least two parts and join/concatenate the pieces together back into one variable.

    Something like this:

    $HTMLMessage = @"
    # Put the non-server specific pieces here
    "@
    
    foreach ($server in $servers) {
    # Put the individual server fragment(s) here
    # Then join with $HTMLMessage using += or -join, etc
    }
    
    # Rest of your code out here
    
  • #82525

    James Petty
    Participant

    Tom,
    I have made a few changes to your script and it is working like I think you have intended it. From what I can tell your $tableFragment is not an array. That is why you are only getting the last element in your email.

    Also, the $computerName on line 11 doesn't correspond to anything, i have changed that to $server.
    Your CSS should be outside the foreach loop as it only needs to be applied once. I am not a web developer and have never been able to get inline CSS to work. I have broken that out into its own hearstring ($css starting on line 9). I also added a email Tile as well as a Header to the HTML so that we can apply the CSS that you were wanting.

    # Set free disk space threshold below in percent (default at 10%)
    # use 15% for testing
    [decimal]$thresholdspace = 15
    
    $servers = #YOUR LIST OF SERVERS # list of servers to report
    $tableFragment = @()
    
    #CSS to Different Hear String for easy maintenance as well to keep things portable
    $css = @"
    
    body{font: .8em ""Lucida Grande"", Tahoma, Arial, Helvetica, sans-serif;}
    ol{margin:0;padding: 0 1.5em;}
    table{color:#FFF;background:#C00;border-collapse:collapse;width:647px;border:5px solid #900;}
    thead{}
    thead th{padding:1em 1em .5em;border-bottom:1px dotted #FFF;font-size:120%;text-align:left;}
    thead tr{}
    td{padding:.5em 1em;}
    tfoot{}
    tfoot td{padding-bottom:1.5em;}
    tfoot tr{}
    middle{background-color:#900;}
    
    "@
    
    #adding Details so we can add a CSS header
    $HTMLDetails = @{
        Title = "Email Alert"
        Head = $CSS
        }
    
    foreach ($server in $servers) {
    
    # assemble free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above
    $tableFragment += Get-WMIObject  -ComputerName $server Win32_LogicalDisk `
    | select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
    | Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `
    } #end foreach
    
    
    # assemble the HTML for our body of the email report.
    $HTMLmessage = @"
    Disk Space Storage Report
    This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed.
    
    $($tableFragment | ConvertTo-Html @HTMLDetails)
    "@ 
    
    
    # Set up a regex search and match to look for any  tags in our body. These would only be present if the script above found disks below the threshold of free space.
    # We use this regex matching method to determine whether or not we should send the email and report.
    $regexsubject = $HTMLmessage
    $regex = [regex] '(?im)'
     
    # if there was any row at all, send the email
    if ($regex.IsMatch($regexsubject)) {
                            send-mailmessage -from 'test@test.com' -to 'test@testing.com' -subject "Disk Space Monitoring Report" -body $HTMLmessage -BodyAsHtml -priority High -smtpServer test.smtp.com
    }
    

    Next we made $tableFragment an Array to collect all of our data and applied our HTML Heading and CSS in the $HTMLMessage (See line 45).

    NOTE I did not make any modiciations to the actual meat of the script, just fixed your Array, HTML, CSS problem.

  • #82534

    tommls
    Participant

    Hello everyone,

    I used all the best suggestions and after awhile I got it working as follows.
    It works well enough for now.
    Next project is to find a way to retrieve all running servers and throw their names into an array so I don't have to update the server list, I don't know how easy or difficult that is.
    Original source: https://www.red-gate.com/simple-talk/sysadmin/powershell/disk-space-monitoring-and-early-warning-with-powershell/, plus modifications & assistance from people here.
    Thank you, Tom

    # Set free disk space threshold below in percent (default at 10%)
    [decimal]$thresholdspace = 10
    
    # list of servers to report
    $servers = @('x5','x6','x7','x8')
    
    $HTMLmessage = "
    Disk Space Monitoring Report
    This report shows only servers with drives having less than $thresholdspace% free space. Drives above this threshold are not listed. Not every server reported needs immediate attention. Anything <5 GB for C: drive should be remedied in a timely manner.
    
    body{font: .8em Arial, Helvetica, sans-serif;}
    ol{margin:0;padding: 0 1.5em;}
    table{border-collapse:collapse;width:700px;border:1px solid;margin-bottom:1em;}
    thead{}
    thead th{padding:1em 1em .5em;font-size:120%;text-align:left;}
    thead tr{}
    td{padding:.5em 1em;}
    tfoot{}
    tfoot td{padding-bottom:1em;}
    tfoot tr{}
    
    
    "
    
    # zero out this string variable
    $tableFragment = ""
    
    foreach ($server in $servers) {
    # assemble free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above
    # assemble fragments together for email report
    $tableFragment += Get-WMIObject  -ComputerName $server Win32_LogicalDisk `
    | select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
    | Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `
    | ConvertTo-HTML -fragment
    }
    
    # final report data
    $HTMLmessage +=$tableFragment
    
    # set up regex search and match to look for any  tags in $HTMLmessage body, they will only be present if the script above found disks below the threshold of free space
    # use this regex matching method to determine whether or not we should send the email and report
    $regexsubject = $HTMLmessage
    $regex = [regex] '(?im)'
     
    # if there is any row at all, send email
    if ($regex.IsMatch($regexsubject)) {
       send-mailmessage -from $fromemail -to $users -subject "Disk Space Monitoring Report" -BodyAsHTML -body $HTMLmessage -priority High -smtpServer $mailserver
    }
    

You must be logged in to reply to this topic.