OpenClaw Mailer
Governter E-Mail-Versand für OpenClaw-Agenten — fail-closed Empfänger-Allowlist, ein TLS-Trust-Modell mit agent-shield, Port 587 + MAILER_CA_CERT hinter AV-Interception.
OpenClaw Mailer
Lassen Sie Ihren OpenClaw-Agenten E-Mails versenden — ohne dass er an Beliebige sendet, Secrets leakt oder still TLS abschaltet.
OpenClaw Mailer ist ein kleiner, eigenständiger MCP-Server mit genau einem Tool: send_email (auf Basis von nodemailer). Er ist bewusst getrennt von agent-shield: agent-shield entscheidet, ob eine Aktion erlaubt ist; der Mailer versendet nur. governance_check läuft vor jedem Versand — Entscheidung und Zustellung sind zwei saubere, auditierbare Schritte.
Warum nicht der eingebaute/CLI-Versandweg? Ein reiner Node-Versender teilt ein Trust-Modell mit agent-shield: dieselbe --use-system-ca-/Zertifikatsbehandlung für das Gateway und den Mailversand. Ein zweiter TLS-Stack (z. B. ein Rust-CLI-Mailer) liest den OS-Zertifikatspeicher nicht und scheitert hinter Antiviren-HTTPS-Inspektion — genau das Problem, das diese Seite löst.
So funktioniert es
OpenClaw Agent → governance_check (agent-shield) → {{brand}} Gateway → Policy-Check
↓
✅ ALLOW / ✏️ MODIFY → send_email (openclaw-mailer) → SMTP
🚫 BLOCK → kein VersandDer Agent ruft zuerst governance_check auf. Nur bei ALLOW (oder MODIFY, mit bereits maskierter PII) ruft er send_email. Jeder Schritt erzeugt seinen eigenen manipulationssicheren Trace.
Sichere Defaults
- Empfänger-Allowlist (fail-closed). Jeder Empfänger muss in
MAILER_ALLOWED_RECIPIENTSstehen, sonst wird nichts versendet. Das ist Defense-in-Depth zusätzlich zugovernance_check: Selbst ein kompromittierter oder per Prompt-Injection manipulierter Agent kann nicht an beliebige Adressen mailen. - Zertifikatsprüfung wird nie abgeschaltet.
rejectUnauthorizedbleibttrue. Vertrauen wird hinzugefügt (über den OS-Speicher oderMAILER_CA_CERT), niemals abgeschaltet. - Secrets nur über Env.
SMTP_PASSwird aus der Umgebung gelesen, nie geloggt und nie in Fehlermeldungen oder Hints aufgenommen.
Setup / MCP-Registrierung
Starten Sie den Mailer mit command: node und --use-system-ca als erstem Argument, gefolgt vom absoluten Pfad zum Server. Geben Sie die gesamte Konfiguration über den env-Block weiter — nur Platzhalter, niemals echte Secrets im Repo:
{
"mcpServers": {
"openclaw-mailer": {
"command": "node",
"args": ["--use-system-ca", "C:/Projekte/openclaw-mailer/bin/openclaw-mailer-mcp.mjs"],
"env": {
"SMTP_HOST": "smtp.gmail.com",
"SMTP_PORT": "587",
"SMTP_SECURE": "false",
"SMTP_USER": "[email protected]",
"SMTP_PASS": "Ihr-App-Passwort",
"SMTP_FROM": "Ihr Name <[email protected]>",
"MAILER_ALLOWED_RECIPIENTS": "[email protected]",
"MAILER_CA_CERT": "C:/Users/sie/inspizierende-ca.pem"
}
}
}
}Das App-Passwort gehört ausschließlich in die Laufzeit-Env (oder den Secret-Store Ihres MCP-Hosts) — niemals in die Versionskontrolle. Das Paket wird privat als @{{brand_scope}}/openclaw-mailer geführt und über den absoluten Pfad statt via npx aufgerufen.
Hinter Antiviren-/Firewall-HTTPS-Inspektion Port 587 (STARTTLS) nutzen, nicht 465 — und
MAILER_CA_CERTsetzen. Warum, steht unter TLS hinter AV-Interception.
Umgebungsvariablen
| Variable | Erforderlich | Default | Beschreibung |
|---|---|---|---|
SMTP_HOST | ja | — | SMTP-Server-Hostname. |
SMTP_PORT | nein | 465 | 587 = STARTTLS-Submission (empfohlen hinter AV), 465 = implizites TLS. |
SMTP_SECURE | nein | true (false bei Port 587) | true/1/yes ⇒ implizites TLS. Bei Port 587 Default false, damit nodemailer per STARTTLS upgradet. |
SMTP_USER | ja | — | SMTP-Benutzername (meist die vollständige Adresse). |
SMTP_PASS | ja | — | SMTP-Passwort / App-Passwort. Nie geloggt, nie im Repo. |
SMTP_FROM | nein | SMTP_USER | Envelope/Absender. Akzeptiert Anzeigename <addr>. |
MAILER_ALLOWED_RECIPIENTS | ja | — | Komma-getrennte Empfänger-Allowlist. Pflicht (fail-closed). |
MAILER_CA_CERT | nein | — | Absoluter Pfad zu einer PEM mit einer/mehreren zusätzlichen Root-CAs (z. B. die inspizierende AV-CA). Wird in-process gelesen und zusätzlich zu den eingebauten Roots vertraut. Fällt auf NODE_EXTRA_CA_CERTS zurück, falls nicht gesetzt. |
DEBUG_LOG_PATH | nein | — | Wenn gesetzt: append-only, secret-sichere JSONL-Diagnose (gleiche Konvention wie agent-shield). |
Tool: send_email
| Feld | Typ | Erforderlich |
|---|---|---|
to | string oder string[] | ja |
subject | string | ja |
text | string | ja |
html | string | nein |
Das Ergebnis wird als JSON im MCP-Text-Content zurückgegeben:
- Erfolg:
{ "ok": true, "messageId": "<id>" } - Fehler:
{ "ok": false, "reason": "<grund>", "hint": "<umsetzbarer Hinweis>" }(ein generischer Versandfehler nutzt"message"statt"hint")
reason | Bedeutung |
|---|---|
recipient_not_allowlisted | Ein Empfänger steht nicht in MAILER_ALLOWED_RECIPIENTS — es wurde nichts versendet. |
smtp_tls_untrusted | Die SMTP-Zertifikatskette konnte nicht verifiziert werden (AV-Interception). |
ca_cert_unreadable | MAILER_CA_CERT ist gesetzt, aber die Datei fehlt oder ist keine gültige PEM. |
missing_config | Eine erforderliche Env-Variable fehlt. |
invalid_input | to / subject / text fehlt oder ist fehlerhaft. |
smtp_send_failed | Versand aus anderem Grund fehlgeschlagen (secret-freie message enthalten). |
TLS hinter AV-Interception
Antiviren-/Firewall-HTTPS-Inspektion (z. B. Norton) signiert TLS mit einem eigenen Root-CA neu. Der entscheidende, verifizierte Punkt: Solche Produkte nutzen zwei verschiedene Roots, und welcher kommt, hängt vom Port ab.
| Endpoint | Präsentierter Issuer | Vertrauensfähig? |
|---|---|---|
| HTTPS (443) | Scanning Root (im OS-Speicher) | ✅ ja |
smtp.gmail.com:587 (STARTTLS) | Scanning Root (im OS-Speicher) | ✅ ja |
smtp.gmail.com:465 (implizites TLS) | Untrusted Root (in keinem Speicher) | ❌ nein — aktiver Distrust |
imap.gmail.com:993 | Untrusted Root (in keinem Speicher) | ❌ nein — aktiver Distrust |
Die Untrusted Root (ihr OU lautet wörtlich „generated by … for untrusted server certificates") ist das Signal der AV-Software, dass sie den Upstream-Server nicht verifizieren konnte. Sie wird bewusst aus jedem Trust-Store herausgehalten — es ist kein Missing-CA-Problem, das man durch Vertrauen beheben könnte.
1. Port 587 + STARTTLS nutzen. Setzen Sie SMTP_PORT=587 und SMTP_SECURE=false. Port 587 wird mit der vertrauensfähigen Scanning Root interceptet, die Verbindung lässt sich also korrekt verifizieren. Implizites TLS auf 465 hinter solcher AV vermeiden.
2. Der Scanning-CA über MAILER_CA_CERT vertrauen. Das ist der zuverlässigste Weg, denn manche MCP-Runtimes (z. B. die eingebettete OpenClaw-Runtime) reichen --use-system-ca oder NODE_OPTIONS NICHT an den gespawnten Prozess durch. MAILER_CA_CERT wird in-process gelesen und zusätzlich zu den eingebauten Roots vertraut — unabhängig davon, wie die Runtime Node startet. rejectUnauthorized bleibt true.
Exportieren Sie die AV-Root in eine PEM (Windows-PowerShell-Beispiel für Norton):
Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -match 'Norton' } |
ForEach-Object { "-----BEGIN CERTIFICATE-----`n" +
[Convert]::ToBase64String($_.RawData, 'InsertLineBreaks') +
"`n-----END CERTIFICATE-----" } |
Set-Content -Encoding ascii C:\Users\sie\inspizierende-ca.pemAnschließend MAILER_CA_CERT auf diese Datei zeigen lassen.
Was die Gründe bedeuten. Lässt sich die Kette weiterhin nicht verifizieren, liefert send_email smtp_tls_untrusted mit dem Hint „TLS certificate could not be verified — most likely an antivirus or firewall performing HTTPS inspection with a root CA that Node does not trust by default. Start Node with --use-system-ca (Node ≥22) so it trusts the OS certificate store, or set NODE_EXTRA_CA_CERTS to the inspecting CA. This does NOT disable certificate verification." — plus dem Hinweis, dass MAILER_CA_CERT der zuverlässigste Weg ist. Zeigt MAILER_CA_CERT auf eine fehlende oder Nicht-PEM-Datei, kommt ca_cert_unreadable (fail-closed — es fällt nie stillschweigend auf Standard-Trust zurück).
Niemals die Untrusted Root in einen Trust-Store oder in
MAILER_CA_CERTaufnehmen, und niemalsrejectUnauthorized: falseoderNODE_TLS_REJECT_UNAUTHORIZED=0setzen. Der Untrusted Root zu vertrauen bedeutet, Verbindungen zu vertrauen, die die AV-Software selbst nicht verifizieren konnte — eine echte MITM-Lücke. Der korrekte Weg ist Port 587 + Scanning Root; die Prüfung bleibt aktiv.
Das ist das SMTP-spezifische Gegenstück zum gateway_tls_untrusted des Gateways — gleiche Trust-Philosophie, ein Modell. Zur Gateway-Seite siehe OpenClaw Integration.
Allowlist: Test vs. Produktion
Halten Sie MAILER_ALLOWED_RECIPIENTS so eng wie möglich. Im Setup/Test eine einzelne Testadresse nutzen. Für die Produktion bewusst erweitern, Adresse für Adresse — die Allowlist ist die letzte Verteidigungslinie gegen einen injizierten Agenten, der an Beliebige mailt.
# Test / Setup
[email protected]
# Produktion (explizit, geprüft)
[email protected],[email protected]Traces einsehen
Jeder Versand wird wie jede andere Aktion governt: Der vorausgehende governance_check und sein Ergebnis (Recommendation + Outcome, PII-Findings, optionale Flare-Attestierung) erscheinen als Trace im Dashboard — durchsuchbar und filterbar, genau wie die OpenClaw-Governance-Traces. Für programmatischen Zugriff siehe die Traces-API.
Fehlerbehebung
Symptom (reason) | Ursache | Lösung |
|---|---|---|
recipient_not_allowlisted | Empfänger fehlt in der Allowlist. | Adresse zu MAILER_ALLOWED_RECIPIENTS (komma-getrennt) hinzufügen und Server neu starten. |
smtp_tls_untrusted | AV-/Firewall-HTTPS-Inspektion; die Kette lässt sich nicht verifizieren. | Auf Port 587 wechseln (SMTP_PORT=587, SMTP_SECURE=false) und MAILER_CA_CERT auf die Scanning-CA-PEM setzen. Verifikation nie abschalten. |
ca_cert_unreadable | MAILER_CA_CERT gesetzt, aber Datei fehlt oder keine gültige PEM. | Pfad korrigieren / PEM neu exportieren, oder Variable entfernen für Standard-Trust. |
missing_config | Eine erforderliche Env-Variable fehlt. | SMTP_HOST, SMTP_USER, SMTP_PASS und MAILER_ALLOWED_RECIPIENTS setzen. |
Nächste Schritte
- OpenClaw Integration — die Governance-Seite (
governance_check, Gateway-TLS). - Eigene Policies erstellen, um zu governen, was Ihr Agent mailen darf.
- Approval Workflows einrichten für Hochrisiko-Versände.