Latest Post

 Below is the Disk information. 

<#
.SYNOPSIS
Collects drive space details from a list of Windows servers and emails an HTML report.
#>

# ---- CONFIG ----
$serverListPath = "C:\Scripts\servers.txt"

$servers = Get-Content $serverListPath |
           Where-Object { $_.Trim() -ne "" }

$smtpServer    = "smtp.yourcompany.com"
$from          = "monitoring@yourcompany.com"
$to            = "you@yourcompany.com"
$subject       = "Windows Servers - Drive Space Report - $(Get-Date -Format 'yyyy-MM-dd')"
$freeThreshold = 20   # percent free below which status = Check Now

# ---- COLLECT DATA ----
$results = foreach ($server in $servers) {
    try {
        $disks = Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName $server -Filter "DriveType=3" -ErrorAction Stop

        foreach ($disk in $disks) {
            $sizeGB    = [math]::Round($disk.Size / 1GB, 2)
            $freeGB    = [math]::Round($disk.FreeSpace / 1GB, 2)
            $usedGB    = [math]::Round($sizeGB - $freeGB, 2)
            $pctFree   = if ($sizeGB -gt 0) { [math]::Round(($freeGB / $sizeGB) * 100, 1) } else { 0 }
            $status    = if ($pctFree -lt $freeThreshold) { "Check Now" } else { "Healthy" }

            [PSCustomObject]@{
                Server      = $server
                DeviceID    = $disk.DeviceID
                SizeGB      = $sizeGB
                UsedGB      = $usedGB
                FreeGB      = $freeGB
                PercentFree = $pctFree
                Status      = $status
            }
        }
    }
    catch {
        [PSCustomObject]@{
            Server      = $server
            DeviceID    = "-"
            SizeGB      = $null
            UsedGB      = $null
            FreeGB      = $null
            PercentFree = $null
            Status      = "Server not reachable"
        }
    }
}

# ---- BUILD HTML OUTPUT WITH INLINE STYLES ----
$rows = foreach ($r in $results) {

    $statusStyle = switch ($r.Status) {
        "Healthy"              { "color: #2e7d32; font-weight: bold;" }
        "Check Now"            { "color: #c62828; font-weight: bold;" }
        "Server not reachable" { "color: #c62828; font-weight: bold; background-color: #ffebee;" }
        default                { "" }
    }

    "<tr>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.Server)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.DeviceID)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.SizeGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.UsedGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.FreeGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.PercentFree)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; $statusStyle'>$($r.Status)</td>
    </tr>"
}

$html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body style="margin: 0; padding: 20px; background-color: #f4f6f8; font-family: 'Segoe UI', Arial, sans-serif;">

    <!-- Main Container Table (1100px Width) -->
    <table align="center" width="1100" border="0" cellpadding="0" cellspacing="0" style="width: 1100px; margin: 0 auto;">
        
        <!-- HEADER SECTION (BLUE BACKGROUND) -->
        <tr>
            <td style="background-color: #1e40af; border-radius: 8px; padding: 18px 20px; text-align: center;">
                <h2 style="color: #ffffff; margin: 0; font-size: 18px; font-weight: 600;">
                    Windows Server Drive Space Report - $(Get-Date -Format 'yyyy-MM-dd')
                </h2>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- RESULTS TABLE SECTION -->
        <tr>
            <td align="center">
                <table width="100%" border="0" cellpadding="0" cellspacing="0" style="width: 100%; border-collapse: collapse; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                    <thead>
                        <!-- TABLE HEADER (BLUE BACKGROUND) -->
                        <tr style="background-color: #1e3a8a; color: #ffffff;">
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Server</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">DeviceID</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Size (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Used (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Free (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">% Free</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        $($rows -join "`n")
                    </tbody>
                </table>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SEPARATE AUTOMATED DISCLAIMER BOX -->
        <tr>
            <td style="background-color: #eff6ff; border: 1px solid #bfdbfe; border-left: 4px solid #1e40af; border-radius: 6px; padding: 10px 14px; text-align: center;">
                <span style="font-size: 12px; color: #1e40af; font-weight: 600;">
                    Note: This is an automated report do not reply to this email.
                </span>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SIGNATURE SECTION (BLUE BACKGROUND) -->
        <tr>
            <td style="background-color: #1e40af; border-radius: 8px; padding: 14px 20px; text-align: left;">
                <p style="color: #ffffff; margin: 0; font-size: 13px; line-height: 1.5;">
                    Regards,<br>
                    <strong style="color: #ffffff; font-size: 14px;">SQL DBA Team</strong><br>
                    <span style="color: #dbeafe;">Database Administration</span>
                </p>
            </td>
        </tr>

    </table>

</body>
</html>
"@

# ---- SEND EMAIL ----
Send-MailMessage -From $from -To $to -Subject $subject -Body $html -BodyAsHtml -SmtpServer $smtpServer


 Below is the Backup information. 

# ==========================================
# Configuration Parameters
# ==========================================
$ServerListFile = "C:\Data\Sqlserver.txt"
$SmtpServer     = "smtp.yourcompany.com"
$SmtpPort       = 25
$EmailFrom      = "sqlmonitoring@yourcompany.com"
$EmailTo        = "dba-team@yourcompany.com"
$EmailSubject   = "SQL Backup Monitoring Report - $(Get-Date -Format 'dd-MMM-yyyy')"

$StartTime = Get-Date

# ==========================================
# SQL Query to Fetch Backup History
# ==========================================
$SqlQuery = @"
SELECT 
    d.name AS DatabaseName,
    d.database_id,
    CASE WHEN d.name IN ('master', 'model', 'msdb') THEN 'System DB' ELSE 'User DB' END AS DBType,
    MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) AS LastFullBackup,
    MAX(CASE WHEN b.type = 'I' THEN b.backup_finish_date END) AS LastDiffBackup
FROM sys.databases d
LEFT JOIN msdb.dbo.backupset b ON d.name = b.database_name
WHERE d.name <> 'tempdb' AND d.state_desc = 'ONLINE'
GROUP BY d.name, d.database_id;
"@

# Data Collectors
$ServerResults = @()
$ExceptionList = @()

$TotalServers = 0
$ServersHealthy = 0
$ServersFailed = 0
$ServersUnreachable = 0

if (-not (Test-Path $ServerListFile)) {
    Write-Error "Server list file not found at $ServerListFile"
    exit
}

$SqlServerList = Get-Content $ServerListFile | Where-Object { $_ -and -not $_.StartsWith("#") }

foreach ($ServerInput in $SqlServerList) {
    $ServerInput = $ServerInput.Trim()
    $TotalServers++
    
    $ServerHasIssues = $false
    $ServerExceptionsCount = 0
    $DisplayName = $ServerInput

    try {
        $ConnectionString = "Server=$ServerInput;Database=msdb;Integrated Security=SSPI;Connection Timeout=10;"
        $Connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
        $Connection.Open()

        $CmdInstance = $Connection.CreateCommand()
        $CmdInstance.CommandText = "SELECT @@SERVERNAME AS SqlInstanceName;"
        $DisplayName = $CmdInstance.ExecuteScalar()

        $Command = $Connection.CreateCommand()
        $Command.CommandText = $SqlQuery
        $Adapter = New-Object System.Data.SqlClient.SqlDataAdapter($Command)
        $DataTable = New-Object System.Data.DataTable
        [void]$Adapter.Fill($DataTable)
        $Connection.Close()

        foreach ($Row in $DataTable) {
            $DbName = $Row.DatabaseName
            $DbType = $Row.DBType
            $LastFull = if ($Row.LastFullBackup -ne [DBNull]::Value) { [datetime]$Row.LastFullBackup } else { $null }
            $LastDiff = if ($Row.LastDiffBackup -ne [DBNull]::Value) { [datetime]$Row.LastDiffBackup } else { $null }

            $FullDaysOld = if ($LastFull) { ($StartTime - $LastFull).TotalDays } else { 9999 }
            $DiffHoursOld = if ($LastDiff) { ($StartTime - $LastDiff).TotalHours } else { 9999 }

            $IssueDescription = $null

            if ($DbType -eq 'System DB') {
                if ($FullDaysOld -gt 7) {
                    $IssueDescription = if ($null -eq $LastFull) { "Full backup NEVER performed" } else { "Full backup overdue (> 7 days)" }
                }
            } else {
                if ($FullDaysOld -gt 7 -and $DiffHoursOld -gt 24) {
                    $IssueDescription = "Full (> 7 days) and Differential (> 24 hours) backups overdue"
                } elseif ($FullDaysOld -gt 7) {
                    $IssueDescription = "Full backup overdue (> 7 days)"
                } elseif ($DiffHoursOld -gt 24) {
                    $IssueDescription = "Differential backup overdue (> 24 hours)"
                }
            }

            if ($IssueDescription) {
                $ServerHasIssues = $true
                $ServerExceptionsCount++
                $ExceptionList += [PSCustomObject]@{
                    Server           = $DisplayName
                    Database         = $DbName
                    Type             = $DbType
                    IssueDescription = $IssueDescription
                    LastFull         = if ($LastFull) { $LastFull.ToString("dd-MMM HH:mm") } else { "NEVER" }
                    LastDiff         = if ($DbType -eq 'System DB') { "N/A" } else { if ($LastDiff) { $LastDiff.ToString("dd-MMM HH:mm") } else { "NEVER" } }
                }
            }
        }

        if ($ServerHasIssues) {
            $ServersFailed++
            $ServerResults += [PSCustomObject]@{
                ServerName = $DisplayName
                Status     = "ISSUES FOUND"
                Details    = "<span style='color: #c62828; font-weight: bold;'>$ServerExceptionsCount database(s) failing backup SLA</span>"
            }
        } else {
            $ServersHealthy++
            $ServerResults += [PSCustomObject]@{
                ServerName = $DisplayName
                Status     = "ALL DB'S FINE"
                Details    = "<span style='color: #2e7d32;'>All databases met backup SLAs</span>"
            }
        }

    } catch {
        $ServersUnreachable++
        $ErrorMessage = $_.Exception.Message.Trim()
        $ServerResults += [PSCustomObject]@{
            ServerName = "$ServerInput (Unreachable)"
            Status     = "CHECK FAILED"
            Details    = "<div style='color: #c62828; font-weight: bold;'>Connection / Execution Failure</div><div style='background-color: #ffebee; color: #c62828; font-family: Consolas, monospace; font-size: 12px; padding: 6px 10px; border-left: 3px solid #c62828; margin-top: 4px;'>$ErrorMessage</div>"
        }
    }
}

$EndTime = Get-Date
$Duration = "{0:hh}:{0:mm}:{0:ss}" -f ($EndTime - $StartTime)
$HostName = $env:COMPUTERNAME

# ==========================================
# HTML Email Generation (Matching 1100px Layout)
# ==========================================
$OverviewRows = foreach ($res in $ServerResults) {
    $statusStyle = switch ($res.Status) {
        "ALL DB'S FINE" { "color: #2e7d32; font-weight: bold;" }
        "ISSUES FOUND"  { "color: #c62828; font-weight: bold;" }
        "CHECK FAILED"  { "color: #c62828; font-weight: bold; background-color: #ffebee;" }
    }
    
    "<tr>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'><b>$($res.ServerName)</b></td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; $statusStyle'>$($res.Status)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($res.Details)</td>
    </tr>"
}

$ExceptionSection = ""
if ($ExceptionList.Count -gt 0) {
    $ExRows = foreach ($ex in $ExceptionList) {
        "<tr>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'><b>$($ex.Server)</b></td>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($ex.Database)</td>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($ex.Type)</td>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #c62828; font-weight: bold;'>$($ex.IssueDescription)</td>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($ex.LastFull)</td>
            <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($ex.LastDiff)</td>
        </tr>"
    }

    $ExceptionSection = @"
        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- DATABASE EXCEPTIONS SECTION -->
        <tr>
            <td align="center">
                <table width="100%" border="0" cellpadding="0" cellspacing="0" style="width: 100%; border-collapse: collapse; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                    <thead>
                        <tr style="background-color: #1e40af; color: #ffffff;">
                            <th colspan="6" style="padding: 8px 12px; text-align: left; font-size: 13px; font-weight: 600; background-color: #1e40af;">Database Backup Exceptions</th>
                        </tr>
                        <tr style="background-color: #1e3a8a; color: #ffffff;">
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 18%;">Server</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 18%;">Database</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 12%;">Type</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 34%;">Issue Description</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 9%;">Last Full</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 9%;">Last Diff</th>
                        </tr>
                    </thead>
                    <tbody>
                        $($ExRows -join "`n")
                    </tbody>
                </table>
            </td>
        </tr>
"@
}

$HtmlBody = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body style="margin: 0; padding: 20px; background-color: #f4f6f8; font-family: 'Segoe UI', Arial, sans-serif;">

    <!-- Main Container Table (1100px Width) -->
    <table align="center" width="1100" border="0" cellpadding="0" cellspacing="0" style="width: 1100px; margin: 0 auto;">
        
        <!-- HEADER SECTION (BLUE BACKGROUND) -->
        <tr>
            <td style="background-color: #1e40af; border-radius: 8px; padding: 18px 20px; text-align: center;">
                <h2 style="color: #ffffff; margin: 0; font-size: 18px; font-weight: 600;">
                    SQL Server Backup Monitoring Report - $(Get-Date -Format 'yyyy-MM-dd')
                </h2>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- EXECUTION SUMMARY SECTION -->
        <tr>
            <td align="center">
                <table width="100%" border="0" cellpadding="0" cellspacing="0" style="width: 100%; border-collapse: collapse; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                    <thead>
                        <tr style="background-color: #1e40af; color: #ffffff;">
                            <th colspan="2" style="padding: 8px 12px; text-align: left; font-size: 13px; font-weight: 600; background-color: #1e40af;">Execution Summary</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333; width: 40%;">Monitoring Host Name</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333; font-weight: bold;">$HostName</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Script Execution Duration</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333; font-weight: bold;">$Duration</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Total SQL Servers Checked</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333; font-weight: bold;">$TotalServers</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Servers - All DBs Healthy</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #2e7d32; font-weight: bold;">$ServersHealthy</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Servers - Backup Issues Found</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #c62828; font-weight: bold;">$ServersFailed</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Servers - Connection / Check Failed</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #c62828; font-weight: bold;">$ServersUnreachable</td>
                        </tr>
                        <tr>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;">Total Database Backup Exceptions</td>
                            <td style="border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #c62828; font-weight: bold;">$($ExceptionList.Count)</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SERVER STATUS OVERVIEW SECTION -->
        <tr>
            <td align="center">
                <table width="100%" border="0" cellpadding="0" cellspacing="0" style="width: 100%; border-collapse: collapse; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                    <thead>
                        <tr style="background-color: #1e40af; color: #ffffff;">
                            <th colspan="3" style="padding: 8px 12px; text-align: left; font-size: 13px; font-weight: 600; background-color: #1e40af;">Server Status Overview</th>
                        </tr>
                        <tr style="background-color: #1e3a8a; color: #ffffff;">
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 25%;">Server Name</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600; width: 20%;">Status</th>
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Details</th>
                        </tr>
                    </thead>
                    <tbody>
                        $($OverviewRows -join "`n")
                    </tbody>
                </table>
            </td>
        </tr>

        $ExceptionSection

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SEPARATE AUTOMATED DISCLAIMER BOX -->
        <tr>
            <td style="background-color: #eff6ff; border: 1px solid #bfdbfe; border-left: 4px solid #1e40af; border-radius: 6px; padding: 10px 14px; text-align: center;">
                <span style="font-size: 12px; color: #1e40af; font-weight: 600;">
                    Note: This is an automated report do not reply to this email.
                </span>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SIGNATURE SECTION (BLUE BACKGROUND) -->
        <tr>
            <td style="background-color: #1e40af; border-radius: 8px; padding: 14px 20px; text-align: left;">
                <p style="color: #ffffff; margin: 0; font-size: 13px; line-height: 1.5;">
                    Regards,<br>
                    <strong style="color: #ffffff; font-size: 14px;">SQL DBA Team</strong><br>
                    <span style="color: #dbeafe;">Database Administration</span>
                </p>
            </td>
        </tr>

    </table>

</body>
</html>
"@

# Send Email
Send-MailMessage -SmtpServer $SmtpServer `
                 -Port $SmtpPort `
                 -From $EmailFrom `
                 -To $EmailTo `
                 -Subject $EmailSubject `
                 -Body $HtmlBody `
                 -BodyAsHtml



 This script gives failure backups which are older than 7 days for full and 24 hours older than the backup of the differential. 




# ==========================================
# Configuration Parameters
# ==========================================
$ServerListFile = "C:\Data\Sqlserver.txt"
$SmtpServer     = "smtp.yourcompany.com"
$SmtpPort       = 25
$EmailFrom      = "sqlmonitoring@yourcompany.com"
$EmailTo        = "dba-team@yourcompany.com"
$EmailSubject   = "SQL Backup Monitoring Report - $(Get-Date -Format 'dd-MMM-yyyy')"

$StartTime = Get-Date

# ==========================================
# SQL Query to Fetch Backup History
# ==========================================
$SqlQuery = @"
SELECT 
    d.name AS DatabaseName,
    d.database_id,
    CASE WHEN d.name IN ('master', 'model', 'msdb') THEN 'System DB' ELSE 'User DB' END AS DBType,
    MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) AS LastFullBackup,
    MAX(CASE WHEN b.type = 'I' THEN b.backup_finish_date END) AS LastDiffBackup
FROM sys.databases d
LEFT JOIN msdb.dbo.backupset b ON d.name = b.database_name
WHERE d.name <> 'tempdb' AND d.state_desc = 'ONLINE'
GROUP BY d.name, d.database_id;
"@

# Data Collectors
$ServerResults = @()
$ExceptionList = @()

$TotalServers = 0
$ServersHealthy = 0
$ServersFailed = 0
$ServersUnreachable = 0

if (-not (Test-Path $ServerListFile)) {
    Write-Error "Server list file not found at $ServerListFile"
    exit
}

$SqlServerList = Get-Content $ServerListFile | Where-Object { $_ -and -not $_.StartsWith("#") }

foreach ($ServerInput in $SqlServerList) {
    $ServerInput = $ServerInput.Trim()
    $TotalServers++
    
    $ServerHasIssues = $false
    $ServerExceptionsCount = 0
    $DisplayName = $ServerInput # Default to IP address if connection fails

    try {
        $ConnectionString = "Server=$ServerInput;Database=msdb;Integrated Security=SSPI;Connection Timeout=10;"
        $Connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
        $Connection.Open()

        # Get actual SQL Instance Name (@@SERVERNAME)
        $CmdInstance = $Connection.CreateCommand()
        $CmdInstance.CommandText = "SELECT @@SERVERNAME AS SqlInstanceName;"
        $DisplayName = $CmdInstance.ExecuteScalar()

        # Run Backup Check Query
        $Command = $Connection.CreateCommand()
        $Command.CommandText = $SqlQuery
        $Adapter = New-Object System.Data.SqlClient.SqlDataAdapter($Command)
        $DataTable = New-Object System.Data.DataTable
        [void]$Adapter.Fill($DataTable)
        $Connection.Close()

        foreach ($Row in $DataTable) {
            $DbName = $Row.DatabaseName
            $DbType = $Row.DBType
            $LastFull = if ($Row.LastFullBackup -ne [DBNull]::Value) { [datetime]$Row.LastFullBackup } else { $null }
            $LastDiff = if ($Row.LastDiffBackup -ne [DBNull]::Value) { [datetime]$Row.LastDiffBackup } else { $null }

            $FullDaysOld = if ($LastFull) { ($StartTime - $LastFull).TotalDays } else { 9999 }
            $DiffHoursOld = if ($LastDiff) { ($StartTime - $LastDiff).TotalHours } else { 9999 }

            $IssueDescription = $null

            # SLA Rules
            if ($DbType -eq 'System DB') {
                if ($FullDaysOld -gt 7) {
                    $IssueDescription = if ($null -eq $LastFull) { "Full backup NEVER performed" } else { "Full backup overdue (> 7 days)" }
                }
            } else {
                if ($FullDaysOld -gt 7 -and $DiffHoursOld -gt 24) {
                    $IssueDescription = "Full (> 7 days) and Differential (> 24 hours) backups overdue"
                } elseif ($FullDaysOld -gt 7) {
                    $IssueDescription = "Full backup overdue (> 7 days)"
                } elseif ($DiffHoursOld -gt 24) {
                    $IssueDescription = "Differential backup overdue (> 24 hours)"
                }
            }

            if ($IssueDescription) {
                $ServerHasIssues = $true
                $ServerExceptionsCount++
                $ExceptionList += [PSCustomObject]@{
                    Server           = $DisplayName # Displays Server\Instance Name
                    Database         = $DbName
                    Type             = $DbType
                    IssueDescription = $IssueDescription
                    LastFull         = if ($LastFull) { $LastFull.ToString("dd-MMM HH:mm") } else { "NEVER" }
                    LastDiff         = if ($DbType -eq 'System DB') { "N/A" } else { if ($LastDiff) { $LastDiff.ToString("dd-MMM HH:mm") } else { "NEVER" } }
                }
            }
        }

        if ($ServerHasIssues) {
            $ServersFailed++
            $ServerResults += [PSCustomObject]@{
                ServerName = $DisplayName # Displays Server\Instance Name
                Status     = "ISSUES FOUND"
                Details    = "<span style='color: #dc2626; font-weight: bold;'>$ServerExceptionsCount database(s) failing backup SLA</span>"
            }
        } else {
            $ServersHealthy++
            $ServerResults += [PSCustomObject]@{
                ServerName = $DisplayName # Displays Server\Instance Name
                Status     = "ALL DB'S FINE"
                Details    = "<span style='color: #64748b; font-style: italic;'>All databases met backup SLAs</span>"
            }
        }

    } catch {
        $ServersUnreachable++
        $ErrorMessage = $_.Exception.Message.Trim()
        $ServerResults += [PSCustomObject]@{
            ServerName = "$ServerInput (Unreachable)" # Shows IP and failure status
            Status     = "CHECK FAILED"
            Details    = "<div style='color: #dc2626; font-weight: bold;'>Connection / Execution Failure</div><div style='background-color: #fff1f2; color: #991b1b; font-family: Consolas, monospace; font-size: 12px; padding: 8px 12px; border-left: 4px solid #f43f5e; border-radius: 4px; margin-top: 5px; word-break: break-all;'>$ErrorMessage</div>"
        }
    }
}

$EndTime = Get-Date
$Duration = "{0:hh}:{0:mm}:{0:ss}" -f ($EndTime - $StartTime)
$HostName = $env:COMPUTERNAME

# ==========================================
# Modern Outlook-Compatible HTML Email Body
# ==========================================
$HtmlHeader = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #1e293b; background-color: #f1f5f9; margin: 0; padding: 20px; }
        .container { background-color: #ffffff; padding: 30px; border-radius: 12px; max-width: 900px; margin: auto; border: 1px solid #e2e8f0; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
        
        /* Centered Header with Modern Royal Blue Accent */
        .header-card { text-align: center; background: linear-gradient(135deg, #1e40af, #3b82f6); color: #ffffff; padding: 24px; border-radius: 10px; margin-bottom: 25px; }
        .header-card h2 { margin: 0 0 8px 0; font-size: 22px; font-weight: 700; color: #ffffff; letter-spacing: 0.5px; }
        .header-card .meta-info { font-size: 13px; color: #dbeafe; font-weight: 400; margin: 0; }
        .header-card .meta-info b { color: #ffffff; }

        .section-title { font-size: 15px; font-weight: 700; color: #0f172a; margin-top: 25px; margin-bottom: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
        
        /* Rounded Table Wrappers */
        .table-card { border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; margin-bottom: 20px; background-color: #ffffff; }
        table { width: 100%; border-collapse: collapse; font-size: 13px; }
        th { background-color: #1e293b; color: #ffffff; text-align: left; padding: 12px 14px; font-weight: 600; font-size: 12px; letter-spacing: 0.3px; }
        td { padding: 10px 14px; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
        tr:last-child td { border-bottom: none; }

        .summary-table td:first-child { width: 45%; color: #475569; font-weight: 500; }
        .summary-table td:last-child { font-weight: 600; }

        /* Modern Status Badges */
        .badge { padding: 4px 10px; border-radius: 6px; font-weight: 700; font-size: 11px; display: inline-block; letter-spacing: 0.3px; }
        .badge-green { background-color: #dcfce7; color: #15803d; border: 1px solid #bbf7d0; }
        .badge-orange { background-color: #ffedd5; color: #c2410c; border: 1px solid #fed7aa; }
        .badge-red { background-color: #fee2e2; color: #b91c1c; border: 1px solid #fca5a5; }

        /* Rounded Light Signature Card */
        .footer-card { background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px 20px; margin-top: 30px; font-size: 12px; color: #64748b; line-height: 1.5; }
        .footer-title { font-weight: 700; color: #0284c7; font-size: 13px; margin-bottom: 2px; }
    </style>
</head>
<body>
<div class="container">
    
    <!-- Centered Header Card -->
    <div class="header-card">
        <h2>SQL Backup Monitoring Report</h2>
        <p class="meta-info">Generated on: <b>$(Get-Date -Format 'dd-MMM-yyyy HH:mm:ss')</b> &nbsp;|&nbsp; Server Host: <b>$HostName</b></p>
    </div>

    <!-- Execution Summary -->
    <div class="section-title">Execution Summary</div>
    <div class="table-card">
        <table class="summary-table">
            <tr><td>Total SQL Servers Checked</td><td><b>$TotalServers</b></td></tr>
            <tr><td>Servers - All DBs Healthy</td><td><span style="color: #16a34a;">$ServersHealthy</span></td></tr>
            <tr><td>Servers - Backup Issues Found</td><td><span style="color: #dc2626;">$ServersFailed</span></td></tr>
            <tr><td>Servers - Connection / Check Failed</td><td><span style="color: #ea580c;">$ServersUnreachable</span></td></tr>
            <tr><td>Total Database Backup Exceptions</td><td><span style="color: #dc2626;">$($ExceptionList.Count)</span></td></tr>
            <tr><td>Script Execution Time</td><td><b>$Duration</b></td></tr>
        </table>
    </div>

    <!-- Server Status Overview -->
    <div class="section-title">Server Status Overview</div>
    <div class="table-card">
        <table>
            <thead>
                <tr>
                    <th style="width: 28%;">Server Name</th>
                    <th style="width: 24%;">Status</th>
                    <th>Details</th>
                </tr>
            </thead>
            <tbody>
"@

foreach ($res in $ServerResults) {
    $StatusBadge = switch ($res.Status) {
        "ALL DB'S FINE" { "<span class='badge badge-green'>ALL DB'S FINE</span>" }
        "ISSUES FOUND"  { "<span class='badge badge-red'>ISSUES FOUND</span>" }
        "CHECK FAILED"  { "<span class='badge badge-orange'>CHECK FAILED</span>" }
    }
    
    $HtmlHeader += @"
                <tr>
                    <td><b>$($res.ServerName)</b></td>
                    <td>$StatusBadge</td>
                    <td>$($res.Details)</td>
                </tr>
"@
}

$HtmlHeader += @"
            </tbody>
        </table>
    </div>
"@

# Database Exceptions Section
if ($ExceptionList.Count -gt 0) {
    $HtmlHeader += @"
    <div class="section-title">Database Backup Exceptions</div>
    <div class="table-card">
        <table>
            <thead>
                <tr>
                    <th style="width: 18%;">Server</th>
                    <th style="width: 18%;">Database</th>
                    <th style="width: 14%;">Type</th>
                    <th style="width: 32%;">Issue Description</th>
                    <th style="width: 9%;">Last Full</th>
                    <th style="width: 9%;">Last Diff</th>
                </tr>
            </thead>
            <tbody>
"@
    foreach ($ex in $ExceptionList) {
        $HtmlHeader += @"
                <tr>
                    <td><b>$($ex.Server)</b></td>
                    <td>$($ex.Database)</td>
                    <td><i>$($ex.Type)</i></td>
                    <td><span style="color: #dc2626; font-weight: 600;">$($ex.IssueDescription)</span></td>
                    <td>$($ex.LastFull)</td>
                    <td>$($ex.LastDiff)</td>
                </tr>
"@
    }
    $HtmlHeader += @"
            </tbody>
        </table>
    </div>
"@
}

# Rounded Light Signature Card
$HtmlHeader += @"
    <div class="footer-card">
        <div class="footer-title">Central Database Automation Engine</div>
        <b>Database Infrastructure &amp; Administration Team</b><br>
        <span style="font-size: 11px; color: #94a3b8;">This email was generated automatically by Central Monitoring Server (<b>$HostName</b>). Please do not reply directly to this message.</span>
    </div>
</div>
</body>
</html>
"@

# Send Email
Send-MailMessage -SmtpServer $SmtpServer `
                 -Port $SmtpPort `
                 -From $EmailFrom `
                 -To $EmailTo `
                 -Subject $EmailSubject `
                 -Body $HtmlHeader `
                 -BodyAsHtml

# Code completed.

 Here is the updated script.





<#
.SYNOPSIS
Collects drive space details from a list of Windows servers and emails an HTML report.

.NOTES
- Requires WinRM/CIM access to target servers (Enable-PSRemoting on targets, or WMI/DCOM open via firewall).
- Run under an account with admin rights on target servers, or supply -Credential.
- Works on Windows PowerShell 5.1 (built-in Send-MailMessage). For PS7, see notes at bottom.
#>

# ---- CONFIG ----

# Read server names from an external text file
$serverListPath = "C:\Scripts\servers.txt"

$servers = Get-Content $serverListPath |
           Where-Object { $_.Trim() -ne "" }

$smtpServer    = "smtp.yourcompany.com"
$from          = "monitoring@yourcompany.com"
$to            = "you@yourcompany.com"
$subject       = "Windows Servers - Drive Space Report - $(Get-Date -Format 'yyyy-MM-dd')"
$freeThreshold = 20   # percent free below which status = Check Now


# ---- COLLECT DATA ----

$results = foreach ($server in $servers) {
    try {
        $disks = Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName $server -Filter "DriveType=3" -ErrorAction Stop

        foreach ($disk in $disks) {
            $sizeGB    = [math]::Round($disk.Size / 1GB, 2)
            $freeGB    = [math]::Round($disk.FreeSpace / 1GB, 2)
            $usedGB    = [math]::Round($sizeGB - $freeGB, 2)
            $pctFree   = if ($sizeGB -gt 0) { [math]::Round(($freeGB / $sizeGB) * 100, 1) } else { 0 }
            $status    = if ($pctFree -lt $freeThreshold) { "Check Now" } else { "Healthy" }

            [PSCustomObject]@{
                Server      = $server
                DeviceID    = $disk.DeviceID
                SizeGB      = $sizeGB
                UsedGB      = $usedGB
                FreeGB      = $freeGB
                PercentFree = $pctFree
                Status      = $status
            }
        }
    }
    catch {
        [PSCustomObject]@{
            Server      = $server
            DeviceID    = "-"
            SizeGB      = $null
            UsedGB      = $null
            FreeGB      = $null
            PercentFree = $null
            Status      = "Server not reachable"
        }
    }
}


# ---- BUILD HTML OUTPUT WITH INLINE STYLES ----

$rows = foreach ($r in $results) {

    $statusStyle = switch ($r.Status) {
        "Healthy"              { "color: #2e7d32; font-weight: bold;" }
        "Check Now"            { "color: #c62828; font-weight: bold;" }
        "Server not reachable" { "color: #c62828; font-weight: bold; background-color: #ffebee;" }
        default                { "" }
    }

    "<tr>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.Server)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.DeviceID)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.SizeGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.UsedGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.FreeGB)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; color: #333333;'>$($r.PercentFree)</td>
        <td style='border: 1px solid #e0e0e0; padding: 8px 12px; font-size: 13px; $statusStyle'>$($r.Status)</td>
    </tr>"
}

$html = @"
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body style="margin: 0; padding: 20px; background-color: #f4f6f8; font-family: 'Segoe UI', Arial, sans-serif;">

    <!-- Main Container Table to center all sections with 700px width -->
    <table align="center" width="700" border="0" cellpadding="0" cellspacing="0" style="width: 700px; margin: 0 auto;">
        
        <!-- HEADER SECTION -->
        <tr>
            <td style="background-color: #2c3e50; border-radius: 8px; padding: 16px 20px; text-align: center;">
                <h2 style="color: #ffffff; margin: 0; font-size: 18px; font-weight: 600;">
                    Windows Server Drive Space Report - $(Get-Date -Format 'yyyy-MM-dd')
                </h2>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- RESULTS TABLE SECTION -->
        <tr>
            <td align="center">
                <table width="100%" border="0" cellpadding="0" cellspacing="0" style="width: 100%; border-collapse: collapse; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
                    <thead>
                        <tr style="background-color: #34495e; color: #ffffff;">
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Server</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">DeviceID</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Size (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Used (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Free (GB)</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">% Free</th> 
                            <th style="padding: 10px 12px; text-align: left; font-size: 12px; font-weight: 600;">Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        $($rows -join "`n")
                    </tbody>
                </table>
            </td>
        </tr>

        <!-- SPACER -->
        <tr><td height="16" style="height: 16px;"></td></tr>

        <!-- SIGNATURE SECTION -->
        <tr>
            <td style="background-color: #2c3e50; border-radius: 8px; padding: 14px 20px; text-align: left;">
                <p style="color: #ecf0f1; margin: 0; font-size: 13px; line-height: 1.5;">
                    Regards,<br>
                    <strong style="color: #ffffff; font-size: 14px;">SQL DBA Team</strong><br>
                    <span style="color: #bdc3c7;">Database Administration</span>
                </p>
            </td>
        </tr>

    </table>

</body>
</html>
"@


# ---- SEND EMAIL ----

Send-MailMessage -From $from -To $to -Subject $subject -Body $html -BodyAsHtml -SmtpServer $smtpServer


 Here is the consolidated report script to get all server databases informaiton for the full and differential database backups. 





# ==========================================
# Configuration Parameters
# ==========================================
$ServerListFile = "C:\Data\Sqlserver.txt"
$SmtpServer     = "smtp.yourcompany.com"
$SmtpPort       = 25
$EmailFrom      = "sqlmonitoring@yourcompany.com"
$EmailTo        = "dba-team@yourcompany.com"
$EmailSubject   = "SQL Backup Monitoring Report - $(Get-Date -Format 'dd-MMM-yyyy')"

# Force TLS 1.2 for modern SMTP servers
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$StartTime = Get-Date

# ==========================================
# SQL Query to Fetch Backup History
# ==========================================
$SqlQuery = @"
SELECT
    d.name AS DatabaseName,
    d.database_id,
    d.recovery_model_desc AS RecoveryModel,
    CASE WHEN d.name IN ('master', 'model', 'msdb') THEN 'System DB' ELSE 'User DB' END AS DBType,
    MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) AS LastFullBackup,
    MAX(CASE WHEN b.type = 'I' THEN b.backup_finish_date END) AS LastDiffBackup,
    MAX(CASE WHEN b.type = 'L' THEN b.backup_finish_date END) AS LastLogBackup
FROM sys.databases d
LEFT JOIN msdb.dbo.backupset b ON d.name = b.database_name
WHERE d.name <> 'tempdb' AND d.state_desc = 'ONLINE'
GROUP BY d.name, d.database_id, d.recovery_model_desc;
"@

# Data Collectors
$ServerResults = @()
$ExceptionList = @()
$TotalServers = 0
$ServersHealthy = 0
$ServersFailed = 0
$ServersUnreachable = 0

if (-not (Test-Path $ServerListFile)) {
    Write-Error "Server list file not found at $ServerListFile"
    exit
}

$SqlServerList = Get-Content $ServerListFile | Where-Object { $_ -and -not $_.StartsWith("#") }

if ($SqlServerList.Count -eq 0) {
    Write-Warning "No servers found in $ServerListFile."
    exit
}

foreach ($Server in $SqlServerList) {
    $Server = $Server.Trim()
    $TotalServers++
    $ServerHasIssues = $false
    $ServerExceptionsCount = 0

    try {
        $ConnectionString = "Server=$Server;Database=msdb;Integrated Security=SSPI;Connection Timeout=10;"
        $Connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
        $Connection.Open()
        
        $Command = $Connection.CreateCommand()
        $Command.CommandText = $SqlQuery
        $Adapter = New-Object System.Data.SqlClient.SqlDataAdapter($Command)
        $DataTable = New-Object System.Data.DataTable
        [void]$Adapter.Fill($DataTable)
        $Connection.Close()

        foreach ($Row in $DataTable) {
            $DbName = $Row.DatabaseName
            $DbType = $Row.DBType
            $RecoveryModel = $Row.RecoveryModel
            
            $LastFull = if ($Row.LastFullBackup -ne [DBNull]::Value) { [datetime]$Row.LastFullBackup } else { $null }
            $LastDiff = if ($Row.LastDiffBackup -ne [DBNull]::Value) { [datetime]$Row.LastDiffBackup } else { $null }
            $LastLog  = if ($Row.LastLogBackup -ne [DBNull]::Value) { [datetime]$Row.LastLogBackup } else { $null }

            $FullDaysOld = if ($LastFull) { ($StartTime - $LastFull).TotalDays } else { 9999 }
            $DiffHoursOld = if ($LastDiff) { ($StartTime - $LastDiff).TotalHours } else { 9999 }
            $LogHoursOld = if ($LastLog) { ($StartTime - $LastLog).TotalHours } else { 9999 }

            $IssueDescription = $null

            # Evaluation Rules
            if ($DbType -eq 'System DB') {
                if ($FullDaysOld -gt 7) {
                    $IssueDescription = if ($null -eq $LastFull) { "Full backup NEVER performed" } else { "Full backup overdue (> 7 days)" }
                }
            } else {
                # User DBs SLA Logic
                if ($FullDaysOld -gt 7 -and $DiffHoursOld -gt 24) {
                    $IssueDescription = "Full (> 7 days) and Differential (> 24 hours) backups overdue"
                } elseif ($FullDaysOld -gt 7) {
                    $IssueDescription = "Full backup overdue (> 7 days)"
                } elseif ($DiffHoursOld -gt 24) {
                    $IssueDescription = "Differential backup overdue (> 24 hours)"
                }
                
                # Added Log Backup Check for FULL recovery model
                if ($RecoveryModel -eq 'FULL' -and $LogHoursOld -gt 2) {
                    $LogIssue = if ($null -eq $LastLog) { "Log backup NEVER performed" } else { "Log backup overdue (> 2 hours)" }
                    $IssueDescription = if ($IssueDescription) { "$IssueDescription | $LogIssue" } else { $LogIssue }
                }
            }

            # Record Exceptions
            if ($IssueDescription) {
                $ServerHasIssues = $true
                $ServerExceptionsCount++
                
                # Pre-calculate strings to avoid hashtable syntax errors
                $LastFullStr = if ($LastFull) { $LastFull.ToString("dd-MMM HH:mm") } else { "NEVER" }
                $LastDiffStr = if ($DbType -eq 'System DB') { "N/A" } elseif ($LastDiff) { $LastDiff.ToString("dd-MMM HH:mm") } else { "NEVER" }

                $ExceptionList += [PSCustomObject]@{
                    Server           = $Server
                    Database         = $DbName
                    Type             = $DbType
                    IssueDescription = $IssueDescription
                    LastFull         = $LastFullStr
                    LastDiff         = $LastDiffStr
                }
            }
        }

        if ($ServerHasIssues) {
            $ServersFailed++
            $ServerResults += [PSCustomObject]@{
                ServerName = $Server
                Status     = "ISSUES FOUND"
                Details    = "<span style='color: #c0392b; font-weight: bold;'>$ServerExceptionsCount database(s) failing backup SLA</span>"
            }
        } else {
            $ServersHealthy++
            $ServerResults += [PSCustomObject]@{
                ServerName = $Server
                Status     = "ALL DB'S FINE"
                Details    = "<span style='color: #7f8c8d; font-style: italic;'>All databases met backup SLAs</span>"
            }
        }
    } catch {
        $ServersUnreachable++
        # Sanitize error message to prevent HTML breaking
        $ErrorMessage = [System.Net.WebUtility]::HtmlEncode($_.Exception.Message.Trim())
        $ServerResults += [PSCustomObject]@{
            ServerName = $Server
            Status     = "CHECK FAILED"
            Details    = "<div style='color: #c0392b; font-weight: bold;'>Connection / Execution Failure</div><div style='background: #fdf2e9; color: #c0392b; font-family: monospace; padding: 6px; border-left: 3px solid #e67e22; margin-top: 4px;'>$ErrorMessage</div>"
        }
    }
}

$EndTime = Get-Date
$Duration = "{0:hh\:mm\:ss}" -f ($EndTime - $StartTime)
$HostName = $env:COMPUTERNAME

# ==========================================
# HTML Email Generation (Unchanged from your original, just ensuring variables match)
# ==========================================
$HtmlHeader = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; background-color: #f4f6f9; margin: 0; padding: 20px; }
.container { background-color: #ffffff; padding: 25px; border-radius: 6px; max-width: 900px; margin: auto; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
h2 { color: #2c3e50; margin-bottom: 5px; }
.meta-info { font-size: 13px; color: #7f8c8d; margin-bottom: 20px; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
.section-title { font-size: 16px; font-weight: bold; color: #2c3e50; margin-top: 25px; margin-bottom: 10px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 15px; font-size: 13px; }
th { background-color: #2c3e50; color: #ffffff; text-align: left; padding: 10px; }
td { padding: 9px 10px; border-bottom: 1px solid #eef1f5; vertical-align: top; }
.badge { padding: 4px 8px; border-radius: 4px; font-weight: bold; font-size: 11px; display: inline-block; }
.badge-green { background-color: #e8f8f5; color: #27ae60; border: 1px solid #a3e4d7; }
.badge-orange { background-color: #fef9e7; color: #d35400; border: 1px solid #f9e79f; }
.badge-red { background-color: #fadbd8; color: #78281f; border: 1px solid #f5b7b1; }
.footer { font-size: 12px; color: #7f8c8d; margin-top: 30px; border-top: 1px solid #eef1f5; padding-top: 15px; }
</style>
</head>
<body>
<div class="container">
<h2>SQL Backup Monitoring Report</h2>
<div class="meta-info">
Generated on: <b>$(Get-Date -Format 'dd-MMM-yyyy HH:mm:ss')</b> | Server Host: <b>$HostName</b>
</div>
<div class="section-title">Execution Summary</div>
<table>
<tr><td style="width: 40%;">Total SQL Servers Checked</td><td><b>$TotalServers</b></td></tr>
<tr><td>Servers - All DBs Healthy</td><td><b style="color: #27ae60;">$ServersHealthy</b></td></tr>
<tr><td>Servers - Backup Issues Found</td><td><b style="color: #c0392b;">$ServersFailed</b></td></tr>
<tr><td>Servers - Connection / Check Failed</td><td><b style="color: #d35400;">$ServersUnreachable</b></td></tr>
<tr><td>Total Database Backup Exceptions</td><td><b style="color: #c0392b;">$($ExceptionList.Count)</b></td></tr>
<tr><td>Script Execution Time</td><td><b>$Duration</b></td></tr>
</table>
<div class="section-title">Server Status Overview</div>
<table>
<thead>
<tr>
<th style="width: 30%;">Server Name</th>
<th style="width: 25%;">Status</th>
<th>Details</th>
</tr>
</thead>
<tbody>
"@

foreach ($res in $ServerResults) {
    $StatusBadge = switch ($res.Status) {
        "ALL DB'S FINE" { "<span class='badge badge-green'>ALL DB'S FINE</span>" }
        "ISSUES FOUND"  { "<span class='badge badge-red'>ISSUES FOUND</span>" }
        "CHECK FAILED"  { "<span class='badge badge-orange'>CHECK FAILED</span>" }
    }
    $HtmlHeader += @"
<tr>
<td><b>$($res.ServerName)</b></td>
<td>$StatusBadge</td>
<td>$($res.Details)</td>
</tr>
"@
}

$HtmlHeader += @"
</tbody>
</table>
"@

if ($ExceptionList.Count -gt 0) {
    $HtmlHeader += @"
<div class="section-title">Database Backup Exceptions</div>
<table>
<thead>
<tr>
<th>Server</th>
<th>Database</th>
<th>Type</th>
<th>Issue Description</th>
<th>Last Full</th>
<th>Last Diff</th>
</tr>
</thead>
<tbody>
"@
    foreach ($ex in $ExceptionList) {
        $HtmlHeader += @"
<tr>
<td><b>$($ex.Server)</b></td>
<td>$($ex.Database)</td>
<td><i>$($ex.Type)</i></td>
<td><span style="color: #c0392b; font-weight: bold;">$($ex.IssueDescription)</span></td>
<td>$($ex.LastFull)</td>
<td>$($ex.LastDiff)</td>
</tr>
"@
    }
    $HtmlHeader += @"
</tbody>
</table>
"@
}

$HtmlHeader += @"
<div class="footer">
<b>Central Database Automation Engine</b><br>
Database Infrastructure & Administration Team<br>
<span style="font-size: 11px;">This email was generated automatically by Central Monitoring Server ($HostName). Please do not reply directly to this message.</span>
</div>
</div>
</body>
</html>
"@

# Send Email
Send-MailMessage -SmtpServer $SmtpServer `
    -Port $SmtpPort `
    -From $EmailFrom `
    -To $EmailTo `
    -Subject $EmailSubject `
    -Body $HtmlHeader `
    -BodyAsHtml



Author Name

Contact Form

Name

Email *

Message *

Powered by Blogger.