ReportError script centralized

What I want to achieve is the ability to use the script from a central server, which currently works as long as I don’t build on the JSON files with multiple servers, which I must succeed in achieving. The script needs to retrieve email addresses based on the server name, the same goes, of course, further down in the script with get-childitem. I just can’t get it to work. As soon as I add servers to the JSON files, the script stops working. Does anyone have an idea of what I’m missing?

## ReportError.ps1
## Author: Thomas Sköld
## Created: 2023-10-05
## -----------------------------

# Specify paths to your JSON files here
$jsonFilePaths = @(
    "C:\Scripts\Antura\Servers\ReportErrorTest.json",
    "C:\Scripts\Antura\Servers\ReportErrorProd.json"
)

# Introduction for the email message for test and prod environments
$EmailBodyIntroTest = "Group Functions [Test]"
$EmailBodyIntroProd = "Group Functions [Prod]"

# Loop through the JSON files
foreach ($jsonFilePath in $jsonFilePaths) {
    # Read settings from the JSON file
    $jsonContent = Get-Content -Path $jsonFilePath | ConvertFrom-Json

    # Configuration parameters from JSON
    $SMTPServer   = 'smtp.corp.home.se'
    $SMTPFrom     = $jsonContent.mailfrom
    $SMTPFromName = $jsonContent.mailfromname
    $Aliasname    = $jsonContent.aliasname
    $ServerName   = $jsonContent.servername

    # Get email addresses based on the server name
    $EmailAddresses = @{
        "Server1" = $jsonContent.mailto_test
        "Server2" = $jsonContent.mailto_prod
    }

    # Check if the server name exists in the EmailAddresses dictionary
    if ($EmailAddresses.ContainsKey($ServerName)) {
        $NotificationAddresses = $EmailAddresses[$ServerName] -split ';'
    }
    else {
        Write-Host "The server name '$ServerName' did not match any configuration. No email will be sent."
        Write-Host "Available server keys in EmailAddresses:"
        $EmailAddresses.Keys | ForEach-Object {
            Write-Host $_
        }
        continue
    }

    # Build the email message content
    if ($ServerName -eq "Server1") {
        $EmailBodyIntro = $EmailBodyIntroTest
    }
    elseif ($ServerName -eq "Server2") {
        $EmailBodyIntro = $EmailBodyIntroProd
    }
    else {
        # If no matching was found for the server name
        Write-Host "The server name '$ServerName' did not match any configuration. No email will be sent."
        Write-Host "Available server keys in EmailAddresses:"
        $EmailAddresses.Keys | ForEach-Object {
            Write-Host $_
        }
        continue
    }

    $MailBody = "$EmailBodyIntro<br/><br/>Listed below are integration files that Import has been aborted on $Aliasname"
    $MailBody += '<table Border=1 cellpadding=2 cellspacing=2><tr><td><b>CreationTime</b></td><td><b>FullName</b></td></tr>'
    $Errors = 0

    # Loop through files
    Get-ChildItem -Path "\\$ServerName\D$\Integrations\Import" -Filter *.* -Recurse -Depth 3 -Force | ForEach-Object {
        $File = $_
        if ($File.DirectoryName -like "*Error*" -and $File.DirectoryName -notlike "*ErrorReported*" -and $File.DirectoryName -notlike "*BidEstimate*") {
            $FromFile = $File.FullName
            $DestinationPath = Join-Path -Path $File.DirectoryName -ChildPath 'ErrorReported'

            # Create the "ErrorReported" folder if it doesn't exist
            if (-not (Test-Path $DestinationPath -PathType Container)) {
                New-Item -Path $DestinationPath -ItemType Directory
            }

            # Move the file to the "ErrorReported" folder
            Move-Item -Path $FromFile -Destination $DestinationPath -ErrorAction SilentlyContinue -Force
            $Errors++

            # Build email information
            $IntegrationsShareFile = $FromFile -replace 'D:', ('\\' + $Aliasname)
            $IntegrationsShareFile = $IntegrationsShareFile -replace 'Integrations', 'Integrations'
            $IntegrationsShareFile = $IntegrationsShareFile -replace '\\Error\\', '\Error\ErrorReported\'
            $IntegrationsShareFileLink = '" target="_blank">' + $IntegrationsShareFile + '</a>'
            $IntegrationsShareFile = $IntegrationsShareFile -replace ' ', '%20'
            $IntegrationsShareFileLink = '<a href="file:///' + $IntegrationsShareFile + $IntegrationsShareFileLink
            $MailBody += '<tr><td nowrap>' + $File.CreationTime.ToString() + ' </td><td nowrap>' + $IntegrationsShareFileLink + '</td></tr>'
        }
    }

    # Send email if there are errors
    if ($Errors -ne 0) {
        $MailBody += '</table>'
    
        foreach ($MailTo in $NotificationAddresses.Split(";")) {
            if ($MailTo.Trim().Length -ne 0) {
                $SendMailMessageProps = @{
                    From       = "$SMTPFromName <$SMTPFrom>"
                    To         = $MailTo
                    Subject    = "Antura - $Aliasname - Integration files that Import has been aborted."
                    Body       = $MailBody
                    BodyAsHtml = $true
                    SmtpServer = $SMTPServer
                }
                Send-MailMessage @SendMailMessageProps
            }
        }
    }
}

[
	{
		"mailto_test": "test@testson.com",
		"servername": "Server1",
		"mailfrom": "AnturaGFTest@home.com",
		"mailfromname": "AnturaGF (Test)",
		"aliasname": "AnturaGroupFunctionsProd",
		"emailbody_test": "AnturaGroupFunctionsTest"
	}
]
[
	{
		"mailto_prod": "test@testson.com",
		"servername": "Server2",
		"mailfrom": "AnturaGF@home.com",
		"mailfromname": "AnturaGF (Prod)",
		"aliasname": "AnturaGroupFunctionsProd",
		"emailbody_prod": "Group Functions [Prod]"
	}
]

You’ve posted a lot of code, and I’ve not read it all, but most likely it’s the way you’re structuring your JSON that’s making it diffcult to access the objects’ properties.

For multiple servers, consider something like this:

{
	"Server1": {
		"mailto_test": "test@testson.com",
		"mailfrom": "AnturaGFTest@home.com",
		"mailfromname": "AnturaGF (Test)",
		"aliasname": "AnturaGroupFunctionsProd",
		"emailbody_test": "AnturaGroupFunctionsTest"
	},
    "Server2": {
		"mailto_test": "test2@testson.com",
		"mailfrom": "AnturaGFTest@home.com",
		"mailfromname": "AnturaGF (Test)",
		"aliasname": "AnturaGroupFunctionsProd",
		"emailbody_test": "AnturaGroupFunctionsTest"
	}
}

Then you can use dot notation with the server name to access the properties for that server:

$servers = Get-Content .\servers.json | ConvertFrom-Json
$servers.Server1.mailto_test
$servers.Server2.mailto_test

As an alternative to JSON you may want to look into PowerShell data files. I generally find them better for this sort of task as they’re easier to read and more easily commented:

@{
    # These are the details for Server1
	"Server1" = @{
		mailto_test    = "test@testson.com"
		mailfrom       = "AnturaGFTest@home.com"
		mailfromname   = "AnturaGF (Test)"
		aliasname      = "AnturaGroupFunctionsProd"
		emailbody_test = "AnturaGroupFunctionsTest"
	}
    # These are the details for Server2
    "Server2" = @{
		mailto_test    = "test2@testson.com"
		mailfrom       = "AnturaGFTest@home.com"
		mailfromname   = "AnturaGF (Test)"
		aliasname      = "AnturaGroupFunctionsProd"
		emailbody_test = "AnturaGroupFunctionsTest"
	}
}

$servers = Import-PowerShellDataFile .\servers.psd1
$servers.Server1.mailto_test
$servers.Server2.mailto_test
1 Like

Thanks. I will take a look at the difference and make a choice.