I am very glad to see there are more than 50,000 views in my blog when starting on counting “total visits” in my blog 7 months ago. Below are the top views from my blog.
![](https://tungle.ca/wp-content/uploads/2023/02/image-4-1024x331.png)
Today, I want to share a small IT PowerShell script which is used to send notification to domain users before their password will be expired.
According to MS link (https://learn.microsoft.com/en-us/windows/win32/adschema/a-msds-userpasswordexpirytimecomputed), ms-DS-User-Password-Expiry-Time-Computed attribute is used to contain user password’s expire time in Active Directory. So, using the PowerShell code below to query this value in AD.
Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties DisplayName, EmailAddress, msDS-UserPasswordExpiryTimeComputed
![](https://tungle.ca/wp-content/uploads/2023/02/1-1024x268.png)
However, the value “133214896056482435” does not have any meaning, so we use [datetime]::FromFileTime($_.”msDS-UserPasswordExpiryTimeComputed”) to convert this value from FromFileTime to DateTime format in PowerShell.
# Query AD user
$Users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties DisplayName, EmailAddress, msDS-UserPasswordExpiryTimeComputed | `
Select-Object -Property DisplayName, EmailAddress, @{Name="ExpirationDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | `
Sort-Object "ExpirationDate"
$users | sort-object ExpirationDate
The PowerShell outputs a list of Domain users corresponding to “Display Name”, “EmailAddress” and “ExpirationDate”.
![](https://tungle.ca/wp-content/uploads/2023/02/2.png)
Next, check if the password will be expired soon (14 days) and send email notification to domain users.
# Query AD user
$Users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties DisplayName, EmailAddress, msDS-UserPasswordExpiryTimeComputed | `
Select-Object -Property DisplayName, EmailAddress, @{Name="ExpirationDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | `
Sort-Object "ExpirationDate"
#$users | sort-object ExpirationDate
# Check if the password will be expired soon and send email notification.
$UserList = foreach ($User in $users) {
if ($User.ExpirationDate -le (Get-Date).AddDays(14) -and $User.ExpirationDate -ge (Get-Date))
{
# Create PSCustomObject to save a list of users whom will have a password expired soon
[PSCustomObject]@{
Name = $User.DisplayName
EmailAddress = $User.EmailAddress
ExpiryDate = $User.ExpirationDate
}
}
}
$userlist | sort-object ExpirationDate
PowerShell outputs a list of domain users who have the domain password will be expired soon.
![](https://tungle.ca/wp-content/uploads/2023/02/3-1024x175.png)
Now, we will write an entire script to send email notification before AD password will be expired.
Get a password from the console, encrypt it and save into the file C:\Shared\admincred.txt
Read-Host -Prompt "Enter your tenant password" -AsSecureString | ConvertFrom-SecureString | Out-File "C:\Shared\admincred.txt"
![](https://tungle.ca/wp-content/uploads/2023/02/4-1024x139.png)
cat C:\Shared\admincred.txt
![](https://tungle.ca/wp-content/uploads/2023/02/5-1024x97.png)
Below is a full PowerShell script to send email notification.
# PowerShell script that can send email notifications to domain users before their passwords will be expired.
# Query AD user
$Users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties DisplayName, EmailAddress, msDS-UserPasswordExpiryTimeComputed | `
Select-Object -Property DisplayName, EmailAddress, @{Name="ExpirationDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | `
Sort-Object "ExpirationDate"
# Check if the password will be expired soon and send email notification.
$UserList = foreach ($User in $users) {
if ($User.ExpirationDate -le (Get-Date).AddDays(14) -and $User.ExpirationDate -ge (Get-Date))
{
# Create PSCustomObject to save a list of users whom will have a password expired soon
[PSCustomObject]@{
Name = $User.DisplayName
EmailAddress = $User.EmailAddress
ExpiryDate = $User.ExpirationDate
}
# Send email
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$SMTP = "smtp-mail.outlook.com"
$From = "admin@outlook.com"
$username = "admin@outlook.com"
#Read-Host -Prompt "Enter your tenant password" -AsSecureString | ConvertFrom-SecureString | Out-File "C:\Shared\admincred.txt"
$Pass = Get-Content "C:\Shared\admincred.txt" | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PSCredential -argumentlist $username, $Pass
$Subject = "Password Expiration Warning"
$Body = "Dear $($User.DisplayName)," + "`n`nYour password will expire in $User.ExpirationDate. Please change your password as soon as possible." + "`n`nRegards," + "`nIT Department"
$EmailBody = "Hello $($User.DisplayName)," + "`n`n" +
"This is a reminder that your password will expire in $($User.ExpirationDate)." + "`n`n" +
"Please take a moment to change your password to ensure continued access to your account." + "`n`n" +
"Thank you," + "`n" +
"IT Team"
# Try to send the email, catch any exceptions, and log them
Try {
# Send-MailMessage -From $From -To $User.EmailAddress -Subject $Subject -Body $EmailBody -smtpserver $SMTP -usessl -Credential $cred -Port 587
$EmailMessage = @{
From = $From
To = $User.EmailAddress
Subject = $Subject
Body = $EmailBody
SmtpServer = $SMTP
UseSsl = $True
Credential = $cred
Port = 587
}
Send-MailMessage @EmailMessage
# Log success
Add-Content -Path "C:\Shared\Logs\EmailSuccess.log" -Value "Email sent successfully to $($User.DisplayName) at $($User.EmailAddress) on $(Get-Date) "
}
Catch {
# Write the error message to the file EmailFailure.log under C:\Shared\Logs.
Write-Host "Error sending email to $($User.DisplayName) at $($User.EmailAddress): $_"
Add-Content -Path "C:\Shared\Logs\EmailFailure.Log" -Value "Error sending email to $($User.DisplayName) at $($User.EmailAddress) on $(Get-Date) $_"
}
}
}
$Userlist | sort-object ExpirationDate
Run the script.
C:\Users\Administrator\passwordnotify.PS1
![](https://tungle.ca/wp-content/uploads/2023/02/6-1024x85.png)
Checking the EmailSuccess.log file, the script was successfully sent email notification to AD users before their password will be expired.
![](https://tungle.ca/wp-content/uploads/2023/02/7-1024x424.png)
The script sent an email notification to AD users.
![](https://tungle.ca/wp-content/uploads/2023/02/8-1024x409.png)
Finally, we can add the script into the Task Scheduler to check domain users’ password expiration and send email notification.
![](https://tungle.ca/wp-content/uploads/2023/02/image-18.png)
Trigger tab.
![](https://tungle.ca/wp-content/uploads/2023/02/image-2-1024x719.png)
Actions tab.
![](https://tungle.ca/wp-content/uploads/2023/02/11-1024x459.png)
Actions Settings:
Program: %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
Arguments: -ExecutionPolicy Bypass -File C:\Shared\passwordnotify.PS1
The task was running successfully in Task Scheduler history.
![](https://tungle.ca/wp-content/uploads/2023/02/16-1024x795.png)
![](https://tungle.ca/wp-content/uploads/2023/02/17-1024x389.png)
The email notification was sent to Gmail’s account.
![](https://tungle.ca/wp-content/uploads/2023/02/18-1024x427.png)