Dateien nach "/" hochladen
This commit is contained in:
@@ -1,324 +1,248 @@
|
|||||||
# SMTPGraphRelay
|
# SMTPGraphRelay 1.7.0
|
||||||
|
|
||||||
Lokaler SMTP Store-and-Forward Relay für Windows mit Versand über Microsoft 365 / Microsoft Graph.
|
SMTPGraphRelay V1.7 ergänzt optionales lokales SMTP-AUTH für interne Clients.
|
||||||
|
|
||||||
SMTPGraphRelay nimmt klassische lokale SMTP-Mails von Druckern, Scannern, NAS,
|
> **Hinweis:** `AUTH LOGIN` und `AUTH PLAIN` werden hier bewusst ohne TLS angeboten,
|
||||||
Servern, Monitoring-Systemen usw. entgegen und leitet sie per OAuth / Microsoft Graph
|
> weil dieses Relay für vertrauenswürdige interne Netze gedacht ist. Die Zugangsdaten
|
||||||
an Microsoft 365 weiter.
|
> sind auf dem Netzwerkpfad daher nur Base64-kodiert, nicht verschlüsselt. Die
|
||||||
|
> bestehende IP-Allowlist sollte weiterhin restriktiv gesetzt bleiben.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Einfachste Variante
|
**Windows PowerShell 5.1 als Administrator**:
|
||||||
|
|
||||||
**Windows PowerShell 5.1 als Administrator** öffnen und diesen Befehl ausführen:
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$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
|
$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
|
||||||
```
|
```
|
||||||
|
|
||||||
Danach erscheint das SMTPGraphRelay-Verwaltungsmenü.
|
## Neu in V1.7: SMTP AUTH
|
||||||
|
|
||||||
Der Installer lädt automatisch den aktuellen Stand aus dem Gitea-Repository und
|
Unterstützt:
|
||||||
installiert SMTPGraphRelay nach:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
C:\Program Files\SMTPGraphRelay
|
AUTH LOGIN
|
||||||
|
AUTH PLAIN
|
||||||
```
|
```
|
||||||
|
|
||||||
Es muss kein ZIP manuell heruntergeladen oder entpackt werden.
|
EHLO bewirbt die Mechanismen, sobald mindestens ein SMTP-Benutzer existiert:
|
||||||
|
|
||||||
## Installer / Manager
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
[1] Neuinstallation aus Gitea
|
250-AUTH LOGIN PLAIN
|
||||||
[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
|
|
||||||
[0] Beenden
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Was die Neuinstallation automatisch erledigt
|
Erfolgreiche Anmeldung:
|
||||||
|
|
||||||
- prüft Windows PowerShell 5.1
|
|
||||||
- installiert benötigte PowerShell-Module systemweit
|
|
||||||
- lädt die aktuellen Programmdateien aus Gitea
|
|
||||||
- installiert nach `C:\Program Files\SMTPGraphRelay`
|
|
||||||
- erzeugt ein nicht exportierbares Zertifikat in `LocalMachine\My`
|
|
||||||
- erstellt die Entra ID App Registration
|
|
||||||
- erstellt den Entra Service Principal
|
|
||||||
- vergibt **keine globale Graph `Mail.Send` Application Permission**
|
|
||||||
- richtet Exchange Online Application RBAC ein
|
|
||||||
- begrenzt `Application Mail.Send` auf das konfigurierte Absenderpostfach
|
|
||||||
- erzeugt `config.json`
|
|
||||||
- legt Queue-, Failed- und Log-Verzeichnisse an
|
|
||||||
- erstellt die Windows-Firewallregel
|
|
||||||
- erstellt den Scheduled Task unter `SYSTEM`
|
|
||||||
- startet SMTPGraphRelay
|
|
||||||
- führt abschließend den Health Check aus
|
|
||||||
|
|
||||||
## Architektur
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Drucker / Scanner / NAS / Server / Monitoring
|
235 2.7.0 Authentication successful
|
||||||
|
|
|
||||||
| SMTP
|
|
||||||
v
|
|
||||||
SMTPGraphRelay
|
|
||||||
|
|
|
||||||
| Queue / Retry
|
|
||||||
v
|
|
||||||
Microsoft Graph
|
|
||||||
|
|
|
||||||
| OAuth2 App-only
|
|
||||||
v
|
|
||||||
Microsoft 365
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## SMTP-Funktionen
|
Fehlgeschlagene Anmeldung:
|
||||||
|
|
||||||
- `EHLO` / `HELO`
|
|
||||||
- `MAIL FROM`
|
|
||||||
- mehrere `RCPT TO`
|
|
||||||
- `DATA`
|
|
||||||
- `RSET`
|
|
||||||
- `NOOP`
|
|
||||||
- `QUIT`
|
|
||||||
- IPv4-Netzwerk-Allowlist
|
|
||||||
- maximale Nachrichtengröße
|
|
||||||
- bis zu 20 parallele SMTP-Verbindungen standardmäßig
|
|
||||||
- konfigurierbares Parallel-Limit
|
|
||||||
- `421 Service busy` bei erreichtem Parallel-Limit
|
|
||||||
|
|
||||||
## Store-and-Forward Queue
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
queue\
|
535 5.7.8 Authentication credentials invalid
|
||||||
├── incoming\
|
|
||||||
├── pending\
|
|
||||||
└── processing\
|
|
||||||
|
|
||||||
failed\
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Nachrichten werden zunächst atomar unter `incoming` geschrieben.
|
Wenn AUTH für den Client erforderlich ist:
|
||||||
- Erst vollständig geschriebene Nachrichten werden unter `pending` sichtbar.
|
|
||||||
- Während des Graph-Versands liegen Nachrichten unter `processing`.
|
|
||||||
- Nach einem Absturz werden verbliebene Processing-Nachrichten wieder nach Pending gestellt.
|
|
||||||
- Permanent fehlgeschlagene Nachrichten landen unter `failed`.
|
|
||||||
|
|
||||||
## Retry-Verhalten
|
|
||||||
|
|
||||||
- HTTP `429`: Microsoft `Retry-After` wird berücksichtigt
|
|
||||||
- ohne `Retry-After`: exponentielles Backoff
|
|
||||||
- HTTP `408` und `5xx`: Retry
|
|
||||||
- DNS-, TLS-, Timeout- und Netzwerkfehler: Retry
|
|
||||||
- typische permanente `4xx`: direkt nach `failed`
|
|
||||||
- nach `MaxRetries`: nach `failed`
|
|
||||||
|
|
||||||
## Microsoft 365 / Security
|
|
||||||
|
|
||||||
Der Relay verwendet:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Microsoft Graph
|
530 5.7.0 Authentication required
|
||||||
Application Mail.Send
|
|
||||||
```
|
```
|
||||||
|
|
||||||
über **Exchange Online Application RBAC**.
|
Nach standardmäßig fünf Fehlversuchen innerhalb derselben Verbindung werden
|
||||||
|
weitere AUTH-Versuche temporär abgewiesen:
|
||||||
|
|
||||||
Die Berechtigung wird auf das beim Setup angegebene Absenderpostfach beschränkt.
|
```text
|
||||||
|
454 4.7.0 Too many authentication failures
|
||||||
|
```
|
||||||
|
|
||||||
|
## IP-Allowlist bleibt vorgeschaltet
|
||||||
|
|
||||||
|
SMTP-AUTH ersetzt die bestehende `AllowedNetworks`-Prüfung **nicht**.
|
||||||
|
|
||||||
|
Ein Client muss zuerst aus einem erlaubten Netz kommen. Erst danach kann er sich
|
||||||
|
optional bzw. verpflichtend authentifizieren.
|
||||||
|
|
||||||
|
AUTH kann daher niemals einem ansonsten nicht erlaubten Host Zugriff verschaffen.
|
||||||
|
|
||||||
|
## Passwortspeicherung
|
||||||
|
|
||||||
|
SMTP-Passwörter werden nicht im Klartext gespeichert.
|
||||||
|
|
||||||
|
Verwendet wird:
|
||||||
|
|
||||||
|
```text
|
||||||
|
PBKDF2-HMAC-SHA256
|
||||||
|
Salt: 16 Byte zufällig
|
||||||
|
Iterations: 150000
|
||||||
|
Hash: 32 Byte
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispiel in `config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Username": "scanner01",
|
||||||
|
"Salt": "...",
|
||||||
|
"PasswordHash": "...",
|
||||||
|
"Iterations": 150000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
```json
|
||||||
|
"Smtp": {
|
||||||
|
"RequireAuth": true,
|
||||||
|
"AuthMaxFailures": 5,
|
||||||
|
"AllowUnauthenticatedNetworks": [
|
||||||
|
"10.60.10.0/24"
|
||||||
|
],
|
||||||
|
"AuthUsers": [
|
||||||
|
{
|
||||||
|
"Username": "scanner01",
|
||||||
|
"Salt": "...",
|
||||||
|
"PasswordHash": "...",
|
||||||
|
"Iterations": 150000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### RequireAuth
|
||||||
|
|
||||||
|
```text
|
||||||
|
false
|
||||||
|
```
|
||||||
|
|
||||||
|
AUTH ist optional. Clients aus `AllowedNetworks` dürfen weiterhin ohne
|
||||||
|
Benutzername/Passwort senden.
|
||||||
|
|
||||||
|
```text
|
||||||
|
true
|
||||||
|
```
|
||||||
|
|
||||||
|
Clients müssen sich authentifizieren, außer ihre IP liegt in
|
||||||
|
`AllowUnauthenticatedNetworks`.
|
||||||
|
|
||||||
|
### AllowUnauthenticatedNetworks
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
"10.60.10.0/24",
|
||||||
|
"192.168.50.10"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Diese Hosts/Netze dürfen trotz `RequireAuth=true` ohne AUTH senden.
|
||||||
|
|
||||||
|
Sie müssen trotzdem zusätzlich durch `AllowedNetworks` erlaubt sein.
|
||||||
|
|
||||||
|
## Benutzerverwaltung
|
||||||
|
|
||||||
|
Im Setup-/Manager gibt es jetzt:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[9] SMTP-AUTH verwalten
|
||||||
|
```
|
||||||
|
|
||||||
|
Untermenü:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[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
|
||||||
|
```
|
||||||
|
|
||||||
|
Beim Hinzufügen bzw. Ändern eines Passworts erfolgt die Eingabe verdeckt.
|
||||||
|
|
||||||
|
## Graph-Sender bleibt unabhängig
|
||||||
|
|
||||||
|
Der SMTP-Benutzer dient ausschließlich zur Authentifizierung am lokalen Relay.
|
||||||
|
|
||||||
Beispiel:
|
Beispiel:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
SMTPGraphRelay App
|
SMTP AUTH: scanner01
|
||||||
|
MAIL FROM: scanner@device.local
|
||||||
|
|
|
||||||
|
v
|
||||||
|
SMTPGraphRelay
|
||||||
|
|
|
||||||
|
ForceSender=true
|
||||||
|
|
|
|
||||||
| Application Mail.Send
|
|
||||||
v
|
v
|
||||||
info@example.com
|
info@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Die App erhält bewusst **keine zusätzliche tenantweite Graph `Mail.Send`
|
AUTH verändert weder die Entra-App noch das Graph-Zertifikat oder
|
||||||
Application Permission**, da diese das Exchange-RBAC-Scoping umgehen würde.
|
`Graph.SenderMailbox`.
|
||||||
|
|
||||||
Der lokale Relay erzwingt außerdem standardmäßig:
|
## Queue-Metadaten
|
||||||
|
|
||||||
|
Bei authentifizierten Einlieferungen wird der Benutzer zusätzlich in den
|
||||||
|
Queue-Metadaten gespeichert:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"ForceSender": true
|
"AuthenticatedUser": "scanner01"
|
||||||
```
|
```
|
||||||
|
|
||||||
und verwendet ausschließlich `Graph.SenderMailbox` als Graph-Absender.
|
und im Log ausgegeben:
|
||||||
|
|
||||||
## Zertifikatsauthentifizierung
|
|
||||||
|
|
||||||
SMTPGraphRelay verwendet kein Client Secret.
|
|
||||||
|
|
||||||
Das Setup erzeugt ein RSA-Zertifikat unter:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Cert:\LocalMachine\My
|
[7F3A91C2D441] Mail angenommen | ... | Auth=scanner01
|
||||||
```
|
```
|
||||||
|
|
||||||
Der private Schlüssel ist nicht exportierbar.
|
Bei nicht authentifizierten, aber erlaubten Verbindungen:
|
||||||
|
|
||||||
Das Relay prüft regelmäßig die Restlaufzeit des Zertifikats.
|
|
||||||
|
|
||||||
Standard:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Warnung: 60 Tage
|
Auth=unauthenticated
|
||||||
Kritisch: 14 Tage
|
|
||||||
Prüfung: alle 12 Stunden
|
|
||||||
```
|
|
||||||
|
|
||||||
Zur Rotation:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\Renew-SMTPGraphRelayCertificate.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
Die Rotation erfolgt mit Überlappung:
|
|
||||||
|
|
||||||
```text
|
|
||||||
OLD
|
|
||||||
↓
|
|
||||||
NEW erzeugen
|
|
||||||
↓
|
|
||||||
OLD + NEW in Entra
|
|
||||||
↓
|
|
||||||
NEW testen
|
|
||||||
↓
|
|
||||||
Config auf NEW
|
|
||||||
↓
|
|
||||||
Relay neu starten
|
|
||||||
↓
|
|
||||||
OLD optional entfernen
|
|
||||||
```
|
|
||||||
|
|
||||||
## Log-Rotation
|
|
||||||
|
|
||||||
Standard:
|
|
||||||
|
|
||||||
```text
|
|
||||||
MaxFileSizeMB = 10
|
|
||||||
RetentionDays = 30
|
|
||||||
CleanupHours = 12
|
|
||||||
```
|
|
||||||
|
|
||||||
Aktives Log:
|
|
||||||
|
|
||||||
```text
|
|
||||||
logs\SMTPGraphRelay.log
|
|
||||||
```
|
|
||||||
|
|
||||||
Archiv:
|
|
||||||
|
|
||||||
```text
|
|
||||||
logs\SMTPGraphRelay-YYYYMMDD-HHMMSS.log
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Health Check
|
## Health Check
|
||||||
|
|
||||||
|
Der Health Check validiert zusätzlich die SMTP-AUTH-Konfiguration.
|
||||||
|
|
||||||
|
Eine Testmail kann weiterhin mit:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\Test-SMTPGraphRelay.ps1
|
.\Test-SMTPGraphRelay.ps1 -SendTestMail -TestRecipient "user@example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional mit echter SMTP-Testmail:
|
ausgeführt werden.
|
||||||
|
|
||||||
|
Ist AUTH erforderlich, fragt der Health Check bei Bedarf Benutzername und
|
||||||
|
Passwort interaktiv ab.
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\Test-SMTPGraphRelay.ps1 `
|
.\Test-SMTPGraphRelay.ps1 `
|
||||||
-SendTestMail `
|
-SendTestMail `
|
||||||
-TestRecipient "user@example.com"
|
-TestRecipient "user@example.com" `
|
||||||
|
-SmtpUsername "scanner01"
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Health Check prüft unter anderem:
|
Das Passwort wird weiterhin verdeckt abgefragt.
|
||||||
|
|
||||||
- PowerShell-Version
|
## V1.6 Funktionen bleiben erhalten
|
||||||
- Administratorstatus
|
|
||||||
- Config
|
|
||||||
- Graph-Modul
|
|
||||||
- Zertifikat und Private Key
|
|
||||||
- Zertifikatslaufzeit
|
|
||||||
- Queue und Schreibrechte
|
|
||||||
- Failed Queue
|
|
||||||
- Scheduled Task
|
|
||||||
- SMTP Listener
|
|
||||||
- Graph App-only Authentication
|
|
||||||
|
|
||||||
Exitcodes:
|
- Queue-ID
|
||||||
|
- Received-Header
|
||||||
```text
|
- automatische Message-ID
|
||||||
0 = OK
|
- MaxRecipients
|
||||||
1 = Warnung
|
- MaxMessagesPerConnection
|
||||||
2 = Fehler
|
- MaxPendingMessages
|
||||||
```
|
- MinFreeDiskSpaceMB
|
||||||
|
- Queue-/Disk-Backpressure
|
||||||
## Online Update
|
- parallele SMTP-Clients
|
||||||
|
- Graph-Retry
|
||||||
Im Manager:
|
- Log-Rotation
|
||||||
|
- Zertifikatsüberwachung
|
||||||
```text
|
- Online-Update / Repair / Rollback
|
||||||
[3] Nach Online-Updates suchen
|
|
||||||
```
|
|
||||||
|
|
||||||
Der Manager prüft:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay/raw/branch/main/version.json
|
|
||||||
```
|
|
||||||
|
|
||||||
und lädt bei Bedarf:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay/archive/main.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
Vor dem Update wird ein Backup der verwalteten Programmdateien erstellt.
|
|
||||||
|
|
||||||
Bei einem fehlgeschlagenen Health Check erfolgt automatisch ein Rollback.
|
|
||||||
|
|
||||||
### Von Updates niemals überschrieben
|
|
||||||
|
|
||||||
- `config.json`
|
|
||||||
- `queue\`
|
|
||||||
- `failed\`
|
|
||||||
- `logs\`
|
|
||||||
- `backup\`
|
|
||||||
- lokales Zertifikat
|
|
||||||
- Entra App Registration
|
|
||||||
- Exchange Application RBAC
|
|
||||||
|
|
||||||
## Repair
|
|
||||||
|
|
||||||
```text
|
|
||||||
[2] Installation aus Gitea reparieren
|
|
||||||
```
|
|
||||||
|
|
||||||
Repair lädt den aktuellen Programmstand neu aus dem Repository und repariert:
|
|
||||||
|
|
||||||
- Programmdateien
|
|
||||||
- PowerShell-Module
|
|
||||||
- Verzeichnisstruktur
|
|
||||||
- Firewallregel
|
|
||||||
- Scheduled Task
|
|
||||||
|
|
||||||
Cloud-Konfiguration, Zertifikat, Config, Queue und Logs bleiben erhalten.
|
|
||||||
|
|
||||||
## Repository
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay
|
|
||||||
```
|
|
||||||
|
|
||||||
## Systemvoraussetzungen
|
|
||||||
|
|
||||||
- Windows 10 / 11 oder Windows Server
|
|
||||||
- Windows PowerShell 5.1
|
|
||||||
- lokale Administratorrechte für Installation
|
|
||||||
- Internetzugang zu Microsoft Entra, Microsoft Graph, Exchange Online und dem Gitea-Repository
|
|
||||||
- Entra-/Exchange-Administratorkonto für die Ersteinrichtung
|
|
||||||
- Microsoft-365-/Exchange-Online-Postfach für den Relay-Absender
|
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Version": "1.6.0",
|
"Version": "1.7.0",
|
||||||
"Product": "SMTPGraphRelay",
|
"Product": "SMTPGraphRelay",
|
||||||
"MinimumPowerShell": "5.1",
|
"MinimumPowerShell": "5.1",
|
||||||
"ReleaseDate": "2026-08-13"
|
"ReleaseDate": "2026-08-14",
|
||||||
|
"Repository": "https://me-gitea.maieredv.cloud/MAIEREDV/SMTPGraphRelay"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user