Test-SMTPGraphRelay.ps1 gelöscht
This commit is contained in:
@@ -1,589 +0,0 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Health Check für SMTPGraphRelay.
|
||||
|
||||
.DESCRIPTION
|
||||
Prüft die lokale SMTPGraphRelay-Installation ohne Änderungen vorzunehmen.
|
||||
|
||||
Standardprüfungen:
|
||||
- Windows PowerShell 5.1
|
||||
- Administratorstatus
|
||||
- config.json
|
||||
- Microsoft.Graph.Authentication Modul
|
||||
- Zertifikat + Private Key + Ablaufdatum
|
||||
- Verzeichnisse und Schreibrechte
|
||||
- Scheduled Task
|
||||
- SMTP Listener
|
||||
- Queue / Failed Queue
|
||||
- App-only Microsoft Graph Anmeldung
|
||||
|
||||
Optional:
|
||||
- echte SMTP-Testmail über das lokale Relay
|
||||
|
||||
.EXAMPLE
|
||||
.\Test-SMTPGraphRelay.ps1
|
||||
|
||||
.EXAMPLE
|
||||
.\Test-SMTPGraphRelay.ps1 -SendTestMail -TestRecipient manuel.maier@maieredv.de
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$ConfigPath = "$PSScriptRoot\config.json",
|
||||
|
||||
[switch]$SendTestMail,
|
||||
|
||||
[string]$TestRecipient,
|
||||
|
||||
[int]$QueueWarningAgeMinutes = 30,
|
||||
|
||||
[int]$FailedWarningCount = 1
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
$script:OkCount = 0
|
||||
$script:WarnCount = 0
|
||||
$script:FailCount = 0
|
||||
|
||||
function Write-Result {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet("OK","WARN","FAIL","INFO")]
|
||||
[string]$Status,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message
|
||||
)
|
||||
|
||||
switch ($Status) {
|
||||
"OK" {
|
||||
$script:OkCount++
|
||||
Write-Host "[OK] $Message" -ForegroundColor Green
|
||||
}
|
||||
"WARN" {
|
||||
$script:WarnCount++
|
||||
Write-Host "[WARN] $Message" -ForegroundColor Yellow
|
||||
}
|
||||
"FAIL" {
|
||||
$script:FailCount++
|
||||
Write-Host "[FAIL] $Message" -ForegroundColor Red
|
||||
}
|
||||
"INFO" {
|
||||
Write-Host "[INFO] $Message" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Resolve-ConfigPath {
|
||||
param([Parameter(Mandatory)][string]$Path)
|
||||
|
||||
if ([IO.Path]::IsPathRooted($Path)) {
|
||||
return $Path
|
||||
}
|
||||
|
||||
return Join-Path $PSScriptRoot $Path
|
||||
}
|
||||
|
||||
function Test-IsAdministrator {
|
||||
try {
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Test-DirectoryWritable {
|
||||
param([Parameter(Mandatory)][string]$Path)
|
||||
|
||||
try {
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
return $false
|
||||
}
|
||||
|
||||
$testFile = Join-Path $Path (".healthcheck-{0}.tmp" -f [guid]::NewGuid().ToString("N"))
|
||||
[IO.File]::WriteAllText($testFile, "SMTPGraphRelay health check")
|
||||
Remove-Item -LiteralPath $testFile -Force
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Send-RawSmtpTestMail {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$Server,
|
||||
[Parameter(Mandatory)][int]$Port,
|
||||
[Parameter(Mandatory)][string]$From,
|
||||
[Parameter(Mandatory)][string]$To
|
||||
)
|
||||
|
||||
$client = New-Object System.Net.Sockets.TcpClient
|
||||
|
||||
try {
|
||||
$connect = $client.BeginConnect($Server, $Port, $null, $null)
|
||||
|
||||
if (-not $connect.AsyncWaitHandle.WaitOne(5000)) {
|
||||
throw "Timeout beim Verbindungsaufbau zu $Server`:$Port"
|
||||
}
|
||||
|
||||
$client.EndConnect($connect)
|
||||
|
||||
$stream = $client.GetStream()
|
||||
$stream.ReadTimeout = 5000
|
||||
$stream.WriteTimeout = 5000
|
||||
|
||||
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::ASCII)
|
||||
$writer = New-Object System.IO.StreamWriter($stream, [System.Text.Encoding]::ASCII)
|
||||
$writer.NewLine = "`r`n"
|
||||
$writer.AutoFlush = $true
|
||||
|
||||
function Read-SmtpResponse {
|
||||
param([int[]]$ExpectedCodes)
|
||||
|
||||
$lines = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
while ($true) {
|
||||
$line = $reader.ReadLine()
|
||||
|
||||
if ($null -eq $line) {
|
||||
throw "SMTP-Verbindung unerwartet geschlossen."
|
||||
}
|
||||
|
||||
$lines.Add($line)
|
||||
|
||||
if ($line -match '^(\d{3})([ -])') {
|
||||
$code = [int]$matches[1]
|
||||
$separator = $matches[2]
|
||||
|
||||
if ($separator -eq " ") {
|
||||
if ($ExpectedCodes -notcontains $code) {
|
||||
throw "Unerwartete SMTP-Antwort: $($lines -join ' | ')"
|
||||
}
|
||||
|
||||
return ($lines -join " | ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(220))
|
||||
|
||||
$writer.WriteLine("EHLO localhost")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(250))
|
||||
|
||||
$writer.WriteLine("MAIL FROM:<$From>")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(250))
|
||||
|
||||
$writer.WriteLine("RCPT TO:<$To>")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(250))
|
||||
|
||||
$writer.WriteLine("DATA")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(354))
|
||||
|
||||
$subject = "SMTPGraphRelay Health Check $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
|
||||
$writer.WriteLine("From: <$From>")
|
||||
$writer.WriteLine("To: <$To>")
|
||||
$writer.WriteLine("Subject: $subject")
|
||||
$writer.WriteLine("Date: $([DateTime]::Now.ToString('ddd, dd MMM yyyy HH:mm:ss zzz', [Globalization.CultureInfo]::InvariantCulture))")
|
||||
$writer.WriteLine("Message-ID: <$([guid]::NewGuid().ToString('N'))@smtpgraphrelay-healthcheck>")
|
||||
$writer.WriteLine("MIME-Version: 1.0")
|
||||
$writer.WriteLine("Content-Type: text/plain; charset=utf-8")
|
||||
$writer.WriteLine("")
|
||||
$writer.WriteLine("SMTPGraphRelay Health Check")
|
||||
$writer.WriteLine("")
|
||||
$writer.WriteLine("Zeit: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')")
|
||||
$writer.WriteLine("Host: $env:COMPUTERNAME")
|
||||
$writer.WriteLine(".")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(250))
|
||||
|
||||
$writer.WriteLine("QUIT")
|
||||
[void](Read-SmtpResponse -ExpectedCodes @(221))
|
||||
|
||||
return $true
|
||||
}
|
||||
finally {
|
||||
try { $client.Close() } catch {}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "==========================================================" -ForegroundColor Cyan
|
||||
Write-Host " SMTPGraphRelay - Health Check" -ForegroundColor Cyan
|
||||
Write-Host "==========================================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PowerShell / Rechte
|
||||
# ---------------------------------------------------------------------------
|
||||
if ($PSVersionTable.PSEdition -eq "Desktop" -and $PSVersionTable.PSVersion.Major -eq 5) {
|
||||
Write-Result OK "Windows PowerShell $($PSVersionTable.PSVersion) erkannt."
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Dieses Tool sollte mit Windows PowerShell 5.1 laufen. Erkannt: $($PSVersionTable.PSEdition) $($PSVersionTable.PSVersion)"
|
||||
}
|
||||
|
||||
if (Test-IsAdministrator) {
|
||||
Write-Result OK "PowerShell läuft als Administrator."
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "PowerShell läuft nicht als Administrator. Einige Prüfungen können eingeschränkt sein."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Config
|
||||
# ---------------------------------------------------------------------------
|
||||
if (-not (Test-Path -LiteralPath $ConfigPath)) {
|
||||
Write-Result FAIL "config.json nicht gefunden: $ConfigPath"
|
||||
Write-Host ""
|
||||
Write-Host "Health Check abgebrochen, da ohne Config keine weiteren Prüfungen möglich sind." -ForegroundColor Red
|
||||
exit 2
|
||||
}
|
||||
|
||||
try {
|
||||
$config = Get-Content -LiteralPath $ConfigPath -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
Write-Result OK "config.json konnte gelesen und geparst werden."
|
||||
}
|
||||
catch {
|
||||
Write-Result FAIL "config.json ist ungültig: $($_.Exception.Message)"
|
||||
exit 2
|
||||
}
|
||||
|
||||
$requiredConfig = @(
|
||||
"Smtp.ListenAddress",
|
||||
"Smtp.Port",
|
||||
"Graph.TenantId",
|
||||
"Graph.ClientId",
|
||||
"Graph.CertificateThumbprint",
|
||||
"Graph.SenderMailbox",
|
||||
"Paths.Queue",
|
||||
"Paths.Failed",
|
||||
"Paths.Logs"
|
||||
)
|
||||
|
||||
$configMissing = $false
|
||||
|
||||
foreach ($item in $requiredConfig) {
|
||||
$parts = $item -split '\.'
|
||||
$value = $config
|
||||
|
||||
foreach ($part in $parts) {
|
||||
if ($null -eq $value -or -not ($value.PSObject.Properties.Name -contains $part)) {
|
||||
$value = $null
|
||||
break
|
||||
}
|
||||
|
||||
$value = $value.$part
|
||||
}
|
||||
|
||||
if ($null -eq $value -or ([string]$value).Trim().Length -eq 0) {
|
||||
Write-Result FAIL "Config-Wert fehlt: $item"
|
||||
$configMissing = $true
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $configMissing) {
|
||||
Write-Result OK "Alle erforderlichen Config-Werte sind vorhanden."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Module
|
||||
# ---------------------------------------------------------------------------
|
||||
$graphModule = Get-Module -ListAvailable -Name Microsoft.Graph.Authentication |
|
||||
Sort-Object Version -Descending |
|
||||
Select-Object -First 1
|
||||
|
||||
if ($graphModule) {
|
||||
Write-Result OK "Microsoft.Graph.Authentication $($graphModule.Version) gefunden: $($graphModule.ModuleBase)"
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Microsoft.Graph.Authentication ist nicht installiert."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Zertifikat
|
||||
# ---------------------------------------------------------------------------
|
||||
$cert = $null
|
||||
$certPath = "Cert:\LocalMachine\My\$($config.Graph.CertificateThumbprint)"
|
||||
|
||||
try {
|
||||
$cert = Get-Item -LiteralPath $certPath -ErrorAction Stop
|
||||
Write-Result OK "Relay-Zertifikat gefunden: $($cert.Thumbprint)"
|
||||
|
||||
if ($cert.HasPrivateKey) {
|
||||
Write-Result OK "Zertifikat besitzt einen privaten Schlüssel."
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Zertifikat besitzt keinen privaten Schlüssel."
|
||||
}
|
||||
|
||||
$daysRemaining = [Math]::Floor(($cert.NotAfter.ToUniversalTime() - [DateTime]::UtcNow).TotalDays)
|
||||
|
||||
if ($daysRemaining -lt 0) {
|
||||
Write-Result FAIL "Zertifikat ist abgelaufen seit $($cert.NotAfter)."
|
||||
}
|
||||
elseif ($daysRemaining -le 14) {
|
||||
Write-Result FAIL "Zertifikat läuft in $daysRemaining Tagen ab ($($cert.NotAfter))."
|
||||
}
|
||||
elseif ($daysRemaining -le 60) {
|
||||
Write-Result WARN "Zertifikat läuft in $daysRemaining Tagen ab ($($cert.NotAfter))."
|
||||
}
|
||||
else {
|
||||
Write-Result OK "Zertifikat gültig bis $($cert.NotAfter) ($daysRemaining Tage verbleibend)."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Result FAIL "Relay-Zertifikat nicht gefunden oder nicht lesbar: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pfade / Queue
|
||||
# ---------------------------------------------------------------------------
|
||||
$queueRoot = Resolve-ConfigPath $config.Paths.Queue
|
||||
$failedDir = Resolve-ConfigPath $config.Paths.Failed
|
||||
$logsDir = Resolve-ConfigPath $config.Paths.Logs
|
||||
|
||||
$queueIncoming = Join-Path $queueRoot "incoming"
|
||||
$queuePending = Join-Path $queueRoot "pending"
|
||||
$queueProcessing = Join-Path $queueRoot "processing"
|
||||
|
||||
foreach ($entry in @(
|
||||
@{ Name = "Queue Root"; Path = $queueRoot },
|
||||
@{ Name = "Queue incoming"; Path = $queueIncoming },
|
||||
@{ Name = "Queue pending"; Path = $queuePending },
|
||||
@{ Name = "Queue processing"; Path = $queueProcessing },
|
||||
@{ Name = "Failed"; Path = $failedDir },
|
||||
@{ Name = "Logs"; Path = $logsDir }
|
||||
)) {
|
||||
if (Test-Path -LiteralPath $entry.Path) {
|
||||
if (Test-DirectoryWritable -Path $entry.Path) {
|
||||
Write-Result OK "$($entry.Name) vorhanden und beschreibbar: $($entry.Path)"
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "$($entry.Name) vorhanden, aber nicht beschreibbar: $($entry.Path)"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "$($entry.Name) fehlt: $($entry.Path)"
|
||||
}
|
||||
}
|
||||
|
||||
$pendingFiles = @()
|
||||
$processingFiles = @()
|
||||
$failedFiles = @()
|
||||
|
||||
if (Test-Path -LiteralPath $queuePending) {
|
||||
$pendingFiles = @(Get-ChildItem -LiteralPath $queuePending -Filter "*.eml" -File -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
if (Test-Path -LiteralPath $queueProcessing) {
|
||||
$processingFiles = @(Get-ChildItem -LiteralPath $queueProcessing -Filter "*.eml" -File -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
if (Test-Path -LiteralPath $failedDir) {
|
||||
$failedFiles = @(Get-ChildItem -LiteralPath $failedDir -Filter "*.eml" -File -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
if ($pendingFiles.Count -eq 0) {
|
||||
Write-Result OK "Pending Queue ist leer."
|
||||
}
|
||||
else {
|
||||
$oldestPending = $pendingFiles | Sort-Object LastWriteTime | Select-Object -First 1
|
||||
$ageMinutes = [Math]::Floor(((Get-Date) - $oldestPending.LastWriteTime).TotalMinutes)
|
||||
|
||||
if ($ageMinutes -ge $QueueWarningAgeMinutes) {
|
||||
Write-Result WARN "$($pendingFiles.Count) Mail(s) in pending; älteste ist $ageMinutes Minuten alt."
|
||||
}
|
||||
else {
|
||||
Write-Result INFO "$($pendingFiles.Count) Mail(s) in pending; älteste ist $ageMinutes Minuten alt."
|
||||
}
|
||||
}
|
||||
|
||||
if ($processingFiles.Count -gt 0) {
|
||||
Write-Result WARN "$($processingFiles.Count) Mail(s) liegen aktuell in processing."
|
||||
}
|
||||
else {
|
||||
Write-Result OK "Processing Queue ist leer."
|
||||
}
|
||||
|
||||
if ($failedFiles.Count -ge $FailedWarningCount) {
|
||||
Write-Result WARN "$($failedFiles.Count) Mail(s) liegen in failed."
|
||||
}
|
||||
else {
|
||||
Write-Result OK "Failed Queue enthält $($failedFiles.Count) Mail(s)."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Scheduled Task
|
||||
# ---------------------------------------------------------------------------
|
||||
$task = Get-ScheduledTask -TaskName "SMTPGraphRelay" -ErrorAction SilentlyContinue
|
||||
|
||||
if ($task) {
|
||||
Write-Result OK "Scheduled Task 'SMTPGraphRelay' vorhanden."
|
||||
|
||||
$taskInfo = Get-ScheduledTaskInfo -TaskName "SMTPGraphRelay"
|
||||
|
||||
if ($task.State -eq "Running") {
|
||||
Write-Result OK "Scheduled Task läuft."
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "Scheduled Task State: $($task.State)"
|
||||
}
|
||||
|
||||
if ($taskInfo.LastTaskResult -eq 0 -or $taskInfo.LastTaskResult -eq 267009) {
|
||||
Write-Result OK "LastTaskResult: $($taskInfo.LastTaskResult)"
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "LastTaskResult: $($taskInfo.LastTaskResult)"
|
||||
}
|
||||
|
||||
$action = $task.Actions | Select-Object -First 1
|
||||
|
||||
if ($action.Execute -match 'WindowsPowerShell\\v1\.0\\powershell\.exe$') {
|
||||
Write-Result OK "Scheduled Task verwendet Windows PowerShell 5.1."
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "Scheduled Task verwendet unerwartetes PowerShell-Binary: $($action.Execute)"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Scheduled Task 'SMTPGraphRelay' wurde nicht gefunden."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# SMTP Listener
|
||||
# ---------------------------------------------------------------------------
|
||||
$listenPort = [int]$config.Smtp.Port
|
||||
|
||||
try {
|
||||
$listeners = @(Get-NetTCPConnection -LocalPort $listenPort -State Listen -ErrorAction Stop)
|
||||
|
||||
if ($listeners.Count -gt 0) {
|
||||
$owners = @($listeners | Select-Object -ExpandProperty OwningProcess -Unique)
|
||||
Write-Result OK "SMTP Listener aktiv auf TCP $listenPort (PID: $($owners -join ', '))."
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Kein Listener auf TCP $listenPort."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Fallback falls Get-NetTCPConnection nicht verfügbar / eingeschränkt.
|
||||
try {
|
||||
$tcp = New-Object System.Net.Sockets.TcpClient
|
||||
$result = $tcp.BeginConnect("127.0.0.1", $listenPort, $null, $null)
|
||||
|
||||
if ($result.AsyncWaitHandle.WaitOne(2000)) {
|
||||
$tcp.EndConnect($result)
|
||||
Write-Result OK "SMTP Listener auf 127.0.0.1:$listenPort erreichbar."
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "SMTP Listener auf 127.0.0.1:$listenPort nicht erreichbar."
|
||||
}
|
||||
|
||||
$tcp.Close()
|
||||
}
|
||||
catch {
|
||||
Write-Result FAIL "SMTP Listener auf TCP $listenPort nicht erreichbar."
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Graph App-only Auth
|
||||
# ---------------------------------------------------------------------------
|
||||
if ($graphModule -and $cert -and $cert.HasPrivateKey) {
|
||||
try {
|
||||
Import-Module Microsoft.Graph.Authentication -ErrorAction Stop
|
||||
|
||||
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
Connect-MgGraph `
|
||||
-TenantId $config.Graph.TenantId `
|
||||
-ClientId $config.Graph.ClientId `
|
||||
-Certificate $cert `
|
||||
-NoWelcome | Out-Null
|
||||
|
||||
$ctx = Get-MgContext
|
||||
|
||||
if ($ctx -and
|
||||
$ctx.AuthType -eq "AppOnly" -and
|
||||
$ctx.ClientId -eq $config.Graph.ClientId -and
|
||||
$ctx.TenantId -eq $config.Graph.TenantId) {
|
||||
|
||||
Write-Result OK "Microsoft Graph App-only Anmeldung erfolgreich."
|
||||
}
|
||||
else {
|
||||
Write-Result FAIL "Graph-Verbindung vorhanden, aber Kontext entspricht nicht der Relay-App."
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Result FAIL "Microsoft Graph App-only Anmeldung fehlgeschlagen: $($_.Exception.Message)"
|
||||
}
|
||||
finally {
|
||||
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Result WARN "Graph App-only Test übersprungen, da Modul/Zertifikat/Private Key nicht vollständig verfügbar sind."
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Optionale echte SMTP-Testmail
|
||||
# ---------------------------------------------------------------------------
|
||||
if ($SendTestMail) {
|
||||
if ([string]::IsNullOrWhiteSpace($TestRecipient)) {
|
||||
Write-Result FAIL "-SendTestMail wurde angegeben, aber -TestRecipient fehlt."
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$testFrom = [string]$config.Graph.SenderMailbox
|
||||
|
||||
Write-Result INFO "Sende SMTP-Testmail über 127.0.0.1:$listenPort an $TestRecipient ..."
|
||||
|
||||
[void](Send-RawSmtpTestMail `
|
||||
-Server "127.0.0.1" `
|
||||
-Port $listenPort `
|
||||
-From $testFrom `
|
||||
-To $TestRecipient)
|
||||
|
||||
Write-Result OK "SMTP-Testmail wurde vom Relay mit 250 Queued angenommen."
|
||||
Write-Result INFO "Die endgültige Graph-/M365-Zustellung bitte im Relay-Log bzw. Empfängerpostfach prüfen."
|
||||
}
|
||||
catch {
|
||||
Write-Result FAIL "SMTP-Testmail fehlgeschlagen: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Zusammenfassung
|
||||
# ---------------------------------------------------------------------------
|
||||
Write-Host ""
|
||||
Write-Host "==========================================================" -ForegroundColor Cyan
|
||||
Write-Host " Ergebnis" -ForegroundColor Cyan
|
||||
Write-Host "==========================================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
Write-Host (" OK: {0}" -f $script:OkCount) -ForegroundColor Green
|
||||
Write-Host (" WARN: {0}" -f $script:WarnCount) -ForegroundColor Yellow
|
||||
Write-Host (" FAIL: {0}" -f $script:FailCount) -ForegroundColor Red
|
||||
Write-Host ""
|
||||
|
||||
if ($script:FailCount -gt 0) {
|
||||
Write-Host "Gesamtstatus: FEHLER" -ForegroundColor Red
|
||||
exit 2
|
||||
}
|
||||
elseif ($script:WarnCount -gt 0) {
|
||||
Write-Host "Gesamtstatus: WARNUNG" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Gesamtstatus: OK" -ForegroundColor Green
|
||||
exit 0
|
||||
}
|
||||
Reference in New Issue
Block a user