diff --git a/SMTPGraphRelay.ps1 b/SMTPGraphRelay.ps1 index d990ad6..c92bd10 100644 --- a/SMTPGraphRelay.ps1 +++ b/SMTPGraphRelay.ps1 @@ -1,4 +1,4 @@ -[CmdletBinding()] +[CmdletBinding()] param([string]$ConfigPath = "$PSScriptRoot\config.json"); #Requires -Version 5.1 @@ -1160,9 +1160,41 @@ function Get-RelayCertificateStatus { }; } +function Send-CertificateAlertMail { + param([Parameter(Mandatory)][int]$DaysRemaining, [Parameter(Mandatory)][string]$Thumbprint); + + $alertMailbox =$null; + if ($script:Config.Graph.PSObject.Properties.Name -contains "AlertMailbox") { $alertMailbox = [string]$script:Config.Graph.AlertMailbox; } + if ([string]::IsNullOrWhiteSpace($alertMailbox)) { return; } + + $dirs = Get-QueueDirectories; + $queueId = New-QueueId; + $subject = "WICHTIG: SMTPGraphRelay Zertifikat laeuft ab ($env:COMPUTERNAME)"; + $body = "Hallo,`r`n`r`ndas Microsoft Graph Zertifikat ($Thumbprint) auf dem Server $env:COMPUTERNAME laeuft in$DaysRemaining Tagen ab.`r`n`r`nBitte das Setup-Skript (Setup-SMTPGraphRelay.ps1) starten und Modus [5] (Zertifikat erneuern) ausfuehren, damit der Mailversand nicht unterbrochen wird.`r`n`r`nViele Gruesse,`r`nSMTPGraphRelay"; + + $lines = New-Object System.Collections.Generic.List[string];$lines.Add("From: <$($script:Config.Graph.SenderMailbox)>"); + $lines.Add("To: <$alertMailbox>"); + $lines.Add("Subject: $subject"); + $lines.Add("MIME-Version: 1.0"); + $lines.Add("Content-Type: text/plain; charset=utf-8"); + $lines.Add(""); + $lines.Add($body); + + $meta = [ordered]@{ QueueId =$queueId; ReceivedUtc = [DateTime]::UtcNow.ToString("o"); RemoteAddress = "127.0.0.1"; AuthenticatedUser = "SystemAlert"; EnvelopeFrom = $script:Config.Graph.SenderMailbox; EnvelopeRecipients = @($alertMailbox); RetryCount = 0; NextAttemptUtc = [DateTime]::UtcNow.ToString("o"); }; + + $pendingEml = Join-Path ($dirs.Pending) "$queueId.eml"; + $pendingMeta = "$pendingEml.json"; + + try { + $raw = ($lines -join "`r`n") + "`r`n"; + [IO.File]::WriteAllText($pendingEml,$raw, [System.Text.Encoding]::UTF8); + $meta \vert{} ConvertTo-Json -Depth 5 \vert{} Set-Content -LiteralPath ($pendingMeta) -Encoding UTF8; + Write-Log "Zertifikats-Warnmail an $alertMailbox in die Queue gelegt (QueueID:$queueId)." "INFO"; + } catch { Write-Log "Fehler beim Erstellen der Warnmail: $($_.Exception.Message)" "ERROR"; } +} + function Test-RelayCertificateExpiry { param([switch]$ForceLog); - try { $status = Get-RelayCertificateStatus; $warningDays = 60; @@ -1173,22 +1205,23 @@ function Test-RelayCertificateExpiry { if ($status.Expired) { Write-Log ("KRITISCH: Graph-Zertifikat {0} ist seit {1} abgelaufen!" -f $status.Thumbprint, $status.NotAfter.ToString("yyyy-MM-dd HH:mm:ss")) "ERROR"; - return $status; - } - - if ($status.DaysRemaining -le $criticalDays) { + } elseif ($status.DaysRemaining -le$criticalDays) { Write-Log ("KRITISCH: Graph-Zertifikat laeuft in {0} Tagen ab ({1}). Bitte Zertifikat erneuern." -f $status.DaysRemaining, $status.NotAfter.ToString("yyyy-MM-dd HH:mm:ss")) "ERROR"; - } elseif ($status.DaysRemaining -le $warningDays) { + } elseif ($status.DaysRemaining -le$warningDays) { Write-Log ("WARNUNG: Graph-Zertifikat laeuft in {0} Tagen ab ({1}). Zertifikatsrotation einplanen." -f $status.DaysRemaining, $status.NotAfter.ToString("yyyy-MM-dd HH:mm:ss")) "WARN"; } elseif ($ForceLog) { Write-Log ("Graph-Zertifikat gueltig bis {0} ({1} Tage verbleibend)." -f $status.NotAfter.ToString("yyyy-MM-dd HH:mm:ss"), $status.DaysRemaining); } + if ($status.DaysRemaining -le $warningDays -and -not$status.Expired) { + if (-not $script:LastCertAlert) {$script:LastCertAlert = [DateTime]::MinValue; } + if ((Get-Date) -gt $script:LastCertAlert.AddDays(1)) { + Send-CertificateAlertMail -DaysRemaining ($status.DaysRemaining) -Thumbprint ($status.Thumbprint);$script:LastCertAlert = Get-Date; + } + } + return $status; - } catch { - Write-Log ("Zertifikatspruefung fehlgeschlagen: {0}" -f $_.Exception.Message) "ERROR"; - return $null; - } + } catch { Write-Log ("Zertifikatspruefung fehlgeschlagen: {0}" -f $_.Exception.Message) "ERROR"; return $null; } } function Get-FunctionBootstrap {