A while back I posted a Powershell script to check password expiration’s in your domain. It worked and it got the job done but as I got better with Powershell I decided to take another look at it and refine it. This time around I’ve turned it into a function with the ability to set specific days you want to filter from as well as explicitly adding the send email option. I’ve also added a parameter so you can check specific users to see when the next time they’ll need to change their password. Feel free to comment on the new script to Get Password Expiration Date Using Powershell
Get Password Expiration Date Using Powershell
The only requirement is that you’ll need the Active Directory Powershell module to be able to query that the information stored in AD. Also, if you plan on using the send email parameter you’ll need to modify lines 88-92 so you can send it out of your own smtp server.
Function Get-PasswordExpirationDate {
#requires -Module ActiveDirectory
<#
.SYNOPSIS
Checks to see if the account is X days within password expiration.
For updated help and examples refer to -Online version.
.NOTES
Name: Get-PasswordExpirationDate
Version: 2.0
Author: theSysadminChannel
DateCreated: 2019-Dec-15
.LINK
https://thesysadminchannel.com/get-password-expiration-date-using-powershell-active-directory -
.PARAMETER DaysWithinExpiration
Set the number of days you want to check until the password is expired. Valid options are 1 - 365.
.PARAMETER SendEmail
Send an email to each user that has the EmailAddress populated to notify them that their password is nearning expiration.
.PARAMETER SamAccountName
Specify the user accounts you want to check. This option does not support the SendEmail or DaysWithinExpiration parameters.
.EXAMPLE
Get-PasswordExpirationDate 15
.EXAMPLE
Get-PasswordExpirationDate -DaysWithinExpiration 10 -SendEmail
.EXAMPLE
Get-PasswordExpirationDate -SamAccountName Username1, username2
#>
[CmdletBinding(DefaultParameterSetName="AllAccounts")]
param(
[Parameter(
Position = 0,
Mandatory = $false,
ParameterSetName = "AllAccounts"
)]
[ValidateRange(1,365)]
[int] $DaysWithinExpiration = 10,
[Parameter(
Mandatory = $false,
ParameterSetName = "AllAccounts"
)]
[switch] $SendEmail,
[Parameter(
Mandatory = $false,
ParameterSetName = "SpecificAccounts",
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[string[]] $SamAccountName
)
BEGIN {}
PROCESS {
#Calculating the expired date from the domain's default password policy. -- Do Not Modify --
$MaxPwdAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days
$expiredDate = (Get-Date).addDays(-$MaxPwdAge)
#Calculating the number of days until you would like to begin notifying the users. -- Do Not Modify --
$emailDate = (Get-Date).addDays(-($MaxPwdAge - $DaysWithinExpiration))
#Since specific accounts were specified we'll output their password expiration dates regardless if they are within the expiration date
#Use msDS-UserPasswordExpiryTimeComputed to calculate expiration date in case a fine grain password policy is used
if ($PSBoundParameters.ContainsKey("SamAccountName")) {
foreach ($User in $SamAccountName) {
try {
$ADObject = Get-ADUser $User -Properties PasswordNeverExpires, PasswordLastSet, EmailAddress, msDS-UserPasswordExpiryTimeComputed
if ($ADObject.PasswordNeverExpires -eq $true) {
$DaysUntilExpired = "NeverExpire"
} else {
$ExpirationDate = Get-Date ([datetime]::FromFileTime($ADObject.'msDS-UserPasswordExpiryTimeComputed'))
$DaysUntilExpired = $ExpirationDate - (Get-Date) | select -ExpandProperty Days
}
[PSCustomObject]@{
SamAccountName = $ADObject.samaccountname.toLower()
PasswordLastSet = $ADObject.PasswordLastSet
ExpirationDate = $ExpirationDate
DaysUntilExpired = $DaysUntilExpired
EmailAddress = $ADObject.EmailAddress
}
} catch {
Write-Error $_.Exception.Message
}
}
} else {
$ExpiredAccounts = Get-ADUser -Filter {(PasswordLastSet -lt $EmailDate) -and (PasswordLastSet -gt $ExpiredDate) -and (PasswordNeverExpires -eq $false) -and (Enabled -eq $true)} -Properties PasswordNeverExpires, PasswordLastSet, EmailAddress
foreach ($ADObject in $ExpiredAccounts) {
try {
$DaysUntilExpired = $ADObject.PasswordLastSet - $ExpiredDate | select -ExpandProperty Days
if ($PSBoundParameters.ContainsKey("SendEmail") -and $null -ne $ADObject.EmailAddress) {
#Setting up email parameters to send a notification email to the user
$From = "[email protected]"
$Subject = "Your Password Will Expire in " + $DaysUntilExpired + " days"
$Body = "Hello,`n`nThis email is to notify you that your password will expire in " + $DaysUntilExpired + " days.`n`nPlease consider changing it to avoid any service interruptions.`n`nThank you,`nThe I.T. Department."
$smtpServer = "mail.thesysadminchannel.com"
#$CC = "[email protected]", "[email protected]"
Send-MailMessage -To $($ADObject.EmailAddress) -From $From -Subject $Subject -BodyAsHtml $Body -SmtpServer $SmtpServer #-Priority High -Cc $CC
}
[PSCustomObject]@{
SamAccountName = $ADObject.samaccountname.toLower()
PasswordLastSet = $ADObject.PasswordLastSet
DaysUntilExpired = $DaysUntilExpired
EmailAddress = $ADObject.EmailAddress
}
} catch {
Write-Error $_.Exception.Message
}
}
}
}
END {}
}
Once you call the function here’s an example of what the output would look like.
You can customize the email to send as high priority or add CC if you like when you specify the -SendEmail parameter
Here’s an example if you wanted to specify users. If the password is set to not expire it will display NeverExpire. It will also error out if a user is not found in Active Directory.
So now that we’ve got a working Powershell script to query Active Directory for expired passwords, we can also use this as a Powershell password expiration report which is really nice.
All in all I wanted to say thanks a lot for taking the time to visit and hopefully you can make use of the get password expiration date Powershell script in your environment. If you like these kinds of posts, feel free to check out our gallery full of useful real-world scripts. Don’t forget to check out our Youtube Page for sysadmin video content.


Thanks for the script! Only had to change -BodyAsHtml to -Body otherwise the line feeds (`n) where ignored.