Check AD Users Password Expiration Time with PowerShell

PowerShell logo

Intro

It could be complicated to change password on RDS server once it has been expired. So I worked on a PowerShell script which check password expiration time and send email to users to prevent them 30 days before their passwords expire.

I will detail here every aspect of the PowerShell script.

Get AD Users from a group

First thing to do is to get the AD users list. Here we want to get users who are inside the RDS group.

Windows | RDS group users
  • Open Windows PowerShell as administrator :
PowerShell | Open PowerShell Console as administrator
  • Enter this command to get all the users from RDS group :
PS C:\ > (Get-ADGroupMember -Identity 'RDS').SamAccountName
  • Output :
PowerShell | Get-ADGroupMember output
  • Add «where objectClass -eq 'user' » to get users accounts only (no groups) :
PS C:\ > (Get-ADGroupMember -Identity 'RDS' | where objectClass -eq 'user').SamAccountName

Get AD User Expiration Time

  • To get the expiration time we need to add the msDS-UserPasswordExpiryTimeComputed property :
PS C:\ > $user = "e.cartman"
PS C:\ > Get-ADUser "$user" -Properties msDS-UserPasswordExpiryTimeComputed
  • Output :
PowerShell | Get-ADGroupMember output
  • As we can see we cannot use the raw information retrieved. We need to use [DateTime]::FromFileTime to convert to human readable format :
PS C:\ > $ADUser=(Get-ADUser "$user" -Properties msDS-UserPasswordExpiryTimeComputed)
PS C:\ > [DateTime]::FromFileTime($ADUser.'msDS-UserPasswordExpiryTimeComputed')
  • Output :
PowerShell |

Check if Password Never Expires is set

If user has the password never expires parameter set, we won't be able to get expiration time.

So when we have a user in this situation we need to unset the password never expires parameter, get the password modification time then turn it on again.

  • Check if PasswordNeverExpires is set :
PS C:\ > if ( $($ADUser.PasswordNeverExpires) ) {
  • Unset PasswordNeverExpires :
PS C:\ > Set-ADUser $user -PasswordNeverExpires $false

Check if Account is Enabled

  • We only care about Enabled Accounts :
PS C:\ > if ((Get-ADUser "$user").Enabled)

Set Email parameter

I use the E-mail Active Directory field to send message to our users.

If this field is empty we will create the email address with the First Name and Last Name parameters.

Active Directory | set email address in user properties
  • Set EmailAddress :
PS C:\ > $user = "e.cartman"
PS C:\ > Set-ADUser $user -EmailAddress $((Get-ADUser $user).GivenName.substring(0,1).ToLower() + (Get-ADUser $user).Surname.tolower() + "@shebangthedolphins.net")
PowerShell | Format Email address

PowerShell Script

###########################
# author : shebangthedolphins.net
# version : 1.0
# date : 2021.02
# role : Check AD password expiration
# other : Tested on Windows 2019 Server
# updates :
#       - 1.0 (2021/02) : First Version
#       - 1.1 (2021/02) : Add enabled accounts and users only

Function Mail {
    param ([string]$emailbody, [string]$sujet, [string]$mail)

    $encoding = [System.Text.Encoding]::UTF8
    Send-MailMessage -Encoding $encoding -To $mail -Subject $sujet -From $mail -smtpserver mx.shebangthedolphins.net -Body $emailbody 
    }

#get RDS users group
foreach ($user in $(Get-ADGroupMember -Identity 'RDS' | where objectClass -eq 'user').SamAccountName) {
    if ((Get-ADUser "$user").Enabled) { #check if account is enabled
	    #get AD users with PasswordNeverExpires, msDS-UserPasswordExpiryTimeComputed and mail parameters
	    $ADUser=Get-ADUser "$user" -Properties PasswordNeverExpires, msDS-UserPasswordExpiryTimeComputed, mail

	    #flag to know if password never expires parameter has been modified
	    $Pne_Flag=$false
	    #if current user has "PasswordNeverExpires" enabled
	    if ( $($ADUser.PasswordNeverExpires) ) {
		Set-ADUser $user -PasswordNeverExpires $false #disable PasswordNeverExpires
		$Pne_Flag=$true #set flag to true
		}
	     #if current user doesn't have mail parameter set
	     if ( !($ADUser.mail) ) {
		 Write-Host $user "doesn't have email set"
		 #set email field
		 Set-ADUser $user -EmailAddress $((Get-ADUser $user).GivenName.substring(0,1).ToLower() + (Get-ADUser $user).Surname.tolower() + "@shebangthedolphins.net")
	     }

	    $ADUser=Get-ADUser "$user" -Properties PasswordNeverExpires, msDS-UserPasswordExpiryTimeComputed, mail
	    $ExpDate=[DateTime]::FromFileTime($ADUser.'msDS-UserPasswordExpiryTimeComputed') #get last modification date
	    $DiffDays=$(New-TimeSpan -Start $(Get-Date) -End $($ExpDate)).Days #substract last modification date to current date
	    if ( $DiffDays -lt 30 ) { #if less than 30 days
		Write-Host "User $user with e-mail :" $ADUser.mail "will have his password expired in" $DiffDays "days, the" $(get-date($ExpDate) -Format "yyyy.MM.dd")
		Mail ("Hello,`n`nYour password is going to expire in less than 30 days.`nAfter this date you will not be able to connect with your password.`nPlease consider to change it.`n`nThank you") "[ShebangTheDolphins] : Your remote desktop password is going to expire soon" $ADUser.mail
		if ($Pne_Flag) { #if the "PasswordNeverExpires" parameter has been modified
		    Set-ADUser $user -PasswordNeverExpires $true #we enable PasswordNeverExpires
		}
	    } else {
		Write-Host "User $user with e-mail :" $ADUser.mail "doesn't have to change his password, it expires in" $DiffDays "days, the" $(get-date($ExpDate) -Format "yyyy.MM.dd")
	    }
    }
}
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :