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.
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.