Setup-SMTPGraphRelay.ps1 aktualisiert

This commit is contained in:
manuel.maier committed 2026-10-13 11:24:25 +02:00
1 parent c7d547a45f
commit 722a80f613
1 file changed
+214 -5
+214 -5
View File
@@ -1493,7 +1493,8 @@ function Retry-FailedQueueEntry {
if ($meta.PSObject.Properties.Name -contains "RetryCount") { if ($meta.PSObject.Properties.Name -contains "RetryCount") {
$meta.RetryCount = 0 $meta.RetryCount = 0
} else {$meta | Add-Member -NotePropertyName RetryCount -NotePropertyValue 0 } else {
$meta | Add-Member -NotePropertyName RetryCount -NotePropertyValue 0
} }
$now = [DateTime]::UtcNow.ToString("o") $now = [DateTime]::UtcNow.ToString("o")
@@ -1621,11 +1622,13 @@ function Manage-FailedQueue {
Write-Ok "Failed Queue ist leer." Write-Ok "Failed Queue ist leer."
} }
elseif (Confirm-Yes "Alle $($entries.Count) Failed-Mails erneut zustellen?") { elseif (Confirm-Yes "Alle $($entries.Count) Failed-Mails erneut zustellen?") {
$ok = 0$failed = 0 $ok = 0
$failed = 0
foreach ($entry in $entries) { foreach ($entry in $entries) {
try { try {
Retry-FailedQueueEntry -Config $config -Entry $entry$ok++ Retry-FailedQueueEntry -Config $config -Entry $entry
$ok++
} }
catch { catch {
$failed++ $failed++
@@ -1670,7 +1673,8 @@ function Manage-FailedQueue {
foreach ($entry in $entries) { foreach ($entry in $entries) {
try { try {
Remove-FailedQueueEntry -Entry $entry$ok++ Remove-FailedQueueEntry -Entry $entry
$ok++
} }
catch { catch {
Write-Warn "[$($entry.QueueId)] konnte nicht gelöscht werden." Write-Warn "[$($entry.QueueId)] konnte nicht gelöscht werden."
@@ -1936,4 +1940,209 @@ function Manage-SmtpAuth {
# Config nach jeder Änderung neu laden, damit Serialisierung/Arrays exakt # Config nach jeder Änderung neu laden, damit Serialisierung/Arrays exakt
# dem installierten Zustand entsprechen. # dem installierten Zustand entsprechen.
$config = Get-Rel $config = Get-RelayConfig -TargetPath$InstallPath
$config = Ensure-SmtpAuthConfig -Config$config
}
}
function Invoke-FailureModeTests {
Write-Title "SMTPGraphRelay - Failure Mode QA"
$tester = Join-Path$InstallPath "Test-SMTPGraphRelay-FailureModes.ps1"
if (-not (Test-Path -LiteralPath $tester)) {
Write-Fail "Test-SMTPGraphRelay-FailureModes.ps1 ist nicht installiert."
return
}
& $tester -InstallPath$InstallPath
}
function Uninstall-Relay {
Write-Title "SMTPGraphRelay - Deinstallation"
$config = Get-RelayConfig -TargetPath$InstallPath
Write-Warn "Lokale Deinstallation entfernt Task, Firewallregel und auf Wunsch das lokale Zertifikat."
if (-not (Confirm-Yes "Lokale SMTPGraphRelay-Installation wirklich entfernen?")) {
return
}
Stop-RelayTask
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
Write-Ok "Scheduled Task entfernt."
Get-NetFirewallRule -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "SMTPGraphRelay TCP *" } |
Remove-NetFirewallRule -ErrorAction SilentlyContinue
Write-Ok "SMTPGraphRelay Firewallregeln entfernt."
if ($config -and$config.Graph.CertificateThumbprint) {
if (Confirm-Yes "Lokales Relay-Zertifikat $($config.Graph.CertificateThumbprint) entfernen?") {
Remove-Item -LiteralPath "Cert:\LocalMachine\My\$($config.Graph.CertificateThumbprint)" -Force -ErrorAction SilentlyContinue
Write-Ok "Lokales Zertifikat entfernt."
}
}
if ($config -and (Confirm-Yes "Auch Entra-App entfernen?")) {
Ensure-Modules
Write-Warn "Cloud-Cleanup ist destruktiv und betrifft die konfigurierte ClientId:"
Write-Host " $($config.Graph.ClientId)" -ForegroundColor Yellow
if (Confirm-Yes "Cloud-Cleanup endgültig bestätigen?") {
Connect-RelayGraphAdmin -TenantId $config.Graph.TenantId
try {
$app = Get-MgApplication -Filter "appId eq '$($config.Graph.ClientId)'" -Property "id,appId,displayName" | Select-Object -First 1
$sp = Get-MgServicePrincipal -Filter "appId eq '$($config.Graph.ClientId)'" -Property "id,appId,displayName" | Select-Object -First 1
if ($sp) {
Remove-MgServicePrincipal -ServicePrincipalId $sp.Id -ErrorAction SilentlyContinue
Write-Ok "Entra Service Principal entfernt."
}
if ($app) {
Remove-MgApplication -ApplicationId $app.Id -ErrorAction SilentlyContinue
Write-Ok "Entra App Registration entfernt."
}
}
finally {
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
}
}
}
# Programmdateien. Wenn der Installer selbst aus dem Zielordner läuft, kann er
# sich nicht zuverlässig selbst löschen. Dann bleiben Setup + Ordner bis nach Ende stehen.
$currentInstaller = [IO.Path]::GetFullPath($PSCommandPath)
$targetFull = [IO.Path]::GetFullPath($InstallPath)
foreach ($item in Get-ChildItem -LiteralPath$InstallPath -Force -ErrorAction SilentlyContinue) {
try {
if ($item.FullName -eq$currentInstaller) {
continue
}
Remove-Item -LiteralPath $item.FullName -Recurse -Force -ErrorAction Stop
}
catch {
Write-Warn "Konnte nicht entfernen: $($item.FullName)"
}
}
Write-Ok "Lokale Programmdateien entfernt."
if ($currentInstaller.StartsWith($targetFull, [StringComparison]::OrdinalIgnoreCase)) {
Write-Warn "Der aktuell laufende Installer bleibt übrig. Nach dem Beenden kann '$InstallPath' manuell gelöscht werden."
}
Write-Title "Deinstallation abgeschlossen"
}
function Show-Status {
Write-Title "SMTPGraphRelay - Status"
$configPath = Join-Path $InstallPath$ConfigFileName
Write-Host "Installationspfad: $InstallPath"
if (Test-Path -LiteralPath $configPath) {
Write-Ok "config.json vorhanden."
try {
$config = Get-RelayConfig -TargetPath$InstallPath
Write-Host " Sender: $($config.Graph.SenderMailbox) (ForceSender: $($config.Graph.ForceSender))"
Write-Host " SMTP: $($config.Smtp.ListenAddress):$($config.Smtp.Port)"
Write-Host " Client: $($config.Graph.ClientId)"
if ($config.Smtp.PSObject.Properties.Name -contains "RequireAuth") {
$authText = if ([bool]$config.Smtp.RequireAuth) { "erforderlich" } else { "optional / aus" }
$authUsers = if ($config.Smtp.PSObject.Properties.Name -contains "AuthUsers") { @($config.Smtp.AuthUsers).Count } else { 0 }
Write-Host " AUTH: $authText ($authUsers Benutzer)"
}
try {
$failedCount = @(Get-FailedQueueEntries -Config$config).Count
Write-Host " Failed: $failedCount Mail(s)"
} catch {}
} catch {}
}
else {
Write-Warn "Keine config.json vorhanden."
}
$task = Get-ScheduledTask -TaskName$TaskName -ErrorAction SilentlyContinue
if ($task) {
Write-Host "Task State: $($task.State)"
}
else {
Write-Warn "Scheduled Task nicht vorhanden."
}
}
function Show-Menu {
Clear-Host
Write-Title "SMTPGraphRelay - Bootstrap / Repair / Online Update"
Write-Host "Installationspfad: $InstallPath" -ForegroundColor DarkGray
$installedVersion = Get-InstalledVersion -TargetPath$InstallPath
if ($installedVersion -and$installedVersion.Version) {
Write-Host "Installiert: $($installedVersion.Version)" -ForegroundColor DarkGray
}
Write-Host "Updatequelle: Gitea / main" -ForegroundColor DarkGray
Write-Host ""
Write-Host " [1] Neuinstallation aus Gitea"
Write-Host " [2] Installation aus Gitea reparieren"
Write-Host " [3] Nach Online-Updates suchen"
Write-Host " [4] Entra App & Berechtigungen prüfen"
Write-Host " [5] Zertifikat erneuern"
Write-Host " [6] Health Check ausführen"
Write-Host " [7] Deinstallieren"
Write-Host " [8] Status anzeigen"
Write-Host " [9] SMTP-AUTH verwalten"
Write-Host " [10] Failed Queue verwalten"
Write-Host " [11] Failure-Mode QA"
Write-Host " [0] Beenden"
Write-Host ""
}
Assert-WindowsPowerShell51
while ($true) {
Show-Menu
$choice = Read-Host "Auswahl"
try {
switch ($choice) {
"1" { Install-New }
"2" { Repair-Installation }
"3" { Update-Relay }
"4" { Verify-CloudPermissions }
"5" { Invoke-CertificateRenewal }
"6" { Invoke-HealthCheck }
"7" { Uninstall-Relay }
"8" { Show-Status }
"9" { Manage-SmtpAuth }
"10" { Manage-FailedQueue }
"11" { Invoke-FailureModeTests }
"0" { break }
default { Write-Warn "Ungültige Auswahl." }
}
}
catch {
Write-Host ""
Write-Fail $_.Exception.Message
if ($_.ScriptStackTrace) {
Write-Host $_.ScriptStackTrace -ForegroundColor DarkYellow
}
}
if ($choice -ne "0") {
Write-Host ""
Read-Host "Enter drücken, um zum Menü zurückzukehren"
}
if ($choice -eq "0") {
break
}
}