Sophos Email Quarantäne per API verwalten
Die Email Quarantine API bearbeitet Nachrichten, die Sophos Email vor der Zustellung in die gewöhnliche Email-Security-Quarantäne verschoben hat. Der sichere Ablauf lautet: eng suchen, jede Seite auswerten, die X-Sophos-Email-ID und Empfänger festhalten, Inhalte untersuchen, eine Änderung mit kleinem Umfang ausführen und das Ergebnis pro Empfänger prüfen.
Dieser Artikel verwendet ausschliesslich Pfade unter /email/v1/quarantine. Die ähnlich klingende Post-Delivery Quarantine betrifft bereits zugestellte und danach zurückgezogene Nachrichten und hat eine eigene Endpunktfamilie. Ihre Pfade, IDs und Zustände dürfen nicht mit diesem Ablauf gemischt werden.
Voraussetzungen und Variablen vorbereiten
Zuerst den Einstieg in die Sophos Email Management API durcharbeiten. Die geplante Anleitung Sophos Email API authentifizieren und zum Tenant routen vertieft Service Principal, Tenantauflösung und minimale Berechtigungen. Für diesen Ablauf müssen folgende Werte bereits sicher ermittelt sein:
SOPHOS_ACCESS_TOKEN: kurzlebiger OAuth2-Bearer-Token;SOPHOS_TENANT_ID: UUID des Ziel-Tenants;SOPHOS_API_HOST: regionaler API-Host dieses Tenants;- eine dem Service Principal zugewiesene Berechtigung für Email Quarantine.
EMAIL_API_HOST="${SOPHOS_API_HOST%/}/email/v1"
Token, Download-URL, ZIP-Passwort, MIME-Header und Nachrichtentext sind Geheimnisse oder personenbezogene Daten. Sie gehören nicht in Shell-History, Prozessargumente, CI-Ausgaben oder Tickets. Die folgenden JSON-Blöcke sind bewusst Dokumentationsbeispiele; produktive Clients schreiben Payloads in geschützte temporäre Dateien oder übergeben sie über Standard Input.
Die beschriebenen Verträge wurden gegen die Email Management API v1.4.0 geprüft. Vor der Implementierung Methode, Pfad, Schema, Berechtigung und Limits in der aktuellen Spezifikation erneut abgleichen.
Quarantäne eng suchen und vollständig paginieren
POST /quarantine/messages/search verlangt beginDate und endDate als ISO-8601-Zeitpunkte. Filter sind optional. Das folgende Beispiel begrenzt einen eingehenden Malware-Fall auf einen Empfänger und fordert 100 Einträge an, das dokumentierte Maximum pro Suchseite:
{
"beginDate": "2026-09-14T00:00:00.000Z",
"endDate": "2026-09-15T00:00:00.000Z",
"pageSize": 100,
"sort": ["quarantinedAt:DESC"],
"filter": {
"direction": "inbound",
"toContains": "analyst@example.test",
"reason": ["malware"]
}
}
Der Filtervertrag umfasst id, fromContains, toContains, subjectContains, attachmentNameContains, hasAnyAttachment, sizeInMBGreaterThan, sizeInMBLowerThan, direction (inbound oder outbound), productType (mailflow, gateway oder ems) und reason. Die dokumentierten Sortierfelder sind from, forRecipient und quarantinedAt. Mit fields kann man eine Teilantwort anfordern; ein Client darf dann nicht von weggelassenen Feldern auf leere Werte schliessen.
Die Antwort enthält items und pages. Für die nächste Seite übernimmt man pages.nextKey unverändert als String in pageFromKey des nächsten POST-Body. Man beendet die Schleife erst, wenn kein nextKey mehr vorhanden ist, und schützt sie zusätzlich mit maximaler Seitenzahl, Laufzeit und Erkennung wiederholter Schlüssel. pages.size beschreibt nur die aktuelle Seite. Eine volle oder leere erste Seite beweist daher weder Vollständigkeit noch Abwesenheit weiterer Treffer.
Pro Treffer werden mindestens id, forRecipient, reason, quarantinedAt, direction und der geplante Vorgang festgehalten. id ist die UUID aus dem MIME-Header X-Sophos-Email-ID; mimeMessageId ist dagegen der normale Message-ID-Header und kein Ersatz für API-Pfad oder Bulk-Body. Ein und dieselbe Nachricht kann empfängerbezogene Ergebnisse haben.
Nachricht, URLs und Anhänge untersuchen
Alle drei Leseoperationen verwenden die URL-kodierte id im Pfad:
GET /quarantine/messages/{id}/preview
GET /quarantine/messages/{id}/urls?pageSize=50&page=1
GET /quarantine/messages/{id}/attachments?pageSize=50&page=1
Die Vorschau liefert headers, htmlBody und textBody. HTML wird als feindlicher Inhalt behandelt: nicht direkt in einen Browser oder ein Admin-Portal rendern, keine externen Ressourcen nachladen und keine enthaltenen Links öffnen. Für die Analyse bevorzugt man Text und einzelne Header.
URL- und Anhangslisten verwenden nummerierte, bei 1 beginnende Seiten. Der Default für pageSize ist 50; die Antwort nennt in pages.maxSize das zulässige Maximum und kann laut geprüftem Schema bis zu 500 Elemente enthalten. Man iteriert, bis pages.current die letzte gemeldete Seite erreicht oder eine leere Seite folgt. Das Schlüsselmodell der Suche (nextKey) darf hier nicht verwendet werden.
Ein URL-Eintrag ist ein Fund, kein Sicherheitsurteil. Ein Anhangseintrag enthält name, sizeInBytes, fileType und stripped. Aktionen adressieren Anhänge mit ihrem dokumentierten Namen, nicht mit einer erfundenen Attachment-UUID. Bei gleichen Namen oder unerwarteter Liste wird nicht geraten, sondern der Fall manuell geklärt.
Anhänge herunterladen, entfernen oder wieder anhängen
Ein Download ist zweistufig und asynchron. Zuerst startet man für eine Nachricht einen Job. Fehlt attachments, umfasst der Auftrag alle Anhänge; für einen kontrollierten Fall ist eine explizite Liste sicherer:
POST /quarantine/messages/{id}/attachments/download
{
"attachments": ["sample.zip"]
}
Die Antwort enthält mindestens Job-id und status. Diese Job-ID ist der downloadId für den Statuspfad und darf nicht mit der Nachrichten-ID verwechselt werden:
GET /quarantine/downloads/{downloadId}/status
Man pollt mit begrenztem Backoff bis status den Wert completed oder failed hat. Bei completed können attachments, die signierte url und ein password für das geschützte ZIP erscheinen. Die URL ist kurzlebiges Zugriffsmaterial: sofort nur in eine isolierte, genehmigte Analyseumgebung herunterladen, niemals protokollieren und bei Ablauf den Jobstatus beziehungsweise einen neuen, autorisierten Downloadauftrag verwenden. Bei failed wird error ausgewertet; der Client startet nicht endlos neue Jobs.
Strip und Reattach ändern den empfängerbezogenen Anhangszustand:
POST /quarantine/messages/{id}/attachments/strip
POST /quarantine/messages/{id}/attachments/reattach
{
"attachments": ["sample.zip"],
"forRecipients": ["analyst@example.test"]
}
forRecipients grenzt die Änderung ein. Ohne diese Eingrenzung kann die Aktion weitere Empfänger der Nachricht treffen. Die Antwort wird immer in erfolgreiche items und fehlgeschlagene errors zerlegt. Danach ruft man die Anhangsliste erneut ab und prüft stripped für den beabsichtigten Namen. Reattach ist keine Freigabe der Nachricht und kein Beweis, dass der Anhang sicher ist.
Nachrichten kontrolliert freigeben oder löschen
Release und Delete akzeptieren höchstens 50 Einträge pro Request. Jeder Eintrag benötigt die X-Sophos-Email-ID; forRecipients ist optional, aber bei einem empfängerbezogenen Auftrag die sichere Eingrenzung.
POST /quarantine/messages/release
POST /quarantine/messages/delete
Eine eng begrenzte Freigabe sieht so aus:
{
"items": [
{
"id": "11111111-1111-4111-8111-111111111111",
"forRecipients": ["analyst@example.test"],
"stripAttachments": ["sample.zip"]
}
],
"allowSender": false,
"enforceSenderAuthentication": false,
"submitMessageToLabs": false
}
Release liefert HTTP 202: Die Nachricht wurde zur Freigabe angenommen und eingereiht, nicht nachweislich zugestellt. allowSender und enforceSenderAuthentication bleiben standardmässig false. Einen Absender nur nach separater Sicherheitsfreigabe erlauben; wenn allowSender bewusst aktiviert wird, soll die Absenderauthentifizierung nicht versehentlich deaktiviert bleiben. submitMessageToLabs gilt nur für Spam- und Virusnachrichten. stripAttachments wirkt pro Release-Eintrag.
Eine Löschung wird separat und ohne implizite Absendersperre angefordert:
{
"items": [
{
"id": "11111111-1111-4111-8111-111111111111",
"forRecipients": ["analyst@example.test"]
}
],
"blockSender": false
}
Delete liefert bei Erfolg HTTP 200. blockSender ist eine zusätzliche, breiter wirkende Richtlinienänderung und bleibt ohne genehmigten Sperrauftrag false. Release und Delete nicht blind nach Timeout wiederholen: Der Server kann den ersten Request bereits angenommen haben.
Beide Bulk-Antworten können gleichzeitig items und errors enthalten. HTTP-Erfolg bedeutet deshalb nicht, dass alle ID-/Empfänger-Paare erfolgreich waren. Man gleicht jedes angeforderte Paar genau einmal gegen beide Arrays ab; fehlende, doppelte oder widersprüchliche Ergebnisse blockieren die automatische Erfolgsmeldung.
Ergebnis verifizieren
Für jeden Change werden diese Kontrollen ausgeführt:
- Request-ID oder Correlation-ID, HTTP-Status, Zeitpunkt, Tenant und eine redigierte Liste der ID-/Empfänger-Paare protokollieren; keine Inhalte oder Secrets speichern.
- Bei Strip/Reattach die Anhänge erneut listen und
strippedpro Name prüfen. - Bei Release alle
itemsunderrorsauswerten, danach dieselbe Quarantänesuche wiederholen und die tatsächliche Zustellung über den vorgesehenen Betriebsnachweis kontrollieren.202allein genügt nicht. - Bei Delete alle
itemsunderrorsauswerten und dieselbe Suche wiederholen. Eine fehlende Zeile nur zusammen mit der positiven Bulk-Antwort als Nachweis verwenden, weil Zeitfenster und Filter ebenfalls Treffer verbergen können. - Bei Downloads
downloadId, Endstatus und angeforderte Dateinamen abgleichen; URL und Passwort nach Abschluss aus dem Arbeitsspeicher und temporären Ablagen entfernen.
Teilfehler, abgelaufene Jobs und Berechtigungen beheben
- Ein Teil der Bulk-Aktion schlägt fehl:
errorsnachid,recipientunderrorauswerten. Erfolgreiche Paare nicht erneut senden. Nur die weiterhin vorhandenen, erneut genehmigten Fehlerpaare mit einem neuen Request bearbeiten. 400 Bad Request: JSON-Typen, Pflichtfelder, ISO-Zeitpunkte, UUID, Enum-Werte, Seitenmodell und das Limit von 50 beziehungsweise 100 prüfen.pageFromKeyist ein String, keine Seitennummer.401oder403: Token über den normalen OAuth2-Ablauf erneuern beziehungsweise Service-Principal-Zuweisung, Email-Quarantine-Berechtigung und Tenant prüfen. Nicht auf einen anderen Tenant oder Host ausweichen.404oder ungültige ID: Sicherstellen, dass die UUID ausX-Sophos-Email-IDstammt, noch in der gewöhnlichen Quarantäne existiert und zum Tenant gehört. KeinemimeMessageId,downloadIdoder Post-Delivery-ID einsetzen.- Download bleibt
processing: Polling-Intervall und Gesamtdauer begrenzen, Job-ID und Tenant kontrollieren und mit Request-/Correlation-ID eskalieren. Nicht parallel immer neue Jobs starten. - Download ist
failedoder URL abgelaufen:errorsichern, Status noch einmal kontrollieren und nur bei weiterhin gültigem Auftrag einen neuen Download starten. Eine signierte URL nicht bearbeiten oder wiederverwenden. - Anhang fehlt oder Zustand passt nicht: alle nummerierten Anhangsseiten lesen, Namen exakt vergleichen und die
errorspro Empfänger prüfen. Bei Namenskollisionen oder bereits freigegebener Nachricht stoppen. - Release verschwindet aus der Liste, kommt aber nicht an: Freigabe war nur eingereiht. Empfänger, erneute Filterung und nachgelagerte Zustellkontrolle prüfen; nicht automatisch erneut freigeben.
Bei einer Eskalation gehören API-Version, regionaler Host ohne Credentials, Tenant-ID, UTC-Zeitfenster, Methode und Pfad, HTTP-Status, Request-/Correlation-ID sowie redigierte Objekt-IDs und Fehlercodes in den Fall. Token, signierte URLs, ZIP-Passwörter, Nachrichtentexte und Anhänge bleiben ausgeschlossen.