SMTPGraphRelay
SMTPGraphRelay ist ein nativer Windows-SMTP-Relay für interne Geräte und Anwendungen.
Er nimmt klassische SMTP-Mails von Druckern, Scannern, NAS-Systemen, Servern, Monitoring-Tools und anderen Legacy-Geräten entgegen und versendet sie anschließend über Microsoft Graph mit App-only OAuth2 über Microsoft 365.
Der Relay läuft vollständig unter Windows PowerShell 5.1 und benötigt keinen Docker-Container, keinen lokalen Exchange-Server und keinen klassischen SMTP-Smarthost.
Überblick
Drucker / Scanner / NAS / Server / Monitoring
|
| SMTP
v
SMTPGraphRelay
|
| Store-and-Forward Queue
v
Microsoft Graph
|
| OAuth2 App-only
v
Microsoft 365
SMTPGraphRelay wurde für den Betrieb in internen Netzwerken entwickelt.
Installation
Schnellinstallation
Auf dem Zielsystem Windows PowerShell 5.1 als Administrator öffnen und ausführen:
$u='https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay/raw/branch/main/Setup-SMTPGraphRelay.ps1';$f="$env:TEMP\Setup-SMTPGraphRelay.ps1";Invoke-WebRequest $u -UseBasicParsing -OutFile $f;& $f
Der Bootstrap-Installer lädt automatisch den aktuellen Stand aus dem Gitea-Repository und installiert SMTPGraphRelay nach:
C:\Program Files\SMTPGraphRelay
Es muss kein ZIP manuell heruntergeladen oder entpackt werden.
Setup / Manager
Nach dem Start erscheint das Verwaltungsmenü:
[1] Neuinstallation aus Gitea
[2] Installation aus Gitea reparieren
[3] Nach Online-Updates suchen
[4] Entra / Exchange RBAC prüfen
[5] Zertifikat erneuern
[6] Health Check ausführen
[7] Deinstallieren
[8] Status anzeigen
[9] SMTP-AUTH verwalten
[10] Failed Queue verwalten
[11] Failure-Mode QA
[0] Beenden
Neuinstallation
Die Neuinstallation erledigt automatisch:
- Prüfung auf Windows PowerShell 5.1
- Prüfung auf Administratorrechte
- Download der aktuellen Programmdateien aus Gitea
- Installation nach
C:\Program Files\SMTPGraphRelay - Installation der benötigten Microsoft-Graph-PowerShell-Module
- Installation von
ExchangeOnlineManagement - Erstellung eines lokalen Zertifikats
- Erstellung der Entra ID App Registration
- Erstellung des Entra Service Principals
- Einrichtung von Exchange Online Application RBAC
- Beschränkung von
Application Mail.Sendauf das konfigurierte Absenderpostfach - Erstellung der
config.json - Erstellung der Queue-/Failed-/Log-Verzeichnisse
- Erstellung der Windows-Firewallregel
- Erstellung des Scheduled Tasks unter
SYSTEM - Start des Relay
- abschließender Health Check
Microsoft 365 / Graph
SMTPGraphRelay verwendet Microsoft Graph mit App-only Authentifizierung.
Der Versand erfolgt über:
POST /v1.0/users/<SenderMailbox>/sendMail
Die Authentifizierung erfolgt mit:
Tenant ID
Client ID
Certificate Thumbprint
Es wird kein Client Secret verwendet.
Exchange Application RBAC
Der Relay verwendet bewusst keine tenantweite Microsoft Graph Mail.Send Application Permission.
Stattdessen wird Exchange Online Application RBAC verwendet:
Application Mail.Send
|
v
Custom Resource Scope
|
v
konfiguriertes SenderMailbox
Beispiel:
SMTPGraphRelay App
|
| Application Mail.Send
v
info@example.com
Dadurch kann die Anwendung ausschließlich über das konfigurierte Absenderpostfach senden.
Zertifikatsauthentifizierung
Das Setup erzeugt ein RSA-Zertifikat unter:
Cert:\LocalMachine\My
Eigenschaften:
RSA 2048
SHA256
Private Key nicht exportierbar
Gültigkeit: 2 Jahre
Der Relay überwacht die Zertifikatslaufzeit regelmäßig.
Standard:
Warnung: 60 Tage
Kritisch: 14 Tage
Prüfung: alle 12 Stunden
Das Zertifikat kann über den Manager erneuert werden:
[5] Zertifikat erneuern
Die Rotation erfolgt mit Überlappung:
altes Zertifikat
|
v
neues Zertifikat erstellen
|
v
neues Credential zusätzlich in Entra hinterlegen
|
v
App-only Login mit neuem Zertifikat testen
|
v
config.json auf neues Zertifikat umstellen
|
v
Relay neu starten
|
v
altes Zertifikat optional entfernen
SMTP-Funktionen
Unterstützte SMTP-Kommandos:
EHLO
HELO
MAIL FROM
RCPT TO
DATA
RSET
NOOP
QUIT
AUTH LOGIN
AUTH PLAIN
STARTTLS wird bewusst nicht verwendet, da SMTPGraphRelay für interne, vertrauenswürdige Netzwerke vorgesehen ist.
SMTP Listener
Standardmäßig:
ListenAddress: 0.0.0.0
Port: 2525
Der Port kann in config.json geändert werden.
IP-Allowlist
SMTPGraphRelay akzeptiert ausschließlich Clients aus konfigurierten Netzwerken.
Beispiel:
"AllowedNetworks": [
"127.0.0.1/32",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
]
Nicht erlaubte Hosts erhalten:
554 5.7.1 Client not allowed
Die IP-Allowlist bleibt auch bei aktiviertem SMTP-AUTH immer die erste Zugriffskontrolle.
SMTP-AUTH
SMTPGraphRelay unterstützt:
AUTH LOGIN
AUTH PLAIN
SMTP-AUTH kann optional oder verpflichtend aktiviert werden.
Beispiel:
"RequireAuth": true
Clients ohne erfolgreiche Authentifizierung erhalten dann:
530 5.7.0 Authentication required
Erfolgreiche Anmeldung:
235 2.7.0 Authentication successful
Fehlgeschlagene Anmeldung:
535 5.7.8 Authentication credentials invalid
Nach mehreren Fehlversuchen kann die Verbindung temporär gesperrt werden:
454 4.7.0 Too many authentication failures
Standard:
AuthMaxFailures = 5
SMTP-Benutzerverwaltung
Im Manager:
[9] SMTP-AUTH verwalten
Funktionen:
[1] SMTP-AUTH erforderlich EIN/AUS
[2] Benutzer hinzufügen
[3] Benutzer anzeigen
[4] Passwort ändern
[5] Benutzer löschen
[6] Netze ohne Auth verwalten
[7] Max. Fehlversuche ändern
[0] Zurück
Passwörter werden nicht im Klartext gespeichert.
Verwendet wird:
PBKDF2-HMAC-SHA256
zufälliger Salt
150000 Iterationen
32 Byte Hash
AUTH-Ausnahmen
Bestimmte Netze können trotz RequireAuth=true ohne SMTP-AUTH zugelassen werden:
"AllowUnauthenticatedNetworks": [
"10.60.10.0/24"
]
Diese Clients müssen trotzdem zusätzlich in AllowedNetworks enthalten sein.
Absenderkontrolle
Der SMTP-Benutzer beeinflusst nicht den tatsächlichen Microsoft-365-Absender.
Mit:
"ForceSender": true
wird immer Graph.SenderMailbox als Absender verwendet.
Parallele SMTP-Verbindungen
SMTPGraphRelay verarbeitet mehrere SMTP-Clients parallel über einen PowerShell-Runspace-Pool.
Standard:
MaxConcurrentClients = 20
Ist das Limit erreicht:
421 4.3.2 SMTPGraphRelay busy, try again later
SMTP-Limits
Standardwerte:
MaxRecipients = 50
MaxMessagesPerConnection = 25
MaxMessageSizeMB = 25
Zu viele Empfänger:
452 4.5.3 Too many recipients
Zu viele Nachrichten innerhalb einer Verbindung:
452 4.5.3 Too many messages in this session
Zu große Nachricht:
552 5.3.4 Message size exceeds fixed maximum message size
Store-and-Forward Queue
Queue-Struktur:
queue\
├── incoming\
├── pending\
└── processing\
failed\
incoming: Nachricht wird atomar geschrieben.pending: vollständig gespeicherte, versandbereite Nachrichten.processing: aktuell durch den Graph-Worker verarbeitete Nachrichten.failed: dauerhaft fehlgeschlagene Nachrichten.
Queue-ID
Jede Nachricht erhält eine eindeutige Queue-ID.
Beispiel:
7F3A91C2D441
SMTP-Antwort:
250 2.0.0 Message accepted for delivery; queue-id=7F3A91C2D441
Die Queue-ID wird ebenfalls in den Logs verwendet.
Received-Header und Message-ID
SMTPGraphRelay fügt einen eigenen Received:-Header hinzu.
Besitzt eine eingehende Nachricht keine Message-ID, erzeugt der Relay automatisch eine.
Bereits vorhandene Message-IDs bleiben unverändert.
Retry-Logik
Standard-Retry-Zeiten:
1 Minute
5 Minuten
15 Minuten
30 Minuten
60 Minuten
120 Minuten
240 Minuten
480 Minuten
Standard:
MaxRetries = 8
Automatische Wiederholung erfolgt bei:
HTTP 408
HTTP 429
HTTP 5xx
DNS-Fehler
TLS-/Transportfehler
Timeouts
Netzwerkfehler
Bei 429 Too Many Requests wird Retry-After berücksichtigt.
Typische permanente Fehler wie 400, 401, 403, 404, 409, 410, 412, 413, 415, 422 und 423 werden direkt nach failed verschoben.
Queue-Backpressure
Standard:
MaxPendingMessages = 5000
MinFreeDiskSpaceMB = 1024
Queue-Limit erreicht:
452 4.3.1 SMTPGraphRelay queue limit reached
Zu wenig freier Speicher:
452 4.3.1 Insufficient system storage
Kann eine Nachricht nach DATA nicht atomar gespeichert werden:
451 4.3.0 SMTPGraphRelay queue temporarily unavailable
Failed Queue
Im Manager:
[10] Failed Queue verwalten
Funktionen:
[1] Failed Queue anzeigen
[2] Details einer Mail anzeigen
[3] Eine Mail erneut zustellen
[4] Alle Mails erneut zustellen
[5] Eine Mail endgültig löschen
[6] Alle Failed-Mails endgültig löschen
[0] Zurück
Beim erneuten Zustellen wird die Nachricht zurück nach queue\pending verschoben.
Graceful Shutdown
Update, Repair und kontrollierte Stop-Vorgänge beenden den Relay nicht sofort hart.
Der Manager erzeugt:
C:\Program Files\SMTPGraphRelay\shutdown.request
Der Relay schließt zuerst den Listener, nimmt keine neuen Verbindungen mehr an, lässt laufende SMTP-Sessions und den aktuellen Queue-/Graph-Versand auslaufen und beendet sich anschließend selbst.
Standard:
GracefulShutdownSeconds = 30
Bei Timeout fällt der Manager auf einen harten Scheduled-Task-Stop zurück.
Logging
Logdatei:
C:\Program Files\SMTPGraphRelay\logs\SMTPGraphRelay.log
Log-Rotation:
MaxFileSizeMB = 10
RetentionDays = 30
CleanupHours = 12
Archivierte Logs:
SMTPGraphRelay-YYYYMMDD-HHMMSS.log
Health Check
Im Manager:
[6] Health Check ausführen
oder direkt:
.\Test-SMTPGraphRelay.ps1
Geprüft werden unter anderem:
- Windows PowerShell 5.1
- Administratorstatus
config.json- Graph-PowerShell-Modul
- Zertifikat und Private Key
- Zertifikatslaufzeit
- Queue-Verzeichnisse und Schreibrechte
- Pending / Processing / Failed Queue
- Scheduled Task
- SMTP Listener
- Graph App-only Login
- SMTP-AUTH-Konfiguration
Exitcodes:
0 = OK
1 = Warnung
2 = Fehler
SMTP-Testmail
.\Test-SMTPGraphRelay.ps1 `
-SendTestMail `
-TestRecipient "user@example.com"
Bei aktiviertem SMTP-AUTH:
.\Test-SMTPGraphRelay.ps1 `
-SendTestMail `
-TestRecipient "user@example.com" `
-SmtpUsername "scanner01"
Das Passwort wird interaktiv und verdeckt abgefragt.
Online Update
Im Manager:
[3] Nach Online-Updates suchen
Der Manager prüft die version.json im Gitea-Repository und lädt bei einer neuen Version das aktuelle main.zip.
Vor dem Update werden die verwalteten Programmdateien gesichert.
Ablauf:
Versionsprüfung
|
v
Repository laden
|
v
Backup
|
v
Graceful Shutdown
|
v
Programmdateien aktualisieren
|
v
Relay starten
|
v
Health Check
|
+--> Fehler -> automatischer Rollback
Repair
Im Manager:
[2] Installation aus Gitea reparieren
Repair lädt den aktuellen Programmstand erneut aus Gitea und stellt fehlende oder beschädigte Programmdateien wieder her.
Dabei bleiben erhalten:
config.json
queue\
failed\
logs\
backup\
Zertifikat
Entra App Registration
Exchange Application RBAC
Failure-Mode QA
Im Manager:
[11] Failure-Mode QA
oder direkt:
.\Test-SMTPGraphRelay-FailureModes.ps1
Tests:
[1] Graph HTTP 429 / Retry testen
[2] Graph HTTP 500 / Retry testen
[3] Queue-Schreibfehler / SMTP 451 testen
[4] Pending-Queue-Backpressure / SMTP 452 testen
[5] Disk-Backpressure / SMTP 452 testen
[6] Graceful Shutdown während SMTP DATA testen
[7] Graceful Shutdown während Queue/Graph testen
[8] QA-/Debug-Block aus Config entfernen
[0] Beenden
Die ursprüngliche config.json wird vor jedem Test gesichert und anschließend automatisch wiederhergestellt.
Scheduled Task
SMTPGraphRelay läuft als Scheduled Task unter:
SYSTEM
Ausgeführt wird explizit:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
mit:
-NoLogo
-NoProfile
-ExecutionPolicy Bypass
-File "C:\Program Files\SMTPGraphRelay\SMTPGraphRelay.ps1"
-ConfigPath "C:\Program Files\SMTPGraphRelay\config.json"
Verzeichnisstruktur
C:\Program Files\SMTPGraphRelay\
│
├── SMTPGraphRelay.ps1
├── Setup-SMTPGraphRelay.ps1
├── Test-SMTPGraphRelay.ps1
├── Test-SMTPGraphRelay-FailureModes.ps1
├── Renew-SMTPGraphRelayCertificate.ps1
├── version.json
├── config.json
│
├── queue\
│ ├── incoming\
│ ├── pending\
│ └── processing\
│
├── failed\
├── logs\
└── backup\
Systemvoraussetzungen
- Windows 10 / Windows 11 oder Windows Server
- Windows PowerShell 5.1
- lokale Administratorrechte für Installation und Verwaltung
- Zugriff auf das Gitea-Repository
- Internetzugang zu Microsoft Entra ID
- Internetzugang zu Microsoft Graph
- Internetzugang zu Exchange Online
- Microsoft-365-/Exchange-Online-Postfach als Relay-Absender
- Entra-/Exchange-Administratorkonto für die Ersteinrichtung
Repository
https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay
Betriebskonzept
SMTPGraphRelay ist für den internen Einsatz vorgesehen.
Empfohlene Absicherung:
interne Netzwerksegmente
+
AllowedNetworks
+
optional SMTP-AUTH
+
ForceSender
+
Exchange Application RBAC
Dadurch bleibt sowohl der lokale Zugriff als auch der tatsächliche Microsoft-365-Versand klar eingeschränkt.