9.5 KiB
Betrieb, Provider und Zustellgarantien
Start und Upgrade
go run ./cmd/gateway -config ./data/config.json
Die Konfiguration bleibt JSON-Schema 1. Der Server legt outbox.db neben der
Konfiguration an. Ein anderer Pfad lässt sich mit -outbox /pfad/outbox.db setzen.
SQLite arbeitet ohne CGO. Das Verzeichnis muss schreibbar sein; dort entstehen
auch outbox.db-wal und outbox.db-shm.
Verhaltensänderung: HTTP-Eingänge antworten nach persistenter Annahme mit 202, bevor ein Ziel kontaktiert wird:
{"ok":true,"receipt":{"id":"...","duplicate":false}}
Die Zustellhistorie zeigt den späteren Status. Speicherfehler führen zu 503,
ungültige Nachrichten/fehlende Regeln zu 400. Vorschauen versenden und speichern
keine Zustellungen. Verarbeitete Dry-Run-Aufträge erscheinen als dry_run.
Deduplizierung und Retry
HTTP-Sender sollten pro logischer Nachricht einen stabilen Schlüssel setzen:
curl -X POST http://localhost:8080/in/webhook/default \
-H 'Authorization: Bearer replace-me' \
-H 'Idempotency-Key: monitoring-event-123' \
-H 'Content-Type: application/json' \
-d '{"title":"Server","message":"Dienst ausgefallen"}'
- Der Schlüssel gilt für Quelle und Kanal, maximal 256 Bytes. Derselbe Schlüssel
und Inhalt liefern dieselbe Referenz mit
duplicate:true. Anderer Inhalt mit demselben Schlüssel ergibt 409. Empfangszeitpunkte zählen nicht zum Inhalt. - Ohne Schlüssel ist jede HTTP-Anfrage eine neue Nachricht. Gleicher Text allein löst keine Deduplizierung aus: gleiche Meldungen können neue Ereignisse sein.
- Alle passenden Regeln werden in einer Transaktion angenommen. Wenn eine kein gültiges Payload erzeugt, wird keine Teilmenge gespeichert.
- Jeder Ausgang hat einen eigenen Auftrag. Erfolgreiche Aufträge werden nicht wegen des Fehlers eines anderen Ziels wiederholt.
- HTTP-Verbindungsfehler, 408/425/429/5xx sowie temporäre SMTP-4xx-Fehler werden
wiederholt: maximal acht Versuche, zunächst etwa fünf Sekunden Wartezeit,
danach exponentiell mit Zufallsanteil.
Retry-Afterwird bis 24 Stunden beachtet. - Nach dauerhaften Fehlern oder acht Fehlversuchen bleibt der Auftrag
dead. Erneut versuchen startet einen neuen Versuchslauf desselben Auftrags mit ursprünglichem Ziel/Inhalt. Die vorherigen Versuche bleiben in der Historie. - Nach einem Absturz wird ein verwaister Versand nach Ablauf seiner zehnminütigen Reservierung wieder verfügbar. Regulärer Shutdown beendet laufende Netzwerkaufrufe und speichert deren Ergebnisse.
HTTP-Ausgänge senden Idempotency-Key und X-Notify-Gateway-Delivery mit der
stabilen Delivery-ID. SMTP verwendet eine stabile Message-ID. Fremde Provider
müssen diese Merkmale selbst zur Deduplizierung unterstützen. Ein Absturz nach
erfolgreichem Versand, aber vor dem lokalen Erfolgs-Commit, kann daher eine
Doppelzustellung verursachen. Es gibt keine Exactly-once-Garantie.
Ein Worker arbeitet sequenziell. Ein langsames Ziel verzögert andere Aufträge; Provider-Timeouts begrenzen die Dauer. Durchsatztests und konfigurierbare Parallelität für größere Installationen stehen noch aus.
Ausgangsprovider
Unter Ausgänge Verbindungen anlegen und unter Zuordnungen auswählen.
Neue Verbindungen verwenden live:false; Divera247 hat weiterhin dry_run:true.
Die Live-Einstellung wird beim Annehmen gespeichert. Das spätere Abschalten
eines Ausgangs hält bereits angenommene Live-Aufträge nicht an.
| Provider | Einstellungen |
|---|---|
| Discord | https://discord.com/api/webhooks/ID/TOKEN; Titel und Meldung, keine automatischen Mentions, maximal 2000 UTF-16-Codeeinheiten |
| HTTP-Webhook | Vollständige HTTP(S)-URL, optionaler Bearer-Token; POST mit gemappten Nachrichtenfeldern |
| ntfy | Server-Basis-URL, Topic, optionaler Bearer-Token; JSON-Publish, positive Priorität auf maximal 5 begrenzt |
| Gotify | Vollständiger /message-Endpunkt und App-Token; X-Gotify-Key, Titel/Meldung/Priorität |
| SMTP | Host, Port, tls (typisch 465) oder starttls (typisch 587), optional Benutzer/Passwort, reine Absender-/Empfängeradressen |
SMTP verlangt eine gültige Zertifikatskette. AUTH PLAIN wird ausschließlich
nach TLS verwendet. Mail-Inhalte sind UTF-8-Plain-Text als Base64-MIME; keine Anhänge.
Quellen: ntfy JSON-Publish, Gotify Nachrichten, Discord Webhooks.
IMAP-Eingang
Unter Eingänge einen Mail-Eingang einrichten: eindeutige ID, TLS-Adresse
wie imap.example.org:993, Benutzer, Passwort, Ordner und Zuordnungskanal.
Regeln verwenden source: "mail" und diesen Kanal.
- Passwort- oder App-Passwort-Anmeldung; OAuth2 ist noch nicht implementiert.
- Der Ordner wird schreibgeschützt geöffnet; Nachrichten werden weder gelöscht noch als gelesen markiert. Checkpoints liegen in SQLite.
- Beim ersten erfolgreichen Abruf wird standardmäßig der aktuelle UID-Stand übernommen. Vorhandene Nachrichten importieren muss vor diesem ersten Abruf gesetzt sein, wenn alte Nachrichten verarbeitet werden sollen.
- UIDVALIDITY-Wechsel setzt den Cursor zurück. Der neue UID-Namensraum wird erneut verarbeitet; alte Inhalte können dadurch erneut auftreten. Wechsel von Adresse/Benutzer/Ordner/Eingangs-ID erzeugt einen neuen Checkpoint und wendet die Erstimport-Einstellung erneut an.
- Ein Abruf verarbeitet bis zu 100 neue Nachrichten. Checkpoints werden erst nach Outbox-Annahme oder bewusster Filterung fortgeschrieben.
- Maximal 1 MiB Rohmail und dekodierter Text. Plain-Text-MIME wird verwendet; Anhänge werden ignoriert. HTML-only, fehlerhafte/zu große Nachrichten oder ein fehlendes Mapping blockieren den Checkpoint. Die Zustellhistorie zeigt den Abruffehler. Nachricht manuell verschieben oder eine passende Regel ergänzen.
- Absender-/Empfängerfilter vergleichen Adressen ohne Beachtung der Großschreibung. Header beweisen keine Absenderidentität; diese Prüfung gehört zusätzlich auf den empfangenden Mailserver.
- Eigene Gateway-Mails und
Auto-Submitted-Nachrichten werden übersprungen, um Rückkopplungen zu vermeiden. HTTP-Rückläufer mit Gateway-Delivery-Header werden ebenfalls abgelehnt.
Discord-Eingang
- Discord-Anwendung anlegen, Public Key und Application-ID übernehmen.
- Unter Eingänge Command-Name, erlaubte Guild-IDs und Channel-IDs setzen.
- Slash-Command entsprechend discord-command.example.json bei der Anwendung registrieren; der Name muss zur Konfiguration passen.
- Als Interactions Endpoint die öffentliche HTTPS-Adresse
/in/discordsetzen. - Regel mit
source: "discord"und Channel-ID als Kanal erstellen.
PING und Commands werden mit Ed25519 geprüft; Zeitstempel dürfen maximal fünf
Minuten abweichen. Application-ID und beide Allowlists müssen passen.
message ist erforderlich, title und priority optional. Die private Antwort
bestätigt die Speicherung, nicht den Versand. Es erfolgt kein Mithören beliebiger
Channel-Nachrichten und keine automatische Registrierung externer Anwendungen.
Siehe Discord Interactions.
Historie, Metriken und Sicherheit
- Zustellhistorie: Seiten zu 50 Aufträgen, Status, Referenz, Fehlerklasse und letzte 200 Versuchsereignisse pro Auftrag. Keine Bodies oder Zugangsdaten.
/healthz: Prozess erreichbar./readyz: SQLite erreichbar; keine Aussage zur Erreichbarkeit aller Provider./metrics: Prometheus-Gaugenotify_gateway_deliveries{state="..."}. Zugriff mitAuthorization: Bearer ..., wennGATEWAY_METRICS_TOKENgesetzt ist; sonst nur mit Admin-Session.- Schreibende Admin-APIs/Formulare benötigen einen Token aus
GET /ui/api/csrf(X-CSRF-Tokenbzw.csrf_token). Die WebUI erledigt das automatisch. Zusätzlich werden fremde Origins abgelehnt. - Neue Passwort-Hashes verwenden bcrypt. SHA-256-Hashes werden beim erfolgreichen Login migriert; alte Passwörter über 72 Bytes bleiben bis zum Wechsel im Legacy-Format. Neue Passwörter: 10 bis 72 Bytes. Wechsel widerruft alle Sessions.
- Login-Limit: zehn Versuche pro Minute und direkter Client-IP. Proxy-Header werden nicht vertraut; hinter einem Proxy eigenes Rate-Limit verwenden und den originalen Host erhalten.
- Request-Limits: 1 MiB für Eingänge, 2 MiB für Admin-Aufrufe. CSP erlaubt das
eingebettete UI-Skript per Hash; Admin-Antworten verwenden
no-store. - Bearer-Token, SMTP-/IMAP-Passwort und Divera-Accesskey akzeptieren
env:VARIABLE. Fehlende Variablen führen zu Fehlern. Outbox-Snapshots behalten die Referenz; ein später geänderter Variablenwert wird beim Versand verwendet.
Konfiguration und Outbox enthalten sensible Daten; direkte Secrets und Inhalte
werden nicht verschlüsselt. POSIX-Dateimodus ist 0600, unter Windows gelten
zusätzlich die geerbten ACLs. Verzeichniszugriff und Backups entsprechend schützen.
HTTPS über einen Reverse Proxy bleibt erforderlich.
Backup und Aufbewahrung
Für ein konsistentes einfaches Backup Gateway regulär stoppen und das ganze
Datenverzeichnis einschließlich Konfiguration, Datenbank und gegebenenfalls
WAL/SHM-Dateien sichern. Nur die laufende outbox.db zu kopieren genügt nicht.
Wiederherstellung bei gestopptem Gateway, anschließend starten.
Historie und Deduplizierungsbelege werden unbegrenzt aufbewahrt; automatische Bereinigung fehlt noch. Größe überwachen. Tabellen nicht manuell löschen: Belege und Checkpoints sind für Wiederanlauf und Deduplizierung nötig.