Why should we email users a password expiration notification? After all, Windows will let a user know if their password is about to expire. Two reasons:
- Our users don’t really pay attention to those little popup messages in the notification area.*
- Our users organize and spend their day in email. It is often the first and last things they do every day.
By reminding your users to change their passwords through email, you can eliminate potential problems due to an expired password! But being proactive doesn’t mean more work. With PowerShell and Active Directory, we can effortlessly alert our users before their passwords expire. This will save them frustration and save you time!
Controlling the Password Expiration Notification
By default, users will receive a password notification 14 days before their passwords expire. For some reason, users treat passwords like a non-renewable resource – they refuse to change them until a day before they actually expire. To ease your user’s frustrations, change the password notification warning to something a little shorter.
This setting can be configured in Group Policy and is found under Computer Configuration/Policies/Windows Settings/Security Settings/Local Policies/Security Options. It is named Interactive logon: Prompt user to change password before expiration. In our environment, we prompt users at the 4 day mark.
Password Expiration Email Script
To use this script, you will need the Quest AD Cmdlets installed. You will also need to know the maximum password age in your environment. The default is 42.
Add-PSSnapin Quest.ActiveRoles.ADManagement $ExpiringPasswords = Get-QADUser -SearchRoot "OU=Faculty,DC=Test,DC=local" -PasswordNotChangedFor 85 | Where PasswordNeverExpires -eq $False | Select-Object email -Unique $emailFrom = $subject = "Password will Expire Soon" $smtpServer = Foreach ($ExpiringPassword in $ExpiringPasswords) { $emailto = $ExpiringPassword.Email $body = " You are receiving this email because your password expires within 5 days. While on site, press CTRL + ALT + DELETE to change your password. Your password must be 12 characters long and can contain special characters/spaces. It cannot be a previous password. If you have any problems changing your password, please see your technician. You will never be asked for your password by the I.T. Department. If you receive an email requesting your password, please contact your technician." Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -BodyAsHtml -SmtpServer $smtpServer }
To use this script, you will need to edit a few things. First, you will need to change the -searchroot (line 3) to search for your users. Next, you will need to edit -PasswordNotChangedFor 85 so that “85” is five days before your maximum password age. If your password age is 180 days, your script should read -PasswordNotChangedFor 175
Next, you will need to edit $emailFrom and $smtpServer to match your environment. Finally, you might want to edit the $body. The email body used is just a generic template that we use. If you haven’t, setup an automated way for users to reset their own password!
And That’s a Wrap!
The only thing left for you to do is to set this script up as a scheduled task and set it to run daily or every other day. We set ours to run every other day because we some of our users also receive file server quota alerts every day. But that is what they get for taking up my server space!
Once setup, your users will start receiving email notifications and you will (hopefully) have less problems to deal with!
*Back in the days of XP, users were second class objects. Things like password expiration warnings were front and center. These messages required manual interaction from the user. With Windows 7, Microsoft moved these messages to the notification area. Users are already used to ignoring this area. Banished like Clippy, these notifications now tremble to interrupt the user!
Hi: I want to know if the password expired, the script stopped the notificacitions? thanks
I don’t quite understand your question – could you explain it a bit more?
it can’t resolve the directory object, but in my configuration I have targeted an OU within a OU: I have to give the entire OU tree? Like ”OU=Users\Test Users,DC=Tester01,DC=com”.
I have also some white space in the OU name (Users Test, infact)…I have to escape the character?
Thank you
Change your OU path to:
OU=Users,OU=Test Users,DC=Tester01,DC=com”.
I’m wondering what would be required to filter any accounts which have expired. We normally set expiration dates on contractor accounts and it would be really nice if they automatically dropped off the list once they expire.
You would filter off of the AccountIsExpired property. Example:
Get-QADUser -SearchRoot “DC=Test,DC=local” -PasswordNotChangedFor 85 -AccountIsExpired $False
The above line would pull all users whose password has not changed for 85 days and who do not have expired accounts.
Thank you for sharing this informative blog post.
To get the accurate notification for password expiration in my working environment, I use Lepide password expiration reminder tool that do this job preciously. It reminds the users when their password is about to expire through customizable email notifications according to defined time-frame.
I did search and found only your script easy to use for password expiration and notification PS
We didn’t have password GPO in place, we use default 42 days expiration date.
I only got error at $emailto = $ExpiringPassword.Email (do I need to change anything here)
Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:17 char:22
+ Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -Bo …
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
Hi, there:
Your script is working for me but I am not sure about one thing:
Do I need to change anything here if I enter all my mail server information correctly:
$emailto = $ExpiringPassword.Email
Hi ,
I am getting an error in Line#3 when I use
$ExpiringPasswords = “Get-svc.bpi.dev.log_mgmt””OU=ServiceAccount,DC=US,DC=global,DC=schwab,DC=com”-PasswordNotChangedFor 90 | Where PasswordNeverExpires -eq $False | Select-Object email -Unique
_________________________________________________________________________________
I get the below error :
At line:3 char:100
+ … =schwab,DC=com”-PasswordNotChangedFor 90 | Where PasswordNeverExpires -eq $False …
+ ~~~~~~~~~~~~~~~~~~~~~~
Unexpected token ‘-PasswordNotChangedFor’ in expression or statement.
At line:3 char:123
+ … dNotChangedFor 90 | Where PasswordNeverExpires -eq $False | Select-Object email …
+ ~~
Unexpected token ’90’ in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Ok, now when I removed the below from the script from Line#3 it looks like I didn’t see the Unexpected Token error.
-PasswordNotChangedFor 90
However it looks like the script isn’t generating any email for me,
Can you run get-qaduser -passwordnotchangedfor 90 in a powershell console?
Hello,
Thank you for this script.
The script seems running well but I have this issues at the end.
Do you have an idea where could it come from ?
thank you
Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Supply an argume
is not null or empty and then try the command again.
+ Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -Bo …
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
Try this command in your powershell window:
write-host $emailto
Let me know what it says.
It works great. Thank you Joseph!
Great! Enjoy the automation!
Josephy,
Thank you very much! My powershell is in version 2. For windows 2003 does not support ver 3, so have to setup and window 7 to update it. The ver 3 does help. i just need to get over SMTP authentication issue. I do need to report one error of multiple value parameter issue for -Body. Detail as see follow:
—————
PS C:\Windows\System32> C:\Windows\System32\pswemail.ps1
Send-MailMessage : Cannot bind parameter because parameter ‘Body’ is specified more than once. To provide
multiple values to parameters that can accept multiple values, use the array syntax. For example,
“-parameter value1,value2,value3”.
At C:\Windows\System32\pswemail.ps1:17 char:78
+ Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -Bo …
+ ~~~
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : ParameterAlreadyBound,Microsoft.PowerShell.Commands.SendMailMessage
PS C:\Windows\System32> C:\Windows\System32\pswemail.ps1
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The
server response was: 5.7.1 Client was not authenticated
At C:\Windows\System32\pswemail.ps1:17 char:1
+ Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -Sm …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage]
, SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
It looks like you there is an extra space in “-body ashtml”. It should be -BodyAsHtml. Let me know if that fixes the issue.
Thanks for your post. I have follow your script. It does not work in my test environment. My dc is windows 2003 sp2 64 bit. Following is script and error. If you can point out where is wrong i made. Thank you very much!.
script:
———–
Add-PSSnapin Quest.ActiveRoles.ADManagement
$ExpiringPasswords = Get-QADUser -SearchRoot “OU=MTR,DC=Test01,DC=local” -PasswordNotChangedFor 1 | Where PasswordNeverExpires -eq $False | Select-Object email -Unique
$emailFrom = “administrator@test01.local”
$subject = “Password will Expire Soon”
$smtpServer = “192.168.121.153”
Foreach ($ExpiringPassword in $ExpiringPasswords) {
$emailto = $ExpiringPassword.Email
$body = ”
You are receiving this email because your password expires within 5 days. While on site, press CTRL + ALT + DELETE to change your password. Your password must be 12 characters long and can contain special characters/spaces. It cannot be a previous password.
If you have any problems changing your password, please see your technician. You will never be asked for your password by the I.T. Department. If you receive an email requesting your password, please contact your technician.”
Send-MailMessage -to $emailto -from $emailFrom -Subject $subject -Body $body -Body AsHtml -SmtpServer $smtpServer }
————————-
errors:
—————
PS C:\WINDOWS\system32> C:\WINDOWS\system32\pswemail.ps1
Add-PSSnapin : Cannot add Windows PowerShell snap-in Quest.ActiveRoles.ADManagement because it is already added. Verify the name of the
snap-in and try again.
At C:\WINDOWS\system32\pswemail.ps1:1 char:13
+ Add-PSSnapin <<<< Quest.ActiveRoles.ADManagement
+ CategoryInfo : InvalidArgument: (Quest.ActiveRoles.ADManagement:String) [Add-PSSnapin], PSArgumentException
+ FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand
Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "PasswordNeverExpires" value of type "System.String" to type "S
ystem.Management.Automation.ScriptBlock".
At C:\WINDOWS\system32\pswemail.ps1:3 char:106
+ $ExpiringPasswords = Get-QADUser -SearchRoot "OU=MTR,DC=Test01,DC=local" -PasswordNotChangedFor 1 | Where <<<< PasswordNeverExpires
-eq $False | Select-Object email -Unique
+ CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand
Send-MailMessage : Cannot validate argument on parameter 'To'. The argument is null or empty. Supply an argument that is not null or em
pty and then try the command again.
At C:\WINDOWS\system32\pswemail.ps1:17 char:21
+ Send-MailMessage -to <<<< $emailto -from $emailFrom -Subject $subject -Body $body -Body AsHtml -SmtpServer $smtpServer }
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
————
Hey Tony – what version of powershell are you running? In a powershell prompt, type $psversiontable . You should be running PowerShell 3 to use this script.