Active Directory : notification par e-mail pour l’expiration de mot de passe
Sommaire
I. Présentation
Dans ce tutoriel, je vous propose de mettre en place un script PowerShell qui va envoyer une notification par e-mail aux utilisateurs X jours avant l'expiration de leur mot de passe Active Directory, afin de les inviter à changer le mot de passe avant la date butoir.
Selon les environnements, et sous réserve qu'il y ait une politique de mots de passe en place (ce qui, malheureusement, n'es pas si évident que ça), l'expiration du mot de passe sur un compte utilisateur peut poser des problèmes de connexion sur des services basés sur l'authentification Active Directory. D'ailleurs, j'ai abordé cette problématique plus en détail dans mon article "Active Directory et la mise en cache des identifiants".
L'une des "solutions" consiste à notifier les utilisateurs que leur mot de passe va expirer, quelques jours avant le jour J où ils devront impérativement changer le mot de passe. C'est ce que nous allons voir aujourd'hui, en passant par PowerShell.
II. Récupérer la date d'expiration du mot de passe avec PowerShell
Au sein de l'Active Directory, et plus particulièrement des comptes utilisateurs, chaque objet dispose d'un attribut qui contient la date et l'heure d'expiration du mot de passe. Cette valeur est calculée selon la politique de mots de passe appliquée sur l'utilisateur. Voici le nom de l'attribut auquel je fais référence :
msDS-UserPasswordExpiryTimeComputed
Cette valeur est visible avec l'interface graphique, avec la console "Utilisateurs et ordinateurs Active Directory" via l'onglet "Editeur d'attributs", ou via PowerShell. Voici un exemple :
La valeur de cet attribut n'est pas directement modifiable, car il s'agit d'un attribut construit dont la valeur a la particularité d'être calculée à partir d'autres attributs (pwdLastSet) et objets. Tous les détails de cet attribut sont disponibles dans la documentation de Microsoft :
Cette information est également visible avec la commande historique "net user", en précisant un nom d'utilisateur, puis en regardant le champ "Le mot de passe expire". Voici un exemple avec l'utilisateur "guy.mauve" :
net user guy.mauve /domain
Toutefois, je trouve que la valeur de l'attribut Active Directory est plus fiable que celle renvoyée par cette commande.
Avec PowerShell, on peut afficher la date d'expiration des mots de passe pour un ensemble d'utilisateurs avec cette commande :
Get-ADUser -Filter { (Enabled -eq $True) -and (PasswordNeverExpires -eq $False)} –Properties "DisplayName", "mail", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Displayname","mail",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
Cette commande retourne l'information pour tous les utilisateurs activés et dont le mot de passe a une date d'expiration. Voici un exemple de sortie :
III. Expiration du mot de passe : notification par e-mail
L'e-mail est un canal de communication privilégié et efficace en entreprise, même s'il y a également d'autres solutions de communication comme Microsoft Teams. Le fait d'envoyer une notification par e-mail à l'utilisateur quelques jours avant l'expiration de son mot de passe va vous permettre de communiquer en direct avec lui, de façon automatique.
Désormais, intéressons-nous au script PowerShell, qui est disponible sur mon GitHub : vous pouvez le réutiliser en l'état ou l'adapter à votre guise. Pour utiliser ce script nommé "Send-ADPasswordExpirationNotifications.ps1", vous avez seulement besoin de modifier ces quelques variables :
# Nombre de jours avant l'expiration pour envoyer la notification $DateThreshold = 7 # Serveur SMTP - Nom du serveur $SMTPServer = "smtp.domaine.fr" # Serveur SMTP - Numéro de port $SMTPPort = 25 # Serveur SMTP - Adresse e-mail de l'expéditeur $SMTPSender = "[email protected]" # Serveur SMTP - Encodage Email $SMTPEncoding =[System.Text.Encoding]::UTF8 # Envoyer une synthèse aux administrateurs [boolean]$SendReportAdmin = $true # Adresse e-mail du destinataire pour la synthèse $SendReportAdminEmail = "[email protected]"
Vous pouvez adapter le script pour la prise en charge du SSL et/ou des Credentials dans les commandes Send-MailMessage (pour envoyer les e-mails) selon votre environnement. Vous pouvez aussi ajouter l'option "-Cc" avec votre adresse e-mail, si vous souhaitez recevoir une copie de l'e-mail envoyé à chaque utilisateur.
Lorsque ce script tourne, il va récupérer la date d'expiration du mot de passe pour tous les utilisateurs activés et dont l'option "Le mot de passe n'expire jamais" n'est pas cochée. Ensuite :
- Dans le cas où le seuil de notification est définit à "7", un e-mail sera émis à l'utilisateur si son mot de passe expire dans 7 jours ou moins de 7 jours.
- Dans le cas où le mot de passe est déjà expiré, la notification n'est pas envoyée.
Chaque utilisateur recevra une notification similaire à celle-ci :
Le service informatique recevra une synthèse par e-mail avec la liste des utilisateurs dont le mot de passe expire bientôt. Cet e-mail est envoyé uniquement si "$SendReportAdmin = $true" donc vous pouvez activer ou non ce rapport supplémentaire.
Le script est disponible ici :
Pour que ces notifications soient envoyées automatiquement, il convient d'exécuter ce script dans une tâche planifiée. Sur le contrôleur de domaine avec les rôles FSMO, ce sera très bien à mon sens. Quant au compte utilisé pour l'exécution de la tâche planifiée, un gMSA est conseillé.
L'action à lancer ressemblera à ceci :
powershell.exe -File "C:\Scripts\Send-ADPasswordExpirationNotifications.ps1"
Comme ceci :
Si vous n'êtes pas très à l'aise avec cette partie de la configuration, consultez ces deux articles :
IV. Conclusion
Grâce à la mise en place de ce script, vos utilisateurs seront notifiés que leur mot de passe expire prochainement et pourront procéder à la réinitialisation de celui-ci avant l'échéance précisée dans l'e-mail.
Si vous avez des suggestions pour améliorer le script "Send-ADPasswordExpirationNotifications.ps1", n'hésitez pas à m'en faire part.
Mis en place depuis quelques années sur mon précédent poste.
Technique très efficace pour réduire le nombre de ticket pour mot de passe au support.
Surtout avec la généralisation du télétravail.
J’étais a 9 jours de prévenance.
L’évolution en cours était le write back de mot de passe depuis azure ad pour l’extérieur.
Bonjour, ce script m’intéresse, par contre il est fait pour un exchange local et non pour M365, non?
Encore merci.
C
Bonjour,
Je l’ai utilisé avec Office 365, tout dépend comment est configuré le relais SMTP (j’ai créé un connecteur pour faire cette démo et déclaré mon adresse IP publique dans le SPF au niveau DNS).
Si besoin, la commande pour envoyer les e-mails peut être complétée pour ajouter la prise en charge du SSL/TLS et des credentials. 🙂
Bonjour,
Si je comprends bien avec un relais SMTP (via connecteur), il n’est pas nécessaire d’utiliser des crédentials pour l’envoi de mail c’est ça?
Merci.
Arnaud.
Bonjour,
Possible d’avoir la modification pour envoyer avec la prise en charger du SSL/TLS
Merci d’avance
Excellent vraiment super, j’avais jamais pensé à faire ça, mais c’est top!
Je vais mettre en place très prochainement.
Super travail Florian!
Bonjour,
intéressant votre script,
je fais des test sur un lab
j’avais un compte dont le mdp était expiré,
je l’ai donc réinitialisé, par défaut dans la default domain policy, l’exp du pass est défini à 90 jours.
je lance cette commande la commande pour vérifier l’expiration du pass et j’ai tjrs la date du 19/11/2022 pour le compte dont je viens de changer le pass, normalement je devrais avoir une date à + 3 mois a/c aujourd’hui ?
de plus la propriété évoqué sur vos captures ne figure pas dans l’éditeur d’attribut chez moi,
si tous les mois un mail est envoyé alors que le pass doit être changé ts les 3 mois …
ps mon dc pour le lab : version server 2019
Avez vous une idée ?
Merci
Bonjour,
Je trouve ce script très utile! J’aimerai le mettre en place. Je débute tout juste sur powershell et j’aimerai cibler une UO et pas l’AD entier. Comment le faire?
Merci d’avance pour votre retour.
Dans ta commande Get-Aduser, il suffit de rajouter le paramètre -searchbase + le chemin cible dans ton AD.
Exemple :
Get-ADUser * -searchBase « OU=Informatique,OU=Utilisateurs,DC=toto,DC=local »
Ici je récupérerai tous les objets utilisateurs qui sont membres de la « sous-OU » Informatique, du domaine toto.local
Script excellent. Il manquerait juste (à mon sens) le décompte des jours avant la date fatidique.
Personnellement, j’ai adapté le script de Robert Pearman qui permet cela. L’utilisateur reçoit un mail tous les jours jusqu’à l’expiration.
En revanche je préfère largement le visuel html de ton reporting ! Le script de Pearman envoi juste un mail avec en pièce jointe un fichier.csv dégueulasse..
Bonjour,
est il possible d’avoir le lien GITHUB pour telecharger le script powershell.
merci
Bonjour,
Le lien est dans l’article 🙂
Bonjour,
Merci pour script, très bon boulot !
J’ai dû le modifier pour la prise en compte de l’authentification SSL et le port 587 des messages en utilisant des champs supplémentaires :
$password = ‘monmotdepasse
$userName = ‘[email protected]’
[SecureString]$securepassword = $password | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $securepassword
et au niveau des commande Send-MailMessage j’ai ajouté
-UseSsl -Credential ‘monmotdepasse’
Sinon j’ai juste un soucis c’est que la valeur msDS-UserPasswordExpiryTimeComputed qui est toujours vide chez moi alors que l’expiration des mots de passe tourne bien.
je voulais dire
-UseSsl -Credential $credential
Salut Cyril,
Merci pour le complément d’informations pour l’authentification SMTP, cela sera surement utile à d’autres personnes ! 🙂
Pour l’attribut msDS-UserPasswordExpiryTimeComputed, tu as regardé sur plusieurs DC différents pour voir ?
De rien,
Oui j’ai testé sur plusieurs forets différents en 2019 et toujours le même soucis. soit les dates sont en 1601, soit ils sont vides.
Et pourtant les expirations a 60jours fonctionnent bien.
Bonjour,
Merci pour votre script.
J’ai voulu lancé celui-ci mais j’obtiens les erreurs ci-dessous
At C:\scripts_Powershell\MDP_CPT_SVC\script_PS_Cpt_svc.ps1:109 char:80
+ … Body = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,V …
+ ~
Missing expression after ‘,’ in pipeline element.
At C:\scripts_Powershell\MDP_CPT_SVC\script_PS_Cpt_svc.ps1:109 char:80
+ … ody = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,Vo …
+ ~
The ‘<' operator is reserved for future use.
At C:\scripts_Powershell\MDP_CPT_SVC\script_PS_Cpt_svc.ps1:118 char:95
+ … – Expiration des mots de passe AD – $(Get-Date -Format dd/MM/yyyy)" `
+ ~~~
The string is missing the terminator: ".
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingExpression
Etant débutant en PS, pourriez-vous m'aider svp à comprendre?
Par avance merci
Bonjour à tous,
est-il possible d’avoir une décrémentation des jours sur le mail envoyer aux utilisateurs ? Je m’explique que chaque jours ou le mail est envoyer cela passe de » Dans moins de 10 jours » et le lendemain « Dans moins de 9 jours », etc… ?
Je cherche comment le faire mais je ne trouve pas.
Bonjour Florian,
Je te remercie pour cette formation qui fonctionne parfaitement après la petite modification indiquée par Cyril.
Mais au lieu de mettre en place cette notification par mail, pouvons-nous mettre cela en place via une notification Windows ou par message ?
Je te remercie pour ce retour
Cdt
Nicolas
Bonjour,
Bonjour,
Merci à vous pour le partage de ce script. Je l’ai adapté pour envoyer le mail via l’authentification moderne.
Je rencontre le même problème que Cyril à savoir : la valeur msDS-UserPasswordExpiryTimeComputed qui est vide chez certains utilisateurs.
Est-ce que quelqu’un a ce problème est connaît la raison ? J’ai également essayé sur mes différents contrôleurs et le résultat est le même.
Merci d’avance !
Bravo et merci pour ce script.
Cependant dans le mail récapitulatif pour les admin, l’heure n’apparait pas.
Je cherche également à faire apparaître l’heure dans le mail de l’utilisateur car ils attendent malgré tout le dernier jour et à quelques minutes près, ils se retrouvent coincés et nous appellent.
Je ne trouve pas ce qu’il faut modifier afin de faire apparaître l’heure, sauriez-vous me le dire ?
Vous en remerciant par avance.
Bonjour
Merci pour le script
Cependant pour l’entreprise dont je travail je voulais utiliser le script et après quelques modif j’ai ce message d’erreur
Send-MailMessage : Impossible de se connecter au serveur distant
Au caractère C:\Scripts\Send-ADPasswordExpirationNotifications.ps1:66 : 5
+ Send-MailMessage -Verbose -SmtpServer $SMTPServer -Encoding $SMTP …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Je ne comprends pas l’erreur
Merci d’avance
Bonjour et merci pour le script.
J’ai voulu le lancer dans mon AD et voici les message d’erreur que je rencontre:
Pouvez vous m’apporter votre assistance s’il vous plaît? Je vous remercie d’avance.
PS D:\Script_GPO_Production> D:\Script_GPO_Production\Send-ADPasswordExpirationNotifications.ps1
Send-MailMessageForUser : Impossible de lier l’argument au paramètre « SendMailUserSurname », car il s’agit d’une chaîne vide.
Au caractère D:\Script_GPO_Production\Send-ADPasswordExpirationNotifications.ps1:102 : 97
+ … rGivenName $User.GivenName -SendMailUserSurname $User.Surname -SendMa …
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData : (:) [Send-MailMessageForUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Send-MailMessageForUser
PS D:\Script_GPO_Production>
J’ai le même problème…
Bonjour
J’ai essayé de faire fonctionner ce scriptsur le dc principal aprés l’avoir adapté pour office 365, je pensais que je rencontrerai peut-être des erreurs liées à mes modification mais finalement comme d’autre utilisateurs j’ai ces errurs/
Au caractère C:\users\admindp\documents\notification expiration du mot de passe.ps1:119 : 81
+ … Body = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,V …
+ ~
Expression manquante après « , » dans l’élément de pipeline.
Au caractère C:\users\admindp\documents\notification expiration du mot de passe.ps1:119 : 81
+ … ody = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,Vo …
+ ~
L’opérateur « < » est réservé à une utilisation future.
Au caractère C:\users\admindp\documents\notification expiration du mot de passe.ps1:122 : 85
+ … -replace " », » »
+ ~
Le terminateur » est manquant dans la chaîne.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingExpression
J’ai donc fais un test en supprimant le corps du message pour voir ce que cela donnait et j’ai eu une autre erreur :
Au caractère C:\users\admindp\documents\notification expiration du mot de passe.ps1:100 : 110
+ … [datetime]::FromFileTime($User. »msDS-UserPasswordExpiryTimeComputed »)
+ ~~
Le terminateur » est manquant dans la chaîne.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
J’ai testé la variable
S C:\users\admindp\documents> $UserPasswordExpirationDate = [datetime]::FromFileTime($User. »msDS-UserPasswordExpiryTimeComputed »)
PS C:\users\admindp\documents> $UserPasswordExpirationDate
lundi 1 janvier 1601 01:00:00
Je ne comprend pas l’origine de ces erreurs vu que le code fonctionne pour d’autre personne, est-ce un problème de version de powershell? j’ai utilisé la 5.1 built 17763 qui commence à dater
J’ai ensuite installé la version 7 avec le module exchangeonlinemanagement et là c’est encore pire avec ce type de message:
WARNING: The command ‘Send-MailMessage’ is obsolete. This cmdlet does not guarantee secure connections to SMTP servers. While there is no immediate replacement available in PowerShell, we recommend you do not use Send-MailMessage at this time. See https://aka.ms/SendMailMessage for more information.
-Subject: C:\Users\admindp\Documents\notification expiration du mot de passe.ps1:76
Line |
76 | -Subject $SendMailObject
| ~~~~~~~~
| The term ‘-Subject’ is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
-Body: C:\Users\admindp\Documents\notification expiration du mot de passe.ps1:77
Line |
77 | -Body $SendMailBody -BodyAsHtml -Port $SMTPPort
| ~~~~~
| The term ‘-Body’ is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Bonjour
Tout d’abord merci pour toutes ces infos bien utiles.
lorsque que je lance le script j’ai les erreurs suivantes :
pouvez vous me dire d’où cela vient
PS C:\scripts> .\Send-ADPasswordExpirationNotifications.ps1
Au caractère C:\scripts\Send-ADPasswordExpirationNotifications.ps1:111 : 80
+ … Body = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,V …
+ ~
Expression manquante après « , » dans l’élément de pipeline.
Au caractère C:\scripts\Send-ADPasswordExpirationNotifications.ps1:111 : 80
+ … ody = $UsersNotifList | ConvertTo-HTML -PreContent « Bonjour,Vo …
+ ~
L’opérateur « < » est réservé à une utilisation future.
Au caractère C:\scripts\Send-ADPasswordExpirationNotifications.ps1:120 : 95
+ … – Expiration des mots de passe AD – $(Get-Date -Format dd/MM/yyyy)" `
+ ~~~
Le terminateur " est manquant dans la chaîne.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingExpression
Cordialement
Eric
Bonjour
Très bon script.
J’ai dut juste rajouter les passwords expiré non traité par ce script.
En complément, la date :
lundi 1 janvier 1601 01:00:00
Correspond au password expiré.
Bonjour,
Une question, si on exécute le script par une tâche planifié tous les jours, suite à la cette phase
« Dans le cas où le seuil de notification est définit à « 7 », un e-mail sera émis à l’utilisateur si son mot de passe expire dans 7 jours ou moins de 7 jours. »
cela veux dire que la personnes va recevoir un mail tous les jours sur 7 jours ?
Merci