Dateien nach "/" hochladen

This commit is contained in:
2026-08-14 22:58:17 +02:00
parent 9d49321abc
commit f70ee9e763
3 changed files with 801 additions and 6 deletions
+98 -6
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.8: Failed-Queue-Verwaltung und kooperativer Graceful Shutdown; inklusive SMTP AUTH und V1.6 Queue-/Backpressure-Funktionen
V1.9: gezielte QA-/Failure-Mode-Testhooks; inklusive Failed-Queue, Graceful Shutdown, SMTP AUTH und Backpressure
#>
[CmdletBinding()]
@@ -580,6 +580,20 @@ function Send-QueuedMail {
}
try {
$debug = Get-DebugSettings
if ($debug.Enabled -and $debug.DelayBeforeGraphSendSeconds -gt 0) {
Write-Log ("[{0}] QA: Graph-Versand wird um {1} Sek. verzögert." -f `
$queueId, $debug.DelayBeforeGraphSendSeconds) "WARN"
Start-Sleep -Seconds ([int]$debug.DelayBeforeGraphSendSeconds)
}
if ($debug.Enabled -and $debug.SimulateGraphStatus -ge 400) {
Write-Log ("[{0}] QA: simulierter Graph HTTP {1}." -f `
$queueId, $debug.SimulateGraphStatus) "WARN"
throw ("QA simulated Graph HTTP {0}" -f $debug.SimulateGraphStatus)
}
Get-GraphConnection
$sender = [Uri]::EscapeDataString($script:Config.Graph.SenderMailbox)
@@ -1128,6 +1142,57 @@ function Invoke-SmtpAuthPlain {
}
}
function Get-DebugSettings {
$defaults = [ordered]@{
Enabled = $false
DelayBeforeGraphSendSeconds = 0
SimulateGraphStatus = 0
SimulateQueueWriteFailure = $false
OverridePendingCount = -1
OverrideFreeDiskSpaceMB = -1
}
try {
if (-not ($script:Config.PSObject.Properties.Name -contains "Debug") -or -not $script:Config.Debug) {
return [pscustomobject]$defaults
}
$d = $script:Config.Debug
if ($d.PSObject.Properties.Name -contains "Enabled") {
$defaults.Enabled = [bool]$d.Enabled
}
if ($d.PSObject.Properties.Name -contains "DelayBeforeGraphSendSeconds") {
$v = [int]$d.DelayBeforeGraphSendSeconds
if ($v -ge 0 -and $v -le 300) { $defaults.DelayBeforeGraphSendSeconds = $v }
}
if ($d.PSObject.Properties.Name -contains "SimulateGraphStatus") {
$v = [int]$d.SimulateGraphStatus
if ($v -eq 0 -or ($v -ge 400 -and $v -le 599)) { $defaults.SimulateGraphStatus = $v }
}
if ($d.PSObject.Properties.Name -contains "SimulateQueueWriteFailure") {
$defaults.SimulateQueueWriteFailure = [bool]$d.SimulateQueueWriteFailure
}
if ($d.PSObject.Properties.Name -contains "OverridePendingCount") {
$v = [int]$d.OverridePendingCount
if ($v -ge -1 -and $v -le 1000000) { $defaults.OverridePendingCount = $v }
}
if ($d.PSObject.Properties.Name -contains "OverrideFreeDiskSpaceMB") {
$v = [int]$d.OverrideFreeDiskSpaceMB
if ($v -ge -1 -and $v -le 1048576) { $defaults.OverrideFreeDiskSpaceMB = $v }
}
}
catch {}
return [pscustomobject]$defaults
}
function Get-SmtpLimits {
$maxRecipients = 50
$maxMessagesPerConnection = 25
@@ -1169,10 +1234,18 @@ function Get-QueuePressure {
$dirs = Get-QueueDirectories
$limits = Get-SmtpLimits
$debug = Get-DebugSettings
try {
$pendingCount = @(
Get-ChildItem -LiteralPath $dirs.Pending -Filter "*.eml" -File -ErrorAction Stop
).Count
if ($debug.Enabled -and $debug.OverridePendingCount -ge 0) {
$pendingCount = [int]$debug.OverridePendingCount
Write-Log ("QA: PendingCount wird mit {0} simuliert." -f $pendingCount) "WARN"
}
else {
$pendingCount = @(
Get-ChildItem -LiteralPath $dirs.Pending -Filter "*.eml" -File -ErrorAction Stop
).Count
}
}
catch {
return [pscustomobject]@{
@@ -1203,7 +1276,13 @@ function Get-QueuePressure {
if ($root) {
$driveInfo = New-Object System.IO.DriveInfo($root)
if ($driveInfo.IsReady) {
$freeSpaceMB = [Math]::Floor($driveInfo.AvailableFreeSpace / 1MB)
if ($debug.Enabled -and $debug.OverrideFreeDiskSpaceMB -ge 0) {
$freeSpaceMB = [int]$debug.OverrideFreeDiskSpaceMB
Write-Log ("QA: freier Speicher wird mit {0} MB simuliert." -f $freeSpaceMB) "WARN"
}
else {
$freeSpaceMB = [Math]::Floor($driveInfo.AvailableFreeSpace / 1MB)
}
}
}
}
@@ -1290,6 +1369,12 @@ function Save-SmtpMessage {
}
try {
$debug = Get-DebugSettings
if ($debug.Enabled -and $debug.SimulateQueueWriteFailure) {
Write-Log ("[{0}] QA: simulierter Queue-Schreibfehler." -f $QueueId) "WARN"
throw "QA simulated queue write failure"
}
# Erst vollständig in incoming schreiben.
[IO.File]::WriteAllText($incomingEmlTmp, $raw, $utf8NoBom)
$meta | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $incomingMetaTmp -Encoding UTF8
@@ -1918,6 +2003,7 @@ $smtpFunctionNames = @(
"Test-SmtpCredentials",
"Invoke-SmtpAuthLogin",
"Invoke-SmtpAuthPlain",
"Get-DebugSettings",
"Get-SmtpLimits",
"Get-QueuePressure",
"Save-SmtpMessage",
@@ -1958,6 +2044,7 @@ $queueFunctionNames = @(
"Get-QueueDirectories",
"Get-GraphFailureInfo",
"Get-RetryDecision",
"Get-DebugSettings",
"Move-QueueItem",
"Send-QueuedMail",
"Process-Queue"
@@ -2013,7 +2100,7 @@ $listenIp = [System.Net.IPAddress]::Parse($script:Config.Smtp.ListenAddress)
$listener = [System.Net.Sockets.TcpListener]::new($listenIp, [int]$script:Config.Smtp.Port)
$listener.Start()
Write-Log "SMTPGraphRelay V1.8 gestartet auf $($script:Config.Smtp.ListenAddress):$($script:Config.Smtp.Port)"
Write-Log "SMTPGraphRelay V1.9 gestartet auf $($script:Config.Smtp.ListenAddress):$($script:Config.Smtp.Port)"
Write-Log "Graph-Absender: $($script:Config.Graph.SenderMailbox)"
Write-Log "Maximale parallele SMTP-Verbindungen: $script:MaxConcurrentClients"
Write-Log "Queue-/Graph-Worker läuft separat vom SMTP-Listener."
@@ -2032,6 +2119,11 @@ Write-Log ("SMTP-AUTH: {0}; {1} Benutzer; max. {2} Fehlversuche/Verbindung." -f
Write-Log ("Graceful Shutdown: bis zu {0} Sekunden für aktive Sessions/Worker." -f `
$script:GracefulShutdownSeconds)
$debugSettings = Get-DebugSettings
if ($debugSettings.Enabled) {
Write-Log "ACHTUNG: QA-/Debug-Testmodus ist AKTIV." "WARN"
}
$logSettings = Get-LogSettings
Write-Log ("Log-Rotation: max. {0} MB pro Datei, Aufbewahrung {1} Tage." -f `
$logSettings.MaxFileSizeMB, $logSettings.RetentionDays)