Aller au contenu
Avanet

Gérer la quarantaine Sophos Email par API

L’Email Quarantine API traite les messages que Sophos Email a placés dans la quarantaine de sécurité de messagerie ordinaire avant leur livraison. La procédure sûre consiste à effectuer une recherche ciblée, examiner chaque page, consigner le X-Sophos-Email-ID et le destinataire, inspecter le contenu, effectuer une modification de portée réduite et vérifier le résultat pour chaque destinataire.

Cet article utilise uniquement les chemins sous /email/v1/quarantine. Malgré son nom similaire, la Post-Delivery Quarantine concerne des messages déjà livrés puis rappelés et possède sa propre famille d’endpoints. Ne mélangez pas ses chemins, identifiants ou états avec cette procédure.

Préparer les prérequis et les variables

Commencez par suivre l’introduction à la Sophos Email Management API. Le guide prévu Authentifier la Sophos Email API et acheminer les requêtes vers un tenant détaille le Service Principal, la résolution du tenant et les autorisations minimales. Les valeurs suivantes doivent déjà avoir été déterminées de façon sûre :

  • SOPHOS_ACCESS_TOKEN : jeton bearer OAuth2 de courte durée ;
  • SOPHOS_TENANT_ID : UUID du tenant cible ;
  • SOPHOS_API_HOST : hôte API régional de ce tenant ;
  • une autorisation Email Quarantine attribuée au Service Principal.
EMAIL_API_HOST="${SOPHOS_API_HOST%/}/email/v1"

Les jetons, URL de téléchargement, mots de passe ZIP, en-têtes MIME et textes des messages sont des secrets ou des données personnelles. Ils ne doivent figurer ni dans l’historique du shell, ni dans les arguments de processus, ni dans les sorties CI ou les tickets. Les blocs JSON suivants sont volontairement des exemples de documentation ; en production, écrivez les payloads dans des fichiers temporaires protégés ou transmettez-les par l’entrée standard.

Les contrats décrits ont été vérifiés avec l’Email Management API v1.4.0. Avant toute mise en œuvre, vérifiez à nouveau la méthode, le chemin, le schéma, l’autorisation et les limites dans la spécification actuelle.

Effectuer une recherche ciblée et paginer tous les résultats

POST /quarantine/messages/search exige beginDate et endDate sous forme d’instants ISO 8601. Les filtres sont facultatifs. L’exemple limite un cas de malware entrant à un destinataire et demande 100 enregistrements, soit le maximum documenté par page de recherche :

{
  "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"]
  }
}

Le contrat de filtrage comprend id, fromContains, toContains, subjectContains, attachmentNameContains, hasAnyAttachment, sizeInMBGreaterThan, sizeInMBLowerThan, direction (inbound ou outbound), productType (mailflow, gateway ou ems) et reason. Les champs de tri documentés sont from, forRecipient et quarantinedAt. fields permet de demander une réponse partielle ; un client ne doit pas interpréter les champs omis comme des valeurs vides.

La réponse contient items et pages. Pour la page suivante, copiez pages.nextKey sans modification et sous forme de chaîne dans pageFromKey du corps POST suivant. Ne terminez que lorsque nextKey n’est plus présent et protégez aussi la boucle par des limites de pages et de durée ainsi que par la détection des clés répétées. pages.size décrit seulement la page actuelle. Une première page pleine ou vide ne prouve donc ni que la recherche est complète, ni qu’il n’existe aucun autre résultat.

Consignez au minimum id, forRecipient, reason, quarantinedAt, direction et l’opération prévue pour chaque résultat. id est l’UUID de l’en-tête MIME X-Sophos-Email-ID ; mimeMessageId est l’en-tête Message-ID ordinaire et ne peut le remplacer dans un chemin API ou un corps de requête en masse. Un même message peut produire des résultats propres à chaque destinataire.

Inspecter le message, les URL et les pièces jointes

Les trois opérations de lecture utilisent le id encodé pour une URL dans le chemin :

GET /quarantine/messages/{id}/preview
GET /quarantine/messages/{id}/urls?pageSize=50&page=1
GET /quarantine/messages/{id}/attachments?pageSize=50&page=1

L’aperçu renvoie headers, htmlBody et textBody. Traitez le HTML comme un contenu hostile : ne le rendez pas directement dans un navigateur ou un portail d’administration, ne chargez pas de ressources externes et n’ouvrez pas les liens inclus. Pour l’analyse, préférez le texte et certains en-têtes.

Les listes d’URL et de pièces jointes utilisent des pages numérotées à partir de 1. La valeur par défaut de pageSize est 50 ; la réponse indique le maximum autorisé dans pages.maxSize et peut, d’après le schéma vérifié, contenir jusqu’à 500 éléments. Continuez jusqu’à ce que pages.current atteigne la dernière page signalée ou qu’une page vide suive. N’utilisez pas ici le modèle de clé de la recherche (nextKey).

Un enregistrement d’URL est un indice, pas un verdict de sécurité. Un enregistrement de pièce jointe contient name, sizeInBytes, fileType et stripped. Les actions désignent les pièces jointes par leur nom documenté, pas par un UUID de pièce jointe inventé. En cas de noms identiques ou de liste inattendue, ne faites aucune supposition : examinez le cas manuellement.

Télécharger, retirer ou rattacher des pièces jointes

Le téléchargement est asynchrone et se déroule en deux étapes. Démarrez d’abord un job pour un message. Si attachments est omis, le job inclut toutes les pièces jointes ; une liste explicite est plus sûre dans un cas contrôlé :

POST /quarantine/messages/{id}/attachments/download
{
  "attachments": ["sample.zip"]
}

La réponse contient au moins le id et le status du job. Cet ID devient le downloadId du chemin de statut et ne doit pas être confondu avec l’ID du message :

GET /quarantine/downloads/{downloadId}/status

Interrogez le statut avec un backoff limité jusqu’à ce que status soit completed ou failed. Avec completed, attachments, une url signée et un password pour le ZIP protégé peuvent apparaître. L’URL est un accès de courte durée : téléchargez-la rapidement et uniquement dans un environnement d’analyse isolé et approuvé, ne la journalisez jamais et, si elle expire, utilisez le statut du job ou un nouveau job autorisé. Avec failed, analysez error ; le client ne doit pas lancer indéfiniment de nouveaux jobs.

Strip et reattach modifient l’état des pièces jointes pour chaque destinataire :

POST /quarantine/messages/{id}/attachments/strip
POST /quarantine/messages/{id}/attachments/reattach
{
  "attachments": ["sample.zip"],
  "forRecipients": ["analyst@example.test"]
}

forRecipients limite la modification. Sans cette restriction, l’action peut toucher d’autres destinataires du message. Séparez toujours la réponse entre items réussis et errors en échec. Récupérez ensuite la liste des pièces jointes et contrôlez stripped pour le nom prévu. Reattach ne libère pas le message et ne prouve pas que la pièce jointe est sûre.

Libérer ou supprimer des messages de façon contrôlée

Release et delete acceptent au maximum 50 enregistrements par requête. Chaque enregistrement exige le X-Sophos-Email-ID ; forRecipients est facultatif, mais constitue la restriction sûre pour une opération propre à un destinataire.

POST /quarantine/messages/release
POST /quarantine/messages/delete

Une libération étroitement limitée se présente ainsi :

{
  "items": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "forRecipients": ["analyst@example.test"],
      "stripAttachments": ["sample.zip"]
    }
  ],
  "allowSender": false,
  "enforceSenderAuthentication": false,
  "submitMessageToLabs": false
}

Release renvoie HTTP 202 : le message a été accepté et placé en file d’attente pour libération, sans preuve de livraison. allowSender et enforceSenderAuthentication restent à false par défaut. N’autorisez un expéditeur qu’après une validation de sécurité distincte ; si vous activez volontairement allowSender, ne laissez pas l’authentification de l’expéditeur désactivée par mégarde. submitMessageToLabs ne s’applique qu’aux messages de spam et de virus. stripAttachments agit par enregistrement de libération.

Demandez la suppression séparément, sans blocage implicite de l’expéditeur :

{
  "items": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "forRecipients": ["analyst@example.test"]
    }
  ],
  "blockSender": false
}

Delete renvoie HTTP 200 en cas de réussite. blockSender est une modification de politique supplémentaire et plus large ; il reste à false sans demande de blocage approuvée. Ne répétez pas aveuglément release ou delete après un timeout : le serveur peut déjà avoir accepté la première requête.

Les deux réponses en masse peuvent contenir simultanément items et errors. Une réussite HTTP ne signifie donc pas que chaque paire ID/destinataire a réussi. Faites correspondre chaque paire demandée exactement une fois aux deux tableaux ; tout résultat absent, dupliqué ou contradictoire doit empêcher une confirmation automatique de réussite.

Vérifier le résultat

Effectuez les contrôles suivants pour chaque modification :

  1. Journalisez le request ID ou correlation ID, le statut HTTP, l’heure, le tenant et une liste expurgée des paires ID/destinataire ; ne stockez ni contenu ni secret.
  2. Pour strip/reattach, listez de nouveau les pièces jointes et contrôlez stripped pour chaque nom.
  3. Pour release, évaluez tous les items et errors, répétez la même recherche de quarantaine et confirmez la livraison réelle au moyen de la preuve opérationnelle prévue. 202 seul ne suffit pas.
  4. Pour delete, évaluez tous les items et errors et répétez la même recherche. Une entrée absente ne constitue une preuve qu’avec la réponse en masse positive, car la fenêtre temporelle et les filtres peuvent aussi masquer des résultats.
  5. Pour les téléchargements, faites correspondre le downloadId, le statut final et les noms demandés ; supprimez l’URL et le mot de passe de la mémoire et du stockage temporaire à la fin.

Résoudre les échecs partiels, jobs expirés et problèmes d’autorisation

  • Une partie de l’action en masse échoue : Évaluez errors selon id, recipient et error. Ne renvoyez pas les paires réussies. Traitez dans une nouvelle requête uniquement les paires en erreur qui existent encore et ont été de nouveau approuvées.
  • 400 Bad Request : Vérifiez les types JSON, champs obligatoires, instants ISO, UUID, valeurs enum, modèle de pagination et les limites respectives de 50 ou 100. pageFromKey est une chaîne, pas un numéro de page.
  • 401 ou 403 : Renouvelez le jeton par le flux OAuth2 normal ou vérifiez l’attribution au Service Principal, l’autorisation Email Quarantine et le tenant. Ne passez pas à un autre tenant ou hôte.
  • 404 ou ID non valide : Vérifiez que l’UUID provient de X-Sophos-Email-ID, existe toujours dans la quarantaine ordinaire et appartient au tenant. N’utilisez ni mimeMessageId, ni downloadId, ni un ID de Post-Delivery Quarantine.
  • Le téléchargement reste en processing : Limitez l’intervalle et la durée totale des interrogations, vérifiez l’ID du job et le tenant et escaladez avec le request/correlation ID. Ne lancez pas continuellement de nouveaux jobs parallèles.
  • Le téléchargement est failed ou l’URL a expiré : Conservez error, vérifiez encore une fois le statut et ne lancez un nouveau téléchargement que si la demande reste valable. Ne modifiez ni ne réutilisez une URL signée.
  • La pièce jointe manque ou son état diffère : Lisez toutes les pages numérotées de pièces jointes, comparez exactement les noms et vérifiez les errors par destinataire. Arrêtez-vous en cas de noms identiques ou si le message a déjà été libéré.
  • La libération disparaît de la liste mais n’arrive pas : Elle a seulement été mise en file d’attente. Vérifiez le destinataire, répétez le filtrage et examinez les preuves de livraison en aval ; ne libérez pas automatiquement une seconde fois.

Une escalade doit inclure la version de l’API, l’hôte régional sans identifiants, l’ID du tenant, la fenêtre UTC, la méthode et le chemin, le statut HTTP, le request/correlation ID ainsi que les ID d’objets et codes d’erreur expurgés. Excluez les jetons, URL signées, mots de passe ZIP, textes des messages et pièces jointes.