Active Directory Password Expiry Notification

Since upgrading my workplace to Windows 7 my department got a lot of complaints from users that they no longer knew when their passwords would expire. As you’re probably aware, the little balloon box in Windows 7 isn’t all that noticeable compared to the dialogue box Windows XP threw requiring you to actually acknowledge the notice.

Two years ago I hacked a little PowerShell script that sent off a text based email to each user when their password was close to expire. It worked well, as ugly as it was, but I wanted to build in reporting. I ended up re-writing it, and today I’m releasing it into the wild.

Let me introduce to you the Active Directory Password Expiry Notification script, or ADPEN.

Written in PowerShell, ADPEN quickly combs through Active Directory in search of enabled users and sends them a pretty HTML notification email when their password has, or is about to expire.

ADPEN is also capable of sending a report allowing administrators to know who can’t log in and who will have their password expire that day. This is useful in quickly troubleshooting why users have log in problems.

You can run the Active Directory password expiry notification script from within PowerShell, but the best way is to use the Task Scheduler on any domain controller and run daily from there. I highly recommend you sign the ADPEN script to work in your environment.

ADPEN works well but is a little rough around the edges. There is some code duplication and other things that could be cleaned up, but for a quick script its alright.

I’ve modified MailChimp’s Email-Blueprints base_boxed_basic_query.html and utilized Brice Lambson’s simple template engine for PowerShell for parsing through that template.

There are several variables that need to be set in order for the script to run, but I’ve documented it as well as I could and it should be easy to understand.

The simplest way to get things up and running is to go to my github repository richardfleming/adpen where you can clone as well as find full instructions on how to configure and use ADPEN.

I hope you find this script useful! I’ve licensed this under the MIT license meaning you can do whatever you want with the script. My only wish is that any changes you make, to please merge them back so everyone can benefit.

See also



Richard, I love this script. This is almost 100% what I am looking for. My company wants to only send out emails when people’s passwords are at 7, 3, and 1 day. How would I introduce something like this into this script. We want to run the script as a scheduled task on a daily basis, but my users will freak if we send them emails every day.


Richard Fleming

I’m glad it helps!

Looking at the code, you’d have to make a few changes. I’d suggest changing line 24 to read $pwdNotificationStartInDays = 7, then adding a new array right below, say $pwdExpiryNotificationDays = Array(1, 3, 7).

Then you go down to the IF block on line 262 and change it to something like this:

# Prepare-SMTPMessage if password expires less than or on a certain day if ( $objPwdTimeLeft.Days -le $ghtSettings.Pwd.NotificationStartInDays ) { # Only send notices on specific days if ( $pwdExpiryNotificationDays -contains $objPwdTimeLeft.Days ) { Send-PwdExpiryEmailToUsers $strSendTo $objUser.DisplayName $objPwdTimeLeft $now } Populate-Report -strDisplayName $objUser.DisplayName -objPwdTimeLeft $objPwdTimeLeft -now $now }

You’ll have to try that out before you put into production… but that should do the trick.




How can I change the email to read Attention Firstname Lastname,? Instead of the display name… ?

Richard Fleming

First thing, in the function Get-PasswordExpiredUsers, change $objUsers to equal the following: $objUsers = Get-ADUser -Filter $strFilter -Properties SamAccountName, DisplayName, mail, PasswordLastSet, givenName, sn

Then inside the ForEach loop (near the top), you need to make a new variable equal to $objUser.giveName and $ $userFName = $objUser.givenName + “ ” + $

Finally you need to then change the call near the bottom of the ForEach loop to Populate-Report, and change $objUser.DisplayName to your new variable: Populate-Report -strDisplayName $userFName -objPwdTimeLeft $objPwdTimeLeft -now $now

That should do the trick.