Dateien nach "/" hochladen

This commit is contained in:
2026-08-13 23:10:22 +02:00
parent ba2cbd5730
commit 4d4ab979fa
2 changed files with 433 additions and 1 deletions
+95 -1
View File
@@ -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) {