Les admins découvrent souvent qu’un script .NET capable d’envoyer des e‑mails via Exchange Online se bloque dès qu’il est lancé par le Planificateur de tâches : le journal Windows signale alors l’événement SChannel ID 36882, symptôme d’une rupture TLS. Voici un guide complet pour diagnostiquer et éliminer cette erreur.
Vue d’ensemble
Lorsqu’une application .NET ou PowerShell exploitant Microsoft Identity Client s’exécute manuellement dans une session interactive, l’appel SendMailAsync
aboutit. Pourtant, la même binaire, lancée par une tâche planifiée sous le même compte utilisateur, échoue ; Windows consigne alors :
- Journal : Applications & Services Logs → Microsoft‑Windows‑SChannel
- Événement : SChannel ID 36882 « The certificate received from the remote server was issued by an untrusted certificate authority ».
Cette divergence s’explique par les particularités de la session 0, du magasin de certificats Ordinateur local et des restrictions TLS appliquées au contexte de sécurité de la tâche.
Causes techniques les plus fréquentes
Catégorie | Explication détaillée |
---|---|
Contexte de sécurité | Le Planificateur exécute la tâche dans la session 0. Les bibliothèques .NET s’appuient alors sur le magasin de certificats de l’ordinateur, différent de celui de l’utilisateur interactif ; les clés privées d’un certificat client peuvent être inaccessibles. |
Chaîne de confiance TLS | Les certificats root « Microsoft RSA Root Certificate Authority 2017 », « Baltimore CyberTrust Root », etc. ne sont pas présents ou périmés dans Racines de confiance et Intermédiaires de LocalMachine. |
Protocoles et suites de chiffrement | Une stratégie de groupe ou une clé de Registre a désactivé TLS 1.2 / 1.3 pour le contexte SYSTEM . Le serveur Exchange Online refuse alors la négociation. |
Paramètres de la tâche | L’option Exécuter avec les autorisations les plus élevées est décochée ; la tâche hérite d’un token limité incapable de charger les clés machine. |
Variables d’environnement | Le proxy HTTP(S) ou la variable NO_PROXY n’est pas définie pour le service, d’où un échec de la poignée de main TLS derrière certains reverse‑proxies. |
Solutions et bonnes pratiques
1. Configurer la tâche de façon sécurisée
- Dans taskschd.msc, cocher Exécuter avec les autorisations les plus élevées.
- Choisir S’exécuter même si l’utilisateur n’est pas connecté pour obtenir un jeton de type
LOGON_TYPE_SERVICE
plutôt qu’« interactive ». - Spécifier le répertoire de travail dans le champ Démarrer dans pour éviter la résolution relative de fichiers de configuration.
- Placer la tâche dans Bibliothèque → Microsoft → Windows → Application Experience ou un dossier à faible délai de démarrage afin que les dépendances réseau soient déjà initialisées.
2. Vérifier et réparer la chaîne de certificats
- Ouvrir certlm.msc sous un compte Administrateur.
- Importer manuellement les autorités racines officielles d’Exchange Online dans Certificats (Racines de confiance) puis leurs intermédiaires dans Autorités de certification intermédiaires.
- Activer la mise à jour automatique des racines via
gpedit.msc → Configuration ordinateur → Modèles d’administration → Système → Gestionnaire de communications Internet → Paramètres de communication : ActiveX Root Certificates → Activé
. - Redémarrer la machine ou exécuter
certutil -syncWithWU
pour forcer l’actualisation.
3. Garantir la compatibilité TLS 1.2 / 1.3
Pour Windows Server 2012 R2/2016, les protocoles modernes peuvent être désactivés par défaut pour les services. Assurez‑vous des valeurs suivantes :
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" /v Enabled /t REG_DWORD /d 1 /f
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client" /v DisabledByDefault /t REG_DWORD /d 0 /f
Dans un projet .NET Framework ≤ 4.6, forcez le protocole avant tout appel réseau :
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- Installez un runtime .NET 4.8 ou supérieur ; il active TLS 1.2 par défaut.
- Pour .NET 6/7, assurez‑vous que
System.Net.SecurityProtocol
n’a pas été restreint parruntimeconfig.json
. - Appliquez le correctif cumulatif KB 3140245 sur les anciennes plateformes afin d’ajouter le support cryptographique SHA‑2.
4. Consolider l’accès aux clés privées
Un certificat client chargé depuis le magasin CurrentUser reste invisible pour un processus lancé en session 0. Deux stratégies :
- Déplacer le certificat dans LocalMachine et cocher Clé exportable pour éviter l’erreur
Keyset does not exist
. - Dans le code, charger le PFX avec
X509KeyStorageFlags.MachineKeySet | PersistKeySet
. - À l’échelle Azure/hybride, préférez Azure Key Vault assorti d’une identité managée plutôt qu’un PFX local.
5. Adopter un compte de service géré
Un compte de service géré de groupe (gMSA) garantit :
- Un seul secret rotatif géré par Active Directory.
- Un contexte identique pour exécution interactive et non interactive.
- L’absence de mot de passe en clair dans la définition de la tâche.
Après avoir créé le gMSA (Add-ADServiceAccount
), attribuez‑lui l’accès aux clés privées (certutil -setACL
) et renseignez‑le dans l’onglet Général de la tâche.
6. Affiner le déclencheur et l’ordre de démarrage
- Un déclencheur Au démarrage peut échouer si la carte réseau n’a pas encore d’adresse IP. Préférez À l’ouverture de session ou À la connexion au réseau.
- Utilisez l’onglet Conditions pour cocher Démarrer seulement si la connexion réseau est disponible.
- Dans les environnements Citrix ou RDP, évitez les déclencheurs liés à la session utilisateur qui pourraient créer plusieurs instances concurrentes.
7. Contrôles rapides avant validation
Test | Commande / action | Résultat attendu |
---|---|---|
Heure système | w32tm /query /status | Écart NTP < 300 s |
Négociation TLS | openssl s_client -connect outlook.office365.com:443 -tls1_2 | Pas d’alert « unknown ca » |
Droits de la tâche | Onglet Historique → code 0x0 | Succès des étapes Action Started/Completed |
SChannel détaillé | Registre EventLogging = 0x07 | Trames Client Hello / Server Hello complètes |
8. Exemple complet de script PowerShell robuste
# Requires -Version 5.1
# Force TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Connexion via MSAL
\$tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
\$clientId = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
\$certThumb = "ab12 cd34 ef56 7890 ab12 cd34 ef56 7890 ab12 cd34"
\$authority = "[https://login.microsoftonline.com/\$tenantId](https://login.microsoftonline.com/$tenantId)"
\$cert = Get-ChildItem Cert:\LocalMachine\My\$certThumb
\$msalBuilder = \[Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create(\$clientId)
.WithCertificate(\$cert)
.WithAuthority(\$authority)
.Build()
\$token = \$msalBuilder.AcquireTokenForClient(@("[https://graph.microsoft.com/.default")).Execute().AccessToken](https://graph.microsoft.com/.default%22%29%29.Execute%28%29.AccessToken)
# Envoi via Graph
\$body = @{
message = @{
subject = "Test Exchange Online"
body = @{
contentType = "Text"
content = "Message réussi depuis le Planificateur !"
}
toRecipients = @(@{ emailAddress = @{ address = "[destinataire@exemple.com](mailto:destinataire@exemple.com)" } })
}
saveToSentItems = "true"
} | ConvertTo-Json -Depth 5
Invoke-RestMethod -Method POST ` -Uri "https://graph.microsoft.com/v1.0/users/expediteur@exemple.com/sendMail"`
-Headers @{Authorization = "Bearer \$token"} \`
-Body \$body -ContentType "application/json"
Testez le script manuellement ; une fois validé, déclarez‑le dans la tâche planifiée avec le paramètre -ExecutionPolicy Bypass
.
Résultat attendu
Après avoir :
- activé TLS 1.2/1.3 pour le client ;
- installé la chaîne de certificats racine et intermédiaire dans Ordinateur local ;
- élevé les privilèges de la tâche ou utilisé un gMSA ;
- garanti l’accès aux clés privées et un proxy valide,
la négociation TLS se conclut sans alertes SChannel 36882 ; les messages partent du Planificateur de tâches aussi sûrement qu’en exécution manuelle.
FAQ – Problèmes périphériques
Pourquoi l’événement 36882 n’apparaît‑il que dans Applications & Services Logs ?
Il s’agit du journal analytique SChannel, désactivé par défaut. Les alertes critiques sont toutefois redirigées vers ce canal plutôt que dans Système pour éviter la saturation du journal principal.
Puis‑je me contenter d’activer TLS 1.0 pour contourner le problème ?
Non. Microsoft 365 désactive progressivement TLS 1.0/1.1 depuis octobre 2023. En réactivant ces protocoles, vous n’arriverez qu’à un échec Handshake Failure différent.
Un redémarrage est‑il obligatoire après modification du Registre ?
Pas toujours : exécutez gpupdate /force
, puis redémarrez uniquement les services qui consomment SChannel (w3wp.exe, powershell.exe, etc.). Toutefois, un redémarrage global garantit que la pile TLS relit bien toutes les clés.
Que faire si la tâche réussit aléatoirement ?
Ces succès sporadiques pointent souvent vers un load‑balancer qui conserve la session TLS côté serveur. Lorsque la file d’attente bascule vers un autre nœud, la chaîne de certificats est différente et l’erreur réapparaît. Répétez les étapes Chaîne de certificats sur chaque nœud intermédiaire ou forcez SNI dans la requête.
Conclusion
L’événement SChannel ID 36882 masque un problème d’authentification TLS plutôt qu’un bogue d’Exchange Online. En alignant magasin de certificats, configuration TLS, privilèges de tâche et identité de service, on restaure une connexion stable entre le Planificateur Windows et Microsoft 365. Cette méthodologie vous permettra de déployer vos scripts d’envoi d’e‑mails en production sans surprises post‑migration.