Dateien nach "/" hochladen
This commit is contained in:
+95
-1
@@ -7,7 +7,7 @@
|
||||
Nimmt lokale SMTP-Mails an, speichert sie als .eml in einer Queue und sendet sie
|
||||
anschließend per Microsoft Graph sendMail mit App-only Zertifikatsauthentifizierung.
|
||||
|
||||
V1.3: parallele SMTP-Clients, separater Queue-Worker, robuste Queue, statuscodeabhängiger Graph-Retry
|
||||
V1.4: Zertifikatsüberwachung, parallele SMTP-Clients, separater Queue-Worker, robuste Queue und Graph-Retry
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
@@ -803,6 +803,80 @@ function Handle-SmtpClient {
|
||||
}
|
||||
|
||||
|
||||
function Get-RelayCertificateStatus {
|
||||
$thumbprint = [string]$script:Config.Graph.CertificateThumbprint
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($thumbprint)) {
|
||||
throw "Graph.CertificateThumbprint fehlt in config.json."
|
||||
}
|
||||
|
||||
$certPath = "Cert:\LocalMachine\My\$thumbprint"
|
||||
$cert = Get-Item -LiteralPath $certPath -ErrorAction Stop
|
||||
|
||||
if (-not $cert.HasPrivateKey) {
|
||||
throw "Relay-Zertifikat '$thumbprint' besitzt keinen privaten Schlüssel."
|
||||
}
|
||||
|
||||
$remaining = $cert.NotAfter.ToUniversalTime() - [DateTime]::UtcNow
|
||||
|
||||
return [pscustomobject]@{
|
||||
Certificate = $cert
|
||||
Thumbprint = $cert.Thumbprint
|
||||
Subject = $cert.Subject
|
||||
NotBefore = $cert.NotBefore
|
||||
NotAfter = $cert.NotAfter
|
||||
DaysRemaining = [Math]::Floor($remaining.TotalDays)
|
||||
HoursRemaining = [Math]::Floor($remaining.TotalHours)
|
||||
Expired = ($remaining.TotalSeconds -le 0)
|
||||
}
|
||||
}
|
||||
|
||||
function Test-RelayCertificateExpiry {
|
||||
param(
|
||||
[switch]$ForceLog
|
||||
)
|
||||
|
||||
try {
|
||||
$status = Get-RelayCertificateStatus
|
||||
|
||||
$warningDays = 60
|
||||
$criticalDays = 14
|
||||
|
||||
if ($script:Config.Graph.PSObject.Properties.Name -contains "CertificateWarningDays") {
|
||||
try { $warningDays = [int]$script:Config.Graph.CertificateWarningDays } catch {}
|
||||
}
|
||||
|
||||
if ($script:Config.Graph.PSObject.Properties.Name -contains "CertificateCriticalDays") {
|
||||
try { $criticalDays = [int]$script:Config.Graph.CertificateCriticalDays } catch {}
|
||||
}
|
||||
|
||||
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) {
|
||||
Write-Log ("KRITISCH: Graph-Zertifikat läuft 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) {
|
||||
Write-Log ("WARNUNG: Graph-Zertifikat läuft 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 gültig bis {0} ({1} Tage verbleibend)." -f `
|
||||
$status.NotAfter.ToString("yyyy-MM-dd HH:mm:ss"), $status.DaysRemaining)
|
||||
}
|
||||
|
||||
return $status
|
||||
}
|
||||
catch {
|
||||
Write-Log ("Zertifikatsprüfung fehlgeschlagen: {0}" -f $_.Exception.Message) "ERROR"
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Get-FunctionBootstrap {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -925,6 +999,21 @@ $script:Config = Get-Content -LiteralPath $ConfigPath -Raw -Encoding UTF8 | Conv
|
||||
New-Item -ItemType Directory -Path (Resolve-PathFromConfig $script:Config.Paths.Logs) -Force | Out-Null
|
||||
Initialize-QueueDirectories
|
||||
|
||||
# Zertifikat beim Start immer prüfen und Status protokollieren.
|
||||
[void](Test-RelayCertificateExpiry -ForceLog)
|
||||
|
||||
# Prüfintervall optional per config, Standard 12 Stunden.
|
||||
$script:CertificateCheckHours = 12
|
||||
if ($script:Config.Graph.PSObject.Properties.Name -contains "CertificateCheckHours") {
|
||||
try {
|
||||
$configuredHours = [int]$script:Config.Graph.CertificateCheckHours
|
||||
if ($configuredHours -ge 1 -and $configuredHours -le 168) {
|
||||
$script:CertificateCheckHours = $configuredHours
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
$script:NextCertificateCheck = (Get-Date).AddHours($script:CertificateCheckHours)
|
||||
|
||||
# MaxConcurrentClients ist optional, damit bestehende config.json-Dateien unverändert weiterlaufen.
|
||||
$script:MaxConcurrentClients = 20
|
||||
if ($script:Config.Smtp.PSObject.Properties.Name -contains "MaxConcurrentClients") {
|
||||
@@ -1040,6 +1129,11 @@ try {
|
||||
while ($true) {
|
||||
Remove-CompletedSmtpWorkers
|
||||
|
||||
if ((Get-Date) -ge $script:NextCertificateCheck) {
|
||||
[void](Test-RelayCertificateExpiry)
|
||||
$script:NextCertificateCheck = (Get-Date).AddHours($script:CertificateCheckHours)
|
||||
}
|
||||
|
||||
# Sollte der Queue-Worker unerwartet beendet werden, Relay nicht still
|
||||
# ohne Versand weiterlaufen lassen.
|
||||
if ($script:QueueAsyncResult.IsCompleted) {
|
||||
|
||||
Reference in New Issue
Block a user