mail-api.schaefer.zone · Strict Mail API for the AI agent · Status: online
michael@schaefer.zone. Es gelten strenge Regeln:
/next liefert dann nicht das Nächste, sondern die gleiche Mail zurück (mit Status 409).Alle Endpunkte außer /, /health und /admin/* erfordern einen Bearer-Token im Authorization-Header:
Authorization: Bearer <API_TOKEN>
No auth. Liveness check.
{ "status": "ok", "ts": 1718880000 }
Holt die nächste berechtigte Mail (älter als 10h, nicht geblockt), lockt sie und liefert die vollständige Mail (Headers + Body) zurück.
Wenn bereits eine Mail gelockt ist: liefert 200 OK mit derselben bereits gelockten Mail zurück (zusätzlich Feld "lock_reissued": true). /next rückt also niemals vor, solange die alte Mail nicht per /move oder /skip abgearbeitet wurde. Ein abgestürzter Client kann somit einfach /next erneut aufrufen.
Der 5-Minuten-Auto-Release greift nur, falls der Server selbst abstirbt oder der Client gar nicht mehr antwortet.
// 200 OK (neue Mail gelockt)
{
"uid": 87951,
"uidvalidity": 1730000000,
"folder": "INBOX",
"from": { "name": "GitLab", "addr": "gitlab@mg.gitlab.com" },
"to": [{ "name": null, "addr": "michael@schaefer.zone" }],
"cc": [],
"subject": "SessionVault | Successful pipeline...",
"date": "2026-06-20T09:37:00.000Z",
"message_id": "<...>",
"in_reply_to": null,
"headers": { ... },
"body": { "text": "Plain text body", "html": "<html>...</html>" },
"attachments": [
{ "filename": "invoice.pdf", "mime": "application/pdf", "size": 124356, "content_id": null }
],
"has_attachment": true,
"flags": [],
"locked_at": 1718880000,
"expires_at": 1718880300,
"lock_reissued": false
}
// 200 OK (Lock bereits aktiv – gleiche Mail erneut)
{ ...gleiche Struktur..., "lock_reissued": true }
// 404 Not Found
{ "error": "no_eligible_mail", "message": "Keine berechtigte Mail gefunden." }
Liefert die aktuell gelockte Mail erneut (oder 404 falls keine aktiv).
Liefert den Anhang mit Index :index (0-basiert) der aktuell gelockten Mail als Binary-Stream mit passenden Content-Type- und Content-Disposition-Headern.
Verschiebt die aktuell gelockte Mail in den angegebenen AI-Subordner und hebt den Lock auf.
// Request body
{ "to": "AI.Aufbewahren.Kaeufe" }
// 200 OK
{ "status": "moved", "uid": 87951, "from": "INBOX", "to": "AI.Aufbewahren.Kaeufe" }
// 400 (Target nicht erlaubt)
{ "error": "invalid_target", "message": "Target muss mit 'AI.' beginnen." }
// 409 (kein aktiver Lock)
{ "error": "no_active_lock" }
Überspringt die aktuell gelockte Mail. Pflichtfelder: reason und category. Die Mail wird dauerhaft geblockt, bis ein Admin sie freigibt.
// Request body
{
"reason": "Mail enthält Passwort-Reset-Link – kann nicht beurteilen ob Phishing.",
"category": "uncertain_security", // uncertain_security | private_sensitive | needs_human | spam_suspect | other
"confidence": 0.3 // optional 0.0–1.0
}
// 200 OK
{ "status": "skipped", "uid": 87951, "blocked_until": "admin_release" }
// 400 (reason/category fehlen)
{ "error": "missing_fields", "fields": ["reason", "category"] }
Listet alle AI-Subordner auf (nur AI.*, nichts anderes).
{
"folders": [
{ "path": "AI.Spam", "name": "Spam", "special": null },
{ "path": "AI.WICHTIG.Persoenlich", "name": "Persoenlich", "special": null }
],
"count": 15
}
Legt einen neuen AI-Subordner an. Blockt bei Überschreitung von 30 direkten Subordnern.
// Request body
{ "name": "AI.Aufbewahren.XYZ" }
// 200 OK
{ "status": "created", "path": "AI.Aufbewahren.XYZ" }
// 400 (Max überschritten)
{ "error": "max_subfolders_reached", "current": 30, "max": 30 }
Stellt einen Antrag auf Ordner-Umstrukturierung (rename/merge/delete). Wird im Admin-Bereich entschieden.
// Request body
{
"action": "rename", // rename | merge | delete
"from": "AI.Aufbewahren.Kaeufe",
"to": "AI.Aufbewahren.Bestellungen",
"reason": "Besserer Standardbegriff"
}
// 200 OK
{ "status": "request_submitted", "id": 14 }
Liefert die letzten Audit-Einträge (read-only).
Query-Parameter: ?limit=200, ?since=1718870000 (Unix-Sekunden).
Der Admin-Bereich ist unter /admin erreichbar und benötigt ein separates Passwort (Session-Cookie). Er bietet:
# 1. Nächste Mail holen
curl -H "Authorization: Bearer $TOKEN" \
https://mail-api.schaefer.zone/next
# 2. Falls lock_reissued=true (Lock war noch aktiv): dieselbe Mail erneut
# Einfach weiterarbeiten – kein Warten nötig.
curl -H "Authorization: Bearer $TOKEN" \
https://mail-api.schaefer.zone/current
# 3. Falls Anhang vorhanden, gezielt laden
curl -H "Authorization: Bearer $TOKEN" \
https://mail-api.schaefer.zone/current/attachments/0 -o file.pdf
# 4. Entscheiden: verschieben oder überspringen
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"to":"AI.Aufbewahren.Kaeufe"}' \
https://mail-api.schaefer.zone/move
# ODER
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason":"Unklar","category":"needs_human","confidence":0.2}' \
https://mail-api.schaefer.zone/skip
# 5. Nächste Mail (erst jetzt möglich)
curl -H "Authorization: Bearer $TOKEN" https://mail-api.schaefer.zone/next
© 2026 Michael Schäfer · Hosted on vps1.schaefer.zone · Source: /root/2026-06_ai-mail/api/