Powershell : Blacklist Checker with HTML and email Notification


This is a feature one usually pays for, but is that actually required as surely you can write a script to perform these action?

That sounds like a good mission, so for this mission we need to define a list of hostnames or IP's in the script them we need to check the status of those service against the "blacklist checkers" and report that in the Powershell console.

Yes indeed that is possible so lets get the code for that which is a simple lookup to the blacklist providers:

Script : BlacklistChecker.ps1

# Define the list of hostnames and IP addresses to check
$hostList = @(
    "<hostname>",
    "<ip>",
    "<ip>"
)

# Define a list of blacklist servers to check against
$blacklists = @(
    "b.barracudacentral.org",
    "bl.spamcop.net",
    "blacklist.woody.ch",
    "cbl.abuseat.org",
    "dnsbl.sorbs.net",
    "zen.spamhaus.org"
)

# Function to check if an IP address is blacklisted
function Check-Blacklist {
    param (
        [string]$hostname,
        [string]$reversedIp
    )
    $results = @()
    foreach ($blacklist in $blacklists) {
        try {
            $lookup = "$($reversedIp).$blacklist"
            $resolved = [System.Net.Dns]::GetHostAddresses($lookup)
            if ($resolved) {
                $results += [pscustomobject]@{
                    Hostname   = $hostname
                    Blacklist  = $blacklist
                    Status     = "Listed"
                }
            }
        } catch {
            $results += [pscustomobject]@{
                Hostname   = $hostname
                Blacklist  = $blacklist
                Status     = "Not Listed"
            }
        }
    }

    return $results
}

# Process each host in the list
foreach ($hostname in $hostList) {
    $ipAddresses = try {
        [System.Net.Dns]::GetHostAddresses($hostname) | Where-Object { $_.AddressFamily -eq 'InterNetwork' }
    } catch {
        Write-Host "Could not resolve $hostname"
        continue
    }

   if ($ipAddresses.Count -eq 0) {
        Write-Host "No IPv4 addresses found for $hostname"
        continue
    }
    $ipAddresses = $ipAddresses | ForEach-Object { $_.IPAddressToString }
   foreach ($ipAddress in $ipAddresses) {
        $reversedIp = ($ipAddress -split '\.')[-1..0] -join '.'
        $results = Check-Blacklist -hostname $hostname -reversedIp $reversedIp
        $results | Format-Table -AutoSize
    }
}

This when run will look something like this, which is absolutely fantastic for an immediate output:


Add a little HTML magic 🌈 

That then made me wonder would it not be better if we had a HTML formatted report - this would essentially format all that data in a table that’s nicely formatted in HTML, if this is something you’re looking to add then after this section of the code : 

    return $results

You will need to add your HTML code, this is what I have used:

# HTML report initialization
$htmlReport = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blacklist Check Report</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .logo {
            display: block;
            margin-left: auto;
            margin-right: auto;
            width: 150px;
        }
        table {
            width: 50%;
            border-collapse: collapse;
            margin: 20px auto;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        .status-listed {
            color: red;
            font-weight: bold;
        }
        .status-not-listed {
            color: green;
            font-weight: bold;
        }
        .status-listed::before {
            content: "❌ ";
        }
        .status-not-listed::before {
            content: "✅ ";
        }
    </style>
</head>
<body>
    <img src="https://bloguk.z13.web.core.windows.net/stwlogo.png" alt="Logo" class="logo">
    <h1 style="text-align: center;">Blacklist Check Report</h1>
    <table>
        <thead>
            <tr>
                <th>Hostname</th>
                <th>Blacklist</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>
"@

Then finally on the end of the code you will need add this code to actually create the HTML file you need:

# Complete the HTML report
$htmlReport += @"
        </tbody>
    </table>
</body>
</html>
"@

# Output the HTML report to a file
$outputPath = "BlacklistCheckReport.html"
$htmlReport | Out-File -FilePath $outputPath -Encoding UTF8

# Notify user of the report location
Write-Host "Report generated at $outputPath"

That will output a file in the same directory as where the script is run called BlacklsitCheckReport.html which will look something like this:


The answer to the question is yes, you can do you own blacklist checker automation, all your need to figure out is the frequency of these checks.

🐍 Scripts Overview

I would probably advise 2x scripts, the script from above call that:

BlacklistChecker-Console.ps1

The script will only output to the console, then we need another script to provide the HTML content file generation and call that:

BlacklistChecker-HTML.ps1

If you adopt this method you have console only output script, and then another script that has a pretty management, friendly overview of the technical status of your monitored endpoints.

That means when the scripts are run you have a way to monitor your blacklist status, but this does not offer any automation, 

Unlike many Blacklist check websites that will check your listing every 15 minutes and notify you the moment you’re on one of these blacklists……

⛔️ Not automation ready

If you review both the scripts, you now have neither of these are fit for automation, The first script only outputs to a console, and the second will indeed generate to HTML file which theoretically could be emailed……

The downside here is if you set the schedule for every 15 minutes you’re going to get an email every 15 minutes with a report telling you “you’re not on a blacklist” - leave that running for a couple of hours, and you will be completely desensitized to any kind of alert that comes from this inbox

🚀 Automation ready script

If you wish to automate, this process is way to accomplish this  is to have a scheduled task that runs every 15 minutes, unfortunately, not the script you currently have because you will end up with notification fatigue.

Intervention is required, so we only get a HTML report formatted if any check comes back as “listed” in this instance, we wish to have a HTML report format and then instantly emailed out.

This way you will only receive an email when You need to be notified about administrative action you need to take, so we need to change the script parameters which Will enforce the action to only generator HTML page on the status of “listed” And then send an email with that update.

Script : BlacklistChecker-Automation.ps1

# Define the list of hostnames and IP addresses to check
$hostList = @(
    "<host>",
    "<ip1>",
    "<ip2>"
)

# Define the list of blacklist servers to check against
$blacklists = @(
    "b.barracudacentral.org",
    "bl.spamcop.net",
    "blacklist.woody.ch",
    "cbl.abuseat.org",
    "dnsbl.sorbs.net",
    "zen.spamhaus.org"
)

# SMTP server settings
$smtpServer = "smtprelay.bear.local"
$fromAddress = "blacklist@croucher.cloud”
$toAddress = "lee@croucher.cloud"
$subject = "Alert : Blacklist Check Report"

# Function to check if an IP address is blacklisted
function Check-Blacklist {
    param (
        [string]$hostname,
        [string]$reversedIp
    )
    
    $results = @()

    foreach ($blacklist in $blacklists) {
        try {
            $lookup = "$($reversedIp).$blacklist"
            $resolved = [System.Net.Dns]::GetHostAddresses($lookup)
            if ($resolved) {
                $results += [pscustomobject]@{
                    Hostname   = $hostname
                    Blacklist  = $blacklist
                    Status     = "Listed"
                }
            }
        } catch {
            $results += [pscustomobject]@{
                Hostname   = $hostname
                Blacklist  = $blacklist
                Status     = "Not Listed"
            }
        }
    }

    return $results
}

# Flag to determine if any host is listed
$anyListed = $false

# HTML report initialization
$htmlReport = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blacklist Check Report</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .logo {
            display: block;
            margin-left: auto;
            margin-right: auto;
            width: 150px;
        }
        table {
            width: 50%;
            border-collapse: collapse;
            margin: 20px auto;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        .status-listed {
            color: red;
            font-weight: bold;
        }
        .status-not-listed {
            color: green;
            font-weight: bold;
        }
        .status-listed::before {
            content: "❌ ";
        }
        .status-not-listed::before {
            content: "✅ ";
        }
    </style>
</head>
<body>
    <img src="logo.png" alt="Logo" class="logo">
    <h1 style="text-align: center;">Blacklist Check Report</h1>
    <table>
        <thead>
            <tr>
                <th>Hostname</th>
                <th>Blacklist</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>
"@

# Process each host in the list
foreach ($hostname in $hostList) {
    $ipAddresses = try {
        [System.Net.Dns]::GetHostAddresses($hostname) | Where-Object { $_.AddressFamily -eq 'InterNetwork' }
    } catch {
        Write-Host "Could not resolve $hostname"
        continue
    }

    if ($ipAddresses.Count -eq 0) {
        Write-Host "No IPv4 addresses found for $hostname"
        continue
    }

    $ipAddresses = $ipAddresses | ForEach-Object { $_.IPAddressToString }

    foreach ($ipAddress in $ipAddresses) {
        $reversedIp = ($ipAddress -split '\.')[-1..0] -join '.'
        $results = Check-Blacklist -hostname $hostname -reversedIp $reversedIp
        $results | Format-Table -AutoSize
        
        foreach ($result in $results) {
            $statusClass = if ($result.Status -eq "Listed") {
                $anyListed = $true
                "status-listed"
            } else {
                "status-not-listed"
            }
            $htmlReport += @"
            <tr>
                <td>$($result.Hostname)</td>
                <td>$($result.Blacklist)</td>
                <td class="$statusClass">$($result.Status)</td>
            </tr>
"@
        }
    }
}

# Complete the HTML report if any host is listed
if ($anyListed) {
    $htmlReport += @"
        </tbody>
    </table>
</body>
</html>
"@
    
    # Output the HTML report to a file
    $outputPath = "BlacklistCheckReport.html"
    $htmlReport | Out-File -FilePath $outputPath -Encoding UTF8

    # Send the email
    $message = New-Object system.net.mail.mailmessage
    $message.from = $fromAddress
    $message.To.Add($toAddress)
    $message.Subject = $subject
    $message.Body = "Please find the attached blacklist check report."
    $message.IsBodyHtml = $false

    # Attach the HTML report
    $attachment = New-Object system.net.mail.attachment($outputPath)
    $message.Attachments.Add($attachment)

    # Configure the SMTP client and send the email
    $smtpClient = New-Object Net.Mail.SmtpClient($smtpServer)
    $smtpClient.Send($message)

    # Clean up
    $message.Dispose()
    $attachment.Dispose()
    $smtpClient.Dispose()

    Write-Host "Report generated and emailed to $toAddress"
} else {
    Write-Host "No hosts were listed in any blacklists. No report generated."
}


Previous Post Next Post

نموذج الاتصال