Script: New-ADPasswordReminder.ps1 – Email Users When Their Password Will Soon Expire
Note: Development on this script has moved to Github. Please see the repo at https://github.com/patrichard/New-AdPasswordReminder.
Description
In today’s increasingly mobile workforce, many users don’t login to Active Directory on a domain joined computer. Some use only Outlook Web Access/App, some use non-domain joined machines external to the company network, some just use mobile devices such as smartphones and tablets. And others may use Macs.
Users who login via domain joined machines on the company network get the reminder several days ahead. The default is 14 days, but can be configured in the Default Domain Group Policy under Interactive logon: Prompt user to change password before expiration.
OWA users see a notification when they login as well. In OWA 2007 running on IIS6, this can be adjusted via PasswordExpirePrenotifyDays. In fact, with OWA 2007 and 2010, you can even change your password after it expires, using the Password Reset Feature in Exchange 2007 and 2010. However, there are times when that’s just not a remedy. The password reset feature requires the Exchange server to be running on Windows 2008 or later, as it relies on IIS 7. Many Exchange 2007 shops are not on that platform yet.
Anyone who’s ever worked on a Help Desk knows that a LOT of users call to say they can’t login, only to determine it’s because their password expired. Many, if not most, are those types of users mentioned above. Others don’t notice, or simply ignore the notice when logging in. So let’s really make sure we notify them of the pending expiration. There are some third-party tools, including some that run on SharePoint, that enable a user to reset their password. But this is after the fact. Sure, we could use some third-party application to send a reminder, but… well… why? PowerShell to the rescue!
In the pre-Windows 2008 domain functional level days, we could just peek at the Default Domain GPO, and grab the Maximum Password Age parameter, since it was a global setting. Then we could go through Active Directory, find users who are not set to “never expire”, use some math, and come up with a list of users whose password expired soon.
But with the changes implemented with Windows Server 2008, we can now have Fine Grained Password policies, which allows us to have more than just one password policy in our organization. So, Executives get one password, IT people with elevated rights get another, etc. Cool in theory, but frustrating in our endeavor to notify users when they’ll expire.
I blatantly admit that I used part of a script by M. Ali, who wrote a blog post Find out when your Password Expires. The script looks checks Get-AdDomain, and looks at the DomainMode parameter in the results. From here, we know whether we can just peek at the Default Domain policy, or if we need to look deeper. Regardless of which way, we look through the users using Get-AdUser, and grab the PasswordExpired, PasswordNeverExpires, and PasswordLastSet fields. Obviously, if the account is expired, no need to keep reminding the user. And if the password never expires, then we also don’t need to notify the user. With PasswordLastSet, our math comes into play to determine when the password will expire. Not terribly short and sweet, but effective.
Once we know when the password will expire, we can then set a window for when we should notify the users. It makes sense to match what’s in the GPO so that notifications are consistent regardless of platform. This script is set to 14 days by default.
Next, we need to craft some information that we want to convey to the user. In this case, we’ll use some HTML formatting so that we can properly convey the importance of the info, as well as include some additional formatting. I’ve mocked up something based on some third-party tools, and on the comments and recommendations of IT Professionals and users. It’s simple enough to change, but be warned that many clients, including Outlook, don’t strictly adhere to HTML standards. So it can take quite a bit of trial and error to find out what does actually appear the way you want it to.
Installation and Setup
First, you need a receive connector that will accept mail from PowerShell. I cover that in Creating a receive connector to use for sending email from PowerShell. Next, the script must run on a machine with PowerShell 2.0 installed. This is a prerequisite for Exchange 2010 (and installed by default on Windows 2008 R2), but not for Exchange 2007. If you’re reluctant to upgrade PowerShell on your 2007 box, it can be run from any other box that has PowerShell 2.0 and the Exchange Management tools installed. Note: Exchange Management tools should always be updated and patched to the same level that your Exchange servers are.
Second, you’ll need the ActiveDirectory module available on the machine that will run the script. The ActiveDirectory module is installed when you add the Remote-Server Administration Tools feature in Windows Server 2008 R2. If the module is not detected, the script will attempt to install it automatically the first time it runs.
Next, grab the latest zip file from the DOWNLOAD section below. It includes the script and ScriptImages.zip contains a couple of images that are used in the warning for users who’s password expires in < 24 hours (seen in the Outlook screenshot above). The images need to be accessible to all users who will receive the reminder emails. This is likely to be a public web site.
Crack open the script in your favorite editor and update the lines in the param() block to match your environment. This includes $Company, $OwaUrl, $PSEmailServer, $EmailFrom, $HelpDeskPhone, $HelpDeskURL and $DaysToWarn. If you want to target a specific OU, set $OU. Also, set $ImagePath to a path holding the included image files (or those you add/edit). This path should be available to all users who may receive the reminder message. This is probably a public server.
param( [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [switch]$Demo, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [switch]$Preview, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [switch]$Install, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [string]$PreviewUser, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [switch]$Transcript, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="Please specify a company name.")] [ValidateNotNullOrEmpty()] [string]$Company = "Contoso Ltd", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="Please specify an OWA URL")] [ValidateNotNullOrEmpty()][ValidatePattern("^https://")] [string]$OwaUrl = "https://mail.contoso.com", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="Please specify the IP address of your email server")] [ValidateNotNullOrEmpty()][ValidatePattern("\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b")] [string]$PSEmailServer = "10.9.0.11", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="Please specify a name and email address for the email 'from' field")] [ValidateNotNullOrEmpty()][ValidatePattern("\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b")] [string]$EmailFrom = "Help Desk ", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [string]$HelpDeskPhone = "(586) 555-1010", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [ValidatePattern("^http")] [string]$HelpDeskURL = "https://intranet.contoso.com/", [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [string] $TranscriptFilename = $MyInvocation.MyCommand.Name + " " + (hostname)+ " {0:yyyy-MM-dd hh-mmtt}.log" -f (Get-Date), [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false, HelpMessage="This must be zero")] [ValidateNotNullOrEmpty()] [int]$global:UsersNotified = 0, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="Please specify how many days before expiration that users should begin to be notified.")] [ValidateNotNullOrEmpty()] [int]$DaysToWarn = 14, [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false)] [string] $ImagePath = "http://www.contoso.com/images/new-passwordreminder.ps1", [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false)] [ValidateNotNullOrEmpty()] [string] $ScriptName = $MyInvocation.MyCommand.Name, [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false)] [ValidateNotNullOrEmpty()] [string] $ScriptPathAndName = $MyInvocation.MyCommand.Definition, [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false, HelpMessage="Please specify an Organizational Unit")] [ValidateNotNullOrEmpty()] [string] $ou )
Open an Exchange Management Shell session and run the script in demo mode to see a list of users that are expiring soon.The script won’t email the users in demo mode. It merely shows you who it WOULD, and how long till their password expires.
.\New-PasswordReminder.ps1 -demo
As we see in the example screenshot, Claudia’s password expires in 5 days, and the password policy that applies to her requires the password to be changed every 42 days. If we run the script normally, Claudia will receive the email reminder since it’s within the 14 day window defined in the script.
To run the script normally (non-demo mode), manually, just omit the -demo. There is no output to the screen when run normally, as the script is designed to be run as a scheduled task.
Once you’re satisfied that the script is running correctly, we can set it to run as a scheduled task. I have a blog post Running PowerShell scripts via Scheduled Tasks that details everything. In my production environment, it runs at 6am each day.
One of the hardest parts was getting a decently formatted email that looked good. This could take some trial and error, and the original script didn’t really have a way built in to preview what the end user would see. As a result, some hapless users would be flooded with your “test” messages. I fixed that by creating a preview mode. Manually run the script with the preview switch, and a user to send the email to. For example
.\New-PasswordReminder.ps1 -Preview -PreviewUser bgates
This will send an email to the user, bgates. The email is formatted for a password that expires in one day, so the user gets the additional banner near the top as well.
Next up was creating a scheduled task. Not really terribly difficult to do manually, but I could see where it might take some trial and error. So, I added the install switch, which will create a scheduled task for the script, configuring it to run at 6am each day. Of course, that time can be manually adjusted by opening the scheduled task once it’s created. The install mode will ask for credentials to run the scheduled task under. Install it as so:
.\New-PasswordReminder.ps1 -Install
Note: The scheduled task is configured to point to where the script is when you run the install switch. So don’t move it later!
To send an email that does not contain the images or their related formatting, specify $NoImages when running the script. This will send essentially an HTML formatted text email.
Next up, I added some simple logging to the application event log. The script will write a single entry when it starts, and a single entry when it finishes, noting how many users were processed (sent an email). I would love to hear how this script works in large environments. If you’re willing, please let me know (via comments below) how long it’s taking to run in your environment, and the number of users in AD.
Please send me your suggestions!
Donations
I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.
Syntax
New-PasswordReminder.ps1 [-Demo] [-Install] [[-PreviewUser] ] [-NoImages] [-WhatIf] [-Confirm] []
Demo Runs the script in demo mode. Demo mode displays users who are expiring soon, but does not send them the reminder email.
Install Creates a scheduled task to run the script automatically every day at 6:00am
PreviewUser
Defines the user to send the preview email to.
NoImages
Specifies that a HTML text only message should be sent instead of one that contains the fancy formatting.
Installation
Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.
In addition to the info listed above:
If you leave the following parameters blank, the related text will be removed from the email sent to users: $HelpDeskURL. This will get expanded in the future.
You can change the format of the date displayed in the email by changing the value of $DateFormat. The default is “d”, which yields a date such as 09/07/2012 (MM/dd/yyyy). If you’d like the European style, use “MM/dd/yyyy” instead.
Frequently Asked Questions
Question: Does this work with Exchange Server 2013
Answer: Yes
Download
v2.9 – 09-13-2013 New-ADPasswordReminder.v2.9.zip
v2.8 – 05-03-2013 New-ADPasswordReminder.v2.8.zip
v2.7 New-PasswordReminder.v2.7.zip
v2.6 New-PasswordReminder.v2.6.zip
v2.4 New-PasswordReminder.v2.4.zip
ScriptImages.zip – image files used in emails
Changelog
See the changelog for this script which details all versions and their features.
Hi, i want to use this script for only one OU, and OU’s which are located under it. How can i do that?
That is not in the current version, but it is something I’m working on for the next version.
Hi Pat,
ok, thanks for the information! Hm, but there is no option, where i can change the script easily?
maybe there would be an easy way to change the get-aduser properties?
Only a question…your script is still perfect! 🙂
Did you get the option working to have this work in a specific OU? We’re dealing with the same issue here.
That’s in v2.8, the last version released. Define the OU in the script. It’s around line 112.
Julian – I have it working for a specific OU. Let me finish a couple more things I need for this version. I should be able to push it out tomorrow.
Hi Pat,
sure take your time and Thank You very much for your help!!!
I have some more idea: It would be very fine, if you can choose how often a mail will send out to the user. For example: the first information will come 21 days before the password will expired, the second mail will come 12 days before the password will expire. And the last 7 days the mail will be send out daily.
Or could you help me, how i can do that?
The script works great! But the comment above would be a great feature to add to the wish list.
I can add that to the wish list. I always welcome ideas!
The new version was rolled out this morning. Check it out at https://www.ucunleashed.com/569
Hi Pat,
thx a lot for the latest version! Your script is really cool, will try it on monday! Of course, please add it on the wish list, would be really cool to have this feature, too! 🙂
Thx and have a nice weekend,
Julian.
Hi Pat,
Thanks for your script. It has helped me to setup notification for my customer.
When I executed the option -install, the scheduele job is created, but if I launch the job it doesn´t get executed.
I think, that the schedule job don´t include the active directory powershell snappin.
How can I include in the scheduele job all the powershell snappins of my server.
The script calls the module for AD. It doesn’t use snapins. If that feature (RSAT-AD-PowerShell) isn’t installed, it should install it (assuming it’s running with an account that has rights to do that).
If you run it manually, does it work?
It works if I run it manually, but don´t work with the scheduele job.
My server where I execute te script is a Domain Controller with Windows 2008 R2 Standard.
My domain funcional level is Windows 2003, but I´m going to upgrade the domain funcional level to Windows 2008 R2, the next week.
Regards
Yes, works only like Carlos said. I have tried a lot of things with that, but i run out of ideas.
The code after scheduled task: (0x1)
Manually it works..
Okay, and you’re running it on a Windows server? 2008 R2? And you’re using the script from the updated page at http://www.ehloworld.com/569?
Dont use the install option from the script manually create the task with powershell to run the script. and use -ExecutionPolicy Bypass -File to run the script file
There really is no need to use that method. The install option works fine in every environment I’ve installed it in.
Yes,
2008 R2 with Exchange 2010, newest script v2.2. I’ve used your tutorial “Running PowerShell scripts via Scheduled Tasks” (even with command -install).
Thanks,
I tried the 2.4 version also. But still only users with no Policy assigned to (i.e. domain admins) shows up data for days to expire. No other users with password policies can be found. Tried to set DaysToWarn to 80 or 90 (policy says 90 days).
Problem solved. You can’t run the script on a domain controller. Use another server and it works like a charm.
Only issue found is that the install makes a bad command line argument. Have to be modified manually to work.
UIF – Do you remember what needed to be modified manually?
Nevermind I saw below someone already figured it out. Quotes….awesome script and thank you very much.
Best of its kind script. But kinda confused which server i should run it on. I am running an exchange server 2007 sp2 on windows server 2008. Domain controllers are windows server 2008 r2. Domain functional level is 2003. Can i just run it on a DC where exchange management tools is not installed ?
I am trying to use this with users who have a PSO vs GPO applied. When I run the demo it gets 0 results, which is incorrect. Could I have help troubleshooting?
Never mind,
I changed ge =3 and I’m good to go. Great post!
Hi Pat
I tried your script and it works perfectly. thanks for the great effort
I need you help to achieve the following:
I need the script to send the email to the users 1 month before his password expires and again send the email to the users 15 days before his password expires, then send it if the password will expire in 9 days.
The script in its basic form will keep sending the email every day if the days before expire threshold is reached.
In short if the thresh hold is set for 30 day if the script runs daily the users will get the expire mail 15 days before their password expires and 9 days before their password expires.
Interesting request. Let me see what I can do.
Great Script! Been hunting for a while and this is the best one by far.
I too have the scheduled task issue and wonder if it’s UAC related? Will try commenting out the eventvwr write commands.
Also, you can set the $PSEmailServer var but I do see where it’s applied. I added the -smtpServer $PSEmailServer to the send-mailmessage command, and can now direct emails through any smtp server I define.
Using the “-Install” option, minor issue.
My scheduled task inserted by the tool was not working. Eventually I determined the issue is related to the command line arguments not being enclosed in double quotes which is need when the path contains spaces. I manually added the double quotes below to the scheduled task.
-psconsolefile “C:\Program Files\Microsoft\Exchange Server\V14\\Bin\exshell.psc1” -command “C:\My Scripts\New-PasswordReminder.ps1”
Hello Pat
please help us we are struggling…
I need your help to achieve the following:
I need the script to send the email to the users 1 month before his password expires and again send the email to the users 15 days before his password expires, then send it on daily basis if the password will expire in 9 days.
Hello
I managed to let the script to send the email to the users 1 month before his password expires and again send the email to the users 15 days before his password expires, then send it on daily basis if the password will expire in 9 days.
i hope it will work well in the production environment…
Fahad, could you share how you were able to modify the script to this? Trying to do something similar, just different time periods.
Hi, great looking script. I have amended the script and run from exchange 2010 server using EMS. When I execute command:
.\New-PasswordReminder.ps1 -Preview -PreviewUser My_User
The command runs OK but no test email is received?
Any thoughts on what I might be doing wrong!
Thanks,
Phil.
Most common cause of this issue is junkmail or quarantine.
Thanks for the reponse Pat. Nothing in my outlook client, i shall investigate further.
Can you amend my name in my original post to Phil please?
Thanks,
Phil
I have looked at the logs after running and see Evnet Id 70 information message
Finished processing 0 account(s).
For more information about this script, run Get-Help .\New-PasswordReminder.ps1. See the blog post at http://www.ehloworld.com/318.
I ran command:
.\New-PasswordReminder.ps1 -Preview -PreviewUser myFirstname_MyLastname
Thanks,
Phil.
Pat further testing has shown the script does work, I appear to have misinterpreted the ‘Preview’ function. I ran against my AD account where the password is not due to expire. I ran against an alternate account where the password was due to expire and they received the email. Not ideal as I wanted to preview the email prior to going live with the scripts.
Great work.
Phil.
Pat I now have the script working but I note an error. The demo correctly displayed password expiry for user accounts. Using one as an example password expiry was 9 days (confirmed by DumpSec). I sent a preview email to this account. The email password reminder advised the user that their password expired in 1 day 10/03/2012 (this should have been 9 days 18/03/2012).
Any thoughts?
Thanks,
Phil.
That is by design, so that you can see all of the formatting. The message is a little different when it’s only one day, and I wanted the admin to be able to see that.
Hi Pat. So the script only states 1 day in ‘Preview’ mode? Does the message differ much when > 1 day?
Once again great work and I commend you for responding to user comments.
Many Thanks,
Phil.
No, the message doesn’t really change, but the red image above the text goes away when it’s >1 day.
Hello Pat
just suggestion to improve this script. if you can add a log file where all users got the email are logged there. this will help us to know the users their password will expire.
Hi Pat
Thanks for this, one of the best PS script aroung… thumbs up !!!
Simular sugestion as Fahad has… either a log or a CC post to Admin
Jon
Pat,
First let me just say thank you, this is exactly what I’ve been looking to do to deal with users who REFUSE to log off their PCs more than twice a year.
I’ve been able to get everything working just great except the scheduled task doesn’t seem to work properly giving me a results code of 0xFFFC0000. Running the script manually from the command line is flawless tho. Any idea what the issue might be?
Thanks in advance
Chris
If you take the entire line from the scheduled task, and pop it into a cmd prompt (not PowerShell), and it runs, then the likely issue is credentials/authentication.
Thanks! Looks like i was having the same problem as lvjoe (should have read the comments better)
Just needed the double quotes around
“C:\Program Files\Microsoft\Exchange Server\V14\\Bin\exshell.psc1”
and things are working beautifully.
hi Pat,
thanks for this great script its been working for about 2 month but lately,
when i try to running from powershell it always result with error like this:
“Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty.
Supply an argument that i s not null or empty and then try the command again.
At C:\Exchange Password Reminder Script\script-images\NEW-PasswordReminder.ps1:345 char:28
+ Send-MailMessage -To <<<< $accountObj.mail -Subject "Your password expires in $DaysTillE
xpire day(s)" -Body $emailbody -From $EmailFrom -Priority High -BodyAsHtml
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage"
would you please tell me what is wrong with the error?
Tyo
Same error, not sure what the issue is. Script works in -Demo and -Preview -Previewuser but not simply running the script normally with no switches. Any ideas?
Waiting for Chuck to finish testing a new version that clears up the issue he reported.
Can this be used on Windows 2008 instead of Windows 2008 R2
I have not tested it on 2008.
First pPat great script everthing work except the image of header do not show up it states they have moved?
Any ideas how to fix it?
I have tried c:\image\, \\servername\c$\image, \\serverip\c$\image, and \\127.0.0.1\c$\image
please help
The images need to be in a location accessible by EVERY user who may receive the email. That includes users outside your environment who may be reading the email via OWA. I always use a subfolder of the organization’s website, but have gotten it to work with folders on a CAS server – but that brings up extra complexity if you have more than one CAS server.
This script is working great except the password policy listed at the bottom of the email has the settings for my default domain policy and not the settings from the fine grained password policy. Anyone else run into this?
That’s a known issue with the script that I need to resolve when I have some time.
Hi Pat,
I just want to thank you for the script and your efforts.
I was able to setup V2.4 successfully with the steps described above and the note from Chris (missing /malformed path in the Scheduled Task “C:\Program Files\Microsoft\Exchange Server\V14\\Bin\exshell.psc1″ after using the -install option).
Markus
Thanks. I’m working on a new install option that will not only resolve this, but also take into account being installed on servers that don’t have Exchange on them.
How can i mention OU name in script, i have modified the OU in below script at the line highlighted in star.but i am getting whole user’s list and not in perticular OU’s users.
# Get-ADUser -filter * -properties PasswordLastSet,EmailAddress,GivenName –
**********************************************************
SearchBase “OU=Users,DC=mydomain,DC=com” |foreach {
*********************************************************
if (!($preview)){
if ($ou){
$users = Get-AdUser -filter * -SearchScope subtree -SearchBase $ou -ResultSetSize $null
}else{
$users = Get-AdUser -filter * -ResultSetSize $null
}
Could please let me know where i need to change if i want this script to run on specific OU?
Hi Pat,
This script is just what i’m looking for. Thank you.
One question though. How do i change the format of the date? from mm/dd/yyyy to dd/mm/yyyy
Charles
Charles – look for this line:
$DateofExpiration = (Get-Date($DateofExpiration) -f d)
and change it to
$DateofExpiration = (Get-Date($DateofExpiration) -f dd/MM/yyyy)
I’ve added this as a parameter in v2.7
Hello! I need to use scandinavian letters with this script, but they don’t work.
Letters ÄÖ and äö are all just plain ?? in email.
Any idea why?
I’ve been running this script as a test with my existing Domain admin account which has full permission across the enteprise. As I want to set this up to run under a service account what permissions are needed on Exchange/Domain/Local Computer for it to run?
Pat,
I am new to PowerShell scripting but I am trying to learn on my own. I want to thank you for your work on this script, if I can get it to work this will be a huge benefit to my help desk.
I am trying to run the script in Preview and Demo mode but each time I do it returns an error,
Missing ‘)’ in function parameter list.
At C:\scripts\New-PasswordReminder.ps1:174 char:108
+ [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage=” <<<
< No module name specified!")]
+ CategoryInfo : ParserError: (CloseParenToken:TokenId) [], ParseException
+ FullyQualifiedErrorId : MissingEndParenthesisInFunctionParameterList
I dont know what module name the script would be looking for?
Can you or anyone help?
Thanks,
Chuck
Just to clarify, you’re not trying to do Preview and Demo at the same time, right?
This is the command I am running in Powershell
.\New-PasswordReminder.ps1 -Preview -PreviewUser chood
Hi PAT, We have tested this script in our environment and it works great, but before we implement this, our team suggest that we should re-edit the PASSWORD POLICY part. Can this be done as i understand the linec 437-442 call this table directly from AD. Or at least isthere is a way to remove it completely? and maybe insert a customized table.?
You could edit as needed, but I can’t provide support for that.
I am running this directly on my exchange server 2010 using the Exchange Management Shell
Pat,
The issue came down to the AD Management Gateway Service on the PDC. After that was resolved the script ran fine.
I did have one other issue with selecting a specific OU, do I need to have the entire path in quotes or do I just use the name of the OU?
Thanks for your help.
Chuck
Glad to hear you got it working.
The entire OU path needs to be in quotes.
Thanks again,
I will give that a try. You seem to be very well versed on the power shell language, is there any particular book you would recommend for a newbie?
Chuck
hi pat, thx for your outstanding script. for me it works perfect in demomode or when i run it from powershell. but doesn’t work as scheduled task, and when i run from the cli, it runs but on the end it reports the following error:
**************
Get-Content : Cannot find path ‘C:\New-PasswordReminder.ps1’ because it does no
t exist.
At C:\scripts\chkexpiredpw\New-PasswordReminder.ps1:347 char:23
+ $result = Get-Content <<<< $path |
+ CategoryInfo : ObjectNotFound: (C:\New-PasswordReminder.ps1:Str
ing) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCo
ntentCommand
*************
script is running on a 2008 R2 DC with exchange2007 management tools installed.
i would appreciate any help!
regards martin
Look at the bottom of the script for a line that reads
Remove-ScriptVariables -path $MyInvocation.MyCommand.Name
put a # in front of it.
# Remove-ScriptVariables -path $MyInvocation.MyCommand.Name
Run it again and let me know the results.
ok, great. the line on the bottom reads like: “Remove-ScriptVariables($MyInvocation.MyCommand.Name)” i put a # in front, now it works. another tip: do nut create the task as a privilidged user other the one the task is running under. means, if you want to run the task as administrator”, create it also as administrator, othewrwise it wont work.
thx to pat again, great job done!
martin
Glad to see it’s working for you. I’ll have to look and see why Remove-ScriptVariables is throwing an error.
I get the following when I run the script in demo mode. Active Directory is AD 2003 Native. Does it need to be AD DS 2008?
[PS] C:\>.\New-PasswordReminder.ps1 -demo
WARNING: Error initializing default drive: ‘Unable to find a default server with Active Directory Web Services
running.’.
Get-ADDomain : Unable to find a default server with Active Directory Web Services running.
At C:\New-PasswordReminder.ps1:403 char:28
+ $global:dfl = (Get-AdDomain <<<< ).DomainMode
+ CategoryInfo : ResourceUnavailable: (SMA_NBCA:ADDomain) [Get-ADDomain], ADServerDownException
+ FullyQualifiedErrorId : Unable to find a default server with Active Directory Web Services running.,Microsoft.Ac
tiveDirectory.Management.Commands.GetADDomain
Get-ADUser : Unable to find a default server with Active Directory Web Services running.
At C:\New-PasswordReminder.ps1:409 char:22
+ $users = Get-AdUser <<<< -filter * -ResultSetSize $null
+ CategoryInfo : ResourceUnavailable: (:) [Get-ADUser], ADServerDownException
+ FullyQualifiedErrorId : Unable to find a default server with Active Directory Web Services running.,Microsoft.Ac
tiveDirectory.Management.Commands.GetADUser
User Expires Policy
======================== ======= ===========
Get-ADDefaultDomainPasswordPolicy : Unable to find a default server with Active Directory Web Services running.
At C:\New-PasswordReminder.ps1:427 char:65
+ $DefaultDomainPasswordPolicy = Get-ADDefaultDomainPasswordPolicy <<<<
+ CategoryInfo : ResourceUnavailable: (Microsoft.Activ…nPasswordPolicy:ADDefaultDomainPasswordPolicy) [
Get-ADDefaultDomainPasswordPolicy], ADServerDownException
+ FullyQualifiedErrorId : Unable to find a default server with Active Directory Web Services running.,Microsoft.Ac
tiveDirectory.Management.Commands.GetADDefaultDomainPasswordPolicy
Cannot convert value "" to type "System.Boolean", parameters of this type only accept booleans or numbers, use $true, $
false, 1 or 0 instead.
At C:\New-PasswordReminder.ps1:430 char:26
+ [bool]$PasswordComplexity <<<< = $DefaultDomainPasswordPolicy.ComplexityEnabled
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
Get-ADUserPasswordExpirationDate : Cannot bind argument to parameter 'accountIdentity' because it is null.
At C:\New-PasswordReminder.ps1:434 char:34
+ Get-ADUserPasswordExpirationDate <<<
Are you running it on a 2008 R2 domain controller?
No, I am running active directory on a Windows 2003 Server. Do I need to be on AD DS 2008 SP2 or AD DS 2008 R2?
Doubt that’s going to work, since your domain controllers aren’t going to have PowerShell on them.
Ok, Looks like I move the AD DS uopgrade ahead if this project now.
will it work on win 2003 ? just curious.
Not likely. PowerShell doesn’t come in 2003, and I haven’t even looked at trying to come up with a solution for it.
HI,
I can run the script fin in demo and previewuser but not working in normal or task?
PS C:\scripts> .\New-PasswordReminder.ps1 -demo
User Expires Policy
======================== ======= ===========
testuser01 2 90
Development 4 90
testuser1 11 90
PS C:\scripts> .\New-PasswordReminder.ps1
Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Supply an argument that i
s not null or empty and then try the command again.
At C:\scripts\New-PasswordReminder.ps1:346 char:28
+ Send-MailMessage -To <<<< $accountObj.mail -Subject "Your password expires in $DaysTillE
xpire day(s)" -Body $emailbody -From $EmailFrom -Priority High -BodyAsHtml
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
Send-MailMessage : Cannot validate argument on parameter 'To'. The argument is null or empty. Supply an argument that i
s not null or empty and then try the command again.
At C:\scripts\New-PasswordReminder.ps1:346 char:28
+ Send-MailMessage -To <<<< $accountObj.mail -Subject "Your password expires in $DaysTillE
xpire day(s)" -Body $emailbody -From $EmailFrom -Priority High -BodyAsHtml
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
It’s because one or more of the accounts involved in the query has the field MAIL empty in A.D. , fill them up (create to ALL of them (the list of -demo mode) a mailbox and it works), but now mine works only if I run it, I read somewhere about a double slash mistake and can’t find it anymore… someone can help me?
Please help me below queries.
Only DC ip should be mentioned in Exchange SMPTP relay agent right ?
Email id will be picked from DC account properties ( Email attribute ) ?
I have to run only this script in DC ?
Any additional requirement needs to be done on Exchange Server ?
This is an awesome script, Thanks you!
We did run into one issue while testing. We did the preview command line but a couple of the admin users we tried to test against have their password set not to expire so they didn’t even get the preview email and they don’t show up in the demo list either.
I haven’t looked to change the code but if it’s possible to not skip people like this in preview mode AND flag them in demo mode that would be great. In fact “demo” would really become “audit” at that point!
Ah – good catch. I’ll see what I can do.
Hello, thanks very much for this script. It is awesome! The only thing I can’t seem to get working is the transcript. Looks like for each email sent, it should write to a .log file. I did not see any instructions on how to config this to work. Any help would be appreciated!
Are you using the -transcript option? There’s probably not going to be much in there since the script is designed to run as a scheduled task (no real screen output). I’ll clarify that in the next version.
thanks for this awesome script Pat.
A question for you though, when I run this in demo mode, the script only finds one user that is in the Built in Users OU. It does not see the other users in the Users OU nor does it find any other users in other OUs. I’m running this on a windows 2008 R2 server that has exchange 2010 installed and the domain functional level is 2008 R2. What am i missing?
Did you ever get this going?
Thanks for this, I was able to customize it to do exactly what I want! The one thing I would like to request is the ability to email a list (formatted like the -demo option) to myself, or my team. Basically, it would be nice to receive an email every Monday with a list of the users with passwords expiring that week so we can also check remind them to change it, or at-least we will know to expect issues with them later in the week assuming they will still forget to change it (even after daily reminder emails). I’ve tried figuring out how to pipe the output of the -demo option to an email, but I’m still getting used to powershell. It would be awesome if a -admin option (or something like that) could be added to allow the list to be emailed to a specified address. If-not, maybe someone where can help me figure out how to properly pipe the output from -demo to the send-mailmessage cmdlet or something like that?
Thanks again!
][Q}[
You made my day Pat, that Script is fantastic. I am still trying to follow all that functions and code you wrote 🙂
The script itself is working fine, but I receive an error Message when the scripts hits an user without a mailbox, nevertheless the script is still excecuting like it should.
Send-MailMessage : Cannot validate argument on parameter ‘To’. The argument is null or empty. Supply an argument that
is not null or empty and then try the command again.
At C:\New-Password\New-PasswordReminder.ps1:333 char:29
+ Send-MailMessage -To $accountObj.mail -Subject “Password will expire in ….”
Is there any way to suppress that error? The first that is poping in my mind is to add that line on top of the script:
$ErrorActionPreference = “SilentlyContinue”
Is this running from an Exchange 2010 server, or Exchange 2010 management workstation?
David, this is fixed in 2.6, which should be out in a couple of days.
Hi Pat,
Great script. Exactly what I’ve been looking for as many users we have use their mobile devices etc and never get the warning otherwise.
It would be great to have some sort of log. Perhaps the output of the -demo switch could be sent to the helpdesk email every morning which would provide an overview of which users have had communication about their password.
I think that would be quite easy to implement in the current script and perhaps you could include it as part of your 1.6 release?
Thanks again for a great script so far! 🙂
Yeah, I’ve got some ideas for stuff like that, but I really need to build a lab that has some fine grained password policies so I can track down how to get the policy for a user. That’s a critical request, but something I haven’t had time to do.
There is some event log features, too.
Sorry, meant 2.6 release!
Nice Script 1st of all, thank you. keep good work going on
I have a query when i change the default OU to a child one and run the script with demo parameter it still gives all the user’s info on the screen instead of the only existing in the child OU.
Can you please explain its behavior?
Must be a weird quirk I’ll have to look into.
Please do let me know once you have done testing with it, as i want to run the test on a small OU and donot know if it would be executing all the 6000+ users as it doing with preview command, instead of child OU only.(3 users only)
Exchange 2010 Sp1 running Windows 2008 R2 (doing CA, Hub, Transport, and Mailbox)
Windows 2008 R2 Domain
I have tried your script, and it works correctly till I test the
New-PasswordReminder.ps1 -Preview -PreviewUser username
I get the following error
“Send-Mailmessage : The SMTP server requires a secure connection or the client was not authenticated. The Server response was: 5.7.1”
I am running the script on the exchange server
I did the “Creating a receive connector to use for sending email from PowerShell” using “New-ReceiveConnector -Name “Internal Relay” -Bindings 0.0.0.0:25 -RemoteIPRanges 127.0.0.1 -AuthMechanism Tls -Enabled $true -Fqdn “myserver.mydomain.com” -PermissionGroups AnonymousUsers -Server mysever”, changing the needed values.
I did not run the following “Add-ADPermission -User “NT AUTHORITY\ANONYMOUS LOGON” -ExtendedRights “ms-Exch-SMTP-Accept-Any-Recipient””, I was unsure about opening up anonymous on the exchange server.
Thanks
That only allows anonymous to relay to that receive connector, and only from the 127.0.0.1 address.
I am truning to run the script
Add-ADPermission -user “NT AUTHORITY\ANONYMOUS LOGON” -ExtendedRights “ms-Exch-SMTP-Accept-Any-Recipient”
and I get
cmdlet add-adpermission at command position 1
supply values for the following parameters:
Identity:
Any help on this would be great.
As is mentioned in the dedicated post, you can pipe that all together at one time:
New-ReceiveConnector -Name “Internal Relay” -Bindings 0.0.0.0:25 -RemoteIPRanges 127.0.0.1 -AuthMechanism Tls -Enabled $true -Fqdn “myserver.mydomain.com” -PermissionGroups AnonymousUsers -Server mysever | Add-ADPermission -User “NT AUTHORITY\ANONYMOUS LOGON” -ExtendedRights “ms-Exch-SMTP-Accept-Any-Recipient, ms-exch-bypass-anti-spam”
If you ran the cmdlet to create the receive connector, and you’re not trying to add the AD permissions, you need to tell it what you’re assigning them to.
Get-ReceiveConnector “Internal Relay” | Add-ADPermission -User “NT AUTHORITY\ANONYMOUS LOGON” -ExtendedRights “ms-Exch-SMTP-Accept-Any-Recipient”
Hit Pat,
When i run the script manually it works fine, Mailing works. (demo or live)
After i have run the command -install. The task is scheduled. But when the schedulling runs, no one receives an email. (not in spam or something like that)
(even run it under domainadmin to be sure there are enough right) in the scheduler is see last run result (0X1) Also tried run with higest privileges. Also doenst work. Tried with or without quotes. Could you help.
Found it already
there was a space in the string 🙂
Which string?
Rolled out v2.6 today. I think it resolves most of the requests here, with the exception of displaying password policy requirements for fine grained password policies.
Thank you so much for sharing this with us 🙂 Release 2.6 fixed my issue with the error prompt when the script hits an user without a mailbox
Hey Pat. Great script that I hope to have working soon.
I’ve added the correct receive connector and the necessary permissions but I get the following error when I run the script in Preview mode;
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
I have this corresponding error in my application log;
The account ‘EXACTEARTH\Administrator’ provided valid credentials, but is not authorized to use the server; failing authentication.
The script must be running as administrator when it’s sending the preview email. Any ideas?
Tell me what permissions settings are defined? Just anonymous?
Correct. Just Anonymous is checked under ‘Permission Groups’
My bad. I had set PSEmailServer to the IP address of the CAS server (same system I’m running the script on). When I set it to 127.0.0.1 it works like a charm.
Thanks!
I am trying to run the script on a remote system.
I can run the -demo with no error
I can run the -Preview -PreviewUser username with no errors and I get the e-mail
I can run the -install, and it creates the task with no error
When I run the task I get a “0xFFC0000” error
C:\Windows\system32\windowspowershell\v1.0\powershell.exe
-psconsolefile “\Bin\exshell.psc1” -command “C:\inetpub\wwwroot\ftp.Hatch-inc.net\Password_Email\images\New-PasswordReminder.ps1”
Thanks
Looks like the Exchange management tools aren’t installed on that remote machine. Notice the path to -psconsolefile.
I get the following error when trying to run the script.
[PS] C:\Scripts>.\New-PasswordReminder.ps1 -demo
You must provide a value expression on the right-hand side of the ‘/’ operator.
At C:\Scripts\New-PasswordReminder.ps1:160 char:16
+ $env:UserName / <<<
What version is listed in the header? 2.6?
yes v2.6
Thank you Pat for getting it working. Apparently Dreamweaver added those line breaks to the code. Love this script, can’t wait to hear the feedback from the end users. =]
My pleasure. I’m pretty old school, and I use a text editor (UltraEdit) for my code. I’m always afraid that opening it in anything else is going to mangle it.
Glad it’s working.
Before I spen time looking at why it will not work, will it wok with Windows 2008R2 on a windows 2003 domain? Exchagne 2007.
Domain function level shouldn’t matter. So demo mode should work. I haven’t tested with Exchange 2007.
We are running AD 2003 with Office 365 as an e-mail provider. Would your script work in this case as well?
We are running a “password sync” tool that syncs AD passwords to O365.
In theory, yes. But I don’t have a suitable test environment to verify that. If you do test it, PLEASE include your results in the comments!
Hi
We want to test this before changing our domain password policy to expire the passwords… Is there anyway to do this?
Id like to verify I’ve got the email being able to flow correctly, and also that it can find accounts..
If so i can then say yes we will turn on the domain policy but obviously cant do this until i can verify its working!
I’m running it on Exchange 2010 server and its obviously working as im getting the event messages coming ok great!
Had a look through the script and cant see anyway of switching it to either give last time password was set, or just notify regardless of what the current password policy is set as.
Thanks
Martyn
Yes, that’s explained in the post about -preview and -previewuser switches
Hello Pat,
When I run the demo I recieve no results. We have seperate password policies set by group in AD. When I try to specify the OU I get the error:
Get-ADUser : The supplied distinguishedName must belong to one of the following partition(s): …
At C:\New-PasswordReminder.ps1:396 char:22
Any Sugesstions?
Thanks
When you defined an OU, did you include the full DN for the OU, and it’s in quotes? If you run it with -preview and -previewuser [username], do you get the email?
Thanks Pat
The preview user doesnt show any details at all, and no emails are sent…
Our passwords are not currently set to expire as we have lots of remote users who have issues with this. Which is why i want to implement the script, but checks its all ok first..
Is there an option i can change to say – if the password is set to not expire then email??
Thanks for this awesome script!!
Preview option won’t show anything on the screen – it just sends the email to the user defined in -previewuser, regardless of what their expiration status is. If that’s not working, we need to find out why.
Thanks Pat – so if i use -preview -preview user “user here” it should send me an email?
Cheers
Martyn
Pat, thanks for the great script.. I dont have windows 2008 r2 domain controllers yet and its giving me, Unable to find a default server with Active Directory Web Services running. Can this script work without r2 domain controllers?
What version of PowerShell is installed on your DCs?
version 2, ran $host.version and says Major 2, minor 0, build -1 and revision -1
When I run demo from a 2010 server I don’t get any errors, however, I don’t get any results either. I set the days value to 60, 180, and as much as 1,000. I only changed the default values and not the OU.
Version 14.2 Build 247.5 / 2008 R2 SP1 / All roles in single server
Awesome script, got it working and works perfectly! One suggested improvement would be to include in the event log entry, who the email was sent to.
Thanks!
Thanks for the great script. I have a question – our Exchange servers are in a resource forest seperate from the user accounts we want to report on. How can I get this script to run against user accounts in the user forest rather than the linked objects in the Exchange resource forest?
Pat, great job, thanks!
1 question and 1 comment: When you specify an OU, does it recurse the sub OU’s under that?
I second the request to (if possible of course) send an email to a set address with the list of who the password warning was sent to the last time the script was run.
Well, my question is answered if I read correctly.
Get-AdUser -filter * -SearchScope subtree The subtree value indicates all child objects, if I read it correctly.
I have a problem with the HelpdeskURL. I will not have any image in the e-mail. I not set the $HelpdeskURL but nothing change. I try to set the variable with $null value but nothing changes. Anyone have issue with this variables?
Andrea
I’ll be looking at adding a NoHTML option for future versions that should resolve this. Unknown as to when that might happen, though.
How can I change the script so the Demo mode shows DisplayName rather than samaccount name?
No decent editor here,, so I can’t giove you the line number.
Look for “if ($demo) {Write-Host (“{0,-25}{1,-8}{2,-12}” -f $accountObj.Name, $DaysTillExpire, $PolicyDays)}”
change $accountobj.name to $accountobj.displayname and give it a whirl
Can you please post a generic example of how the $ou variable should look like when being set?
$OU needs to be in the “OU=users,OU=New York,dc=contoso,dc=com” format.
Thank you!
I still cant get the OU option to work – can anyone post a full example please – I think I’m being thick ;-/
Andy,
what do you have for youtr $ou string in the variables at the top?
Thanks a lot for this great script. Recently it worked great but today when I add the parameter “demo” I don’t get any results. I have verified the pwdLastSet attribute in my ad and no one has changed the password yet. How is this possible?
Very strange, it stopped to work for 3h. Then I tried to debug it with “-v” for “verbose” and saw everything went through but no email was sent. Suddenly it started to work again, but there has never been an error given out so far.
While my “-demo” stopped to work also the “-PreviewUser” didn’t send an email even tough it went through what I’ve seen so far with “verbose” output.
I will monitor it a few days and report in my findings. If I have time I will also try to add functions like logging to email or a path for admins the actual result and also a text-only email instead of html email for instance as a switch.
Thanks a lot again.
Bullet
I’m working on some more logging features (including emailing an admin) and a -NoHTML option.
It happened again. I’m using Win2k8 R2 with PowerShell 2.0 / New-PasswordReminder.ps1 2.6 . The task scheduler is assigned to the user “SYSTEM” and runs at 06:00 every morning.
As soon the this job has ended I cannot see any users with the “demo” argument anymore for a few hours. Job status is 0 (ok).
_____
PS C:\> .\New-PasswordReminder.ps1 -demo -v
VERBOSE: Setting variables
VERBOSE: Defining functions
VERBOSE: Checking for ActiveDirectory module
VERBOSE: Getting Domain functional level
VERBOSE: Filtering users to OU=Users,OU=SubAcme,DC=Acme,DC=local
VERBOSE: Demo mode
User Expires Policy
======================== ======= ===========
VERBOSE: Setting event log configuration
VERBOSE: Getting password policy configuration
VERBOSE: Getting the user info for user1
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user2
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user3
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user4
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
…
_____
I think it has something to do with this line and the “SYSTEM” account on line 199:
if ($demo) {Write-Host (“{0,-25}{1,-8}{2,-12}” -f $accountObj.Name, $DaysTillExpire, $PolicyDays)}
Maybe the output will be directed to somewhere else?
Thanks in advance.
I tried to debug the script and found out, that the “pwdLastSet” field read by the script is empty. But when I use for instance AD Explorer from Sysinternals I can see that the fields aren’t empty. Any ideas for this temporary bug?
Thanks Bullet
If you run the script manually with an elevated account, what happens?
Hello, thanks for all the hard work you’ve been putting on this script! The demo portion of it works great, but I’m not able to preview the e-mail. I’m having an issue with the send-MailMessage cmdlet. “Unable to connect to the remote server”. I’ve tried the FQDN and IP and it still doesn’t go through. Things to note:
1.) Exchange 07, windows 2000 domain
2.) Trying to run this script on another server.
3.) I’ve ran other powershell scripts off that server before, so not sure why i’m getting this message..
4.) Using v2.6 of the script.
Any help is appreciated!
Send-Mail doesn’t require that the email server be Exchange. It’s just an SMTP cmdlet. So what’s likely the cause is you don’t have a receive connector in Exchange that will accept from the server running the script.
I got it figured out, I thought it was the receive connector too, we had one enabled for this IP range (for the network printer e-mail functionality). I created one specifically for this one too but that did not resolve the issue. Turns out.. it was McAfee OAS blocking the SMTP attempts. Just ran a scheduled task (had to modify some settings thanks to lvjoe for his contribution) and so far everything has been running smooth.
Only minor issue I’m having is that it doesn’t e-mail external users (non-domain e-mails). But that’s an issue unrelated to the script.
A very nice way to test mail functionality without to bother people is to use a dummy mail server for preview. Hassle free emulation of a working of a smtp server with just double click:
http://smtp4dev.codeplex.com/
You can just open PowerShell and use send-mailmessage (http://technet.microsoft.com/en-us/library/hh849925.aspx) against the desired server.
HI Pat,
Thanks for this really nice scritp.
I there a way i an make this script mail just Exhange users instead of doing both?
Thanks in advance!
Mark
I’m not sure I understand what you’re asking. What do you mean “both”?
Thank-you for producing a really great script. I implemented it at my office with a customization of the email message body. I have scheduled a task to run a couple of times a week for anyone whose password needs to be changed within the next 14 days.
When I run the script using demo mode, I get an expected listing of about a couple of dozen users and the days till expirartion and policy. When I use the -previewuser switch and my network username, I get a nicely formatted email So far so good.
When the script runs as a scheduled task without these switches, the event log shows that it only processed just 2 or 3 users. The rest do not get emails. What can I do to troubleshoot and resolve this difficulty?
As a follow up to my prior comment, I have some new information. I had the scheduled task set to run using a service account that I typically use for such things. The task was set to run whether or not the account was logged in. When I reconfigured the task to run using my own domain admin account and watched the command windows pop up, it processed completely. The event log shows that all 28 accounts were correctly processed. I confirmed that users did get an email.
So it seems to be related to how the task is run and not so much the script itself.
Is the box checked that says “run with highest privileges”? If not, check that box.
It wasn’t. I changed it. As curious as I am, I’m reluctant to keep spamming people, so I changed the task to run daily. I can check the event log over the weekend and see if this fixes it.
I am curious why it is able to process a handful without “run with the hightest privileges.” I would expect that it would either run completely or not at all.
Not sure. I need to write a better function for creating the scheduled task so that I can touch more settings. So many things….
Glad you got it working.
You were spot on with your suggestion to check “run with highest privileges.” That definitely solved it for me. The scheduled task is running as expected with the service account and console logged out. Thanks so much!
Another interesting curiosity is that the built-in Windows balloon help reminder seems to calculate one day less than than your script. A user who got a reminder that his password will expire in 14 days got a Windows balloon that said 13. At first I thought this might be because the script ran a few hours earlier than the balloon, but I ran the script subsequently in demo mode, and it still showed 14 days. I checked the value for “msDS-UserPasswordExpiryTimeComputed” on his account and based upon that, I’d say the balloon help in Windows calculated properly, whereas your script seems to be computing one more day. Any thoughts?
Hi firstly thanks very much for this script, it is exactly what I was looking for. The script ran correctly however in the process it changed the AD account owner of all users from the Exchange Mailbox server to the main admins group. Can you tell me if its possible to remove this part of the script please. Thanks
As a follow up to my previous post this was discovered as users who previously could use the “Send As” feature now cannot use this and it will no longer allow me to enable this feature. Adding the Exchange Mailbox server back as the owner fixes this issue.
This script makes not changes to user accounts.
Love this!
Question: Can this be installed multiple times from different folders? We want to customize it per client company (we share our server with 3 other companies). This would allow us to customize company name and such for each client.
Also, I’m using the msDS-UserPasswordExpiryTimeComputed ADUser property from the ActiveDirectory module in a logon script for our Remote Desktop servers to remind users on logon of an expiring password. Could that simplify your script? It seems to support fine grained password policies in our environment just fine (2008 R2).
Thanks for your work on putting this together!
In theory, you should be able to run it multiple times from different folders.
Haven’t looked at msDS-UserPasswordExpiryTimeComputed yet.
Hi there, create info! The only problem is that I can’t find the location of the images that you used. I want to copy/adjust them and set them on my webserver. Do you have the images for us?
Those are linked in the download section
Hi,
Great script. How can i modify the script to send the mail only to user with a specific mail extension. If there something else in the mail box i need to exclude them.
Thanks
Ok, i read my comment and i think i’m not realy clear. So, I have users in my domain who have contact email like hotmail or gmail or no email adresses configured. So i need to exclude them from been warn.
I hope you understand better.
P.S. sorry for my traduction i’m a french speaking person
Thanks
At this time, the script will fire on accounts that have an SMTP address in the Windows Email Address field.
Unfortunately, I don’t have any plans to build in a bunch of exclusion options, as testing them would be extremely time consuming.
After working with a couple of other similar scripts before I found this I have to say THIS ROCKS!. I believe a simple tweak will accomplish the restriction however. In one of those I was using a filter such as Get-ADUser -filter {(mail -like “*@domain.com”) -and (Enabled -eq “True”) -and (PasswordNeverExpires -eq “False”)} which not only deals with non-domain emails, but also eliminates the need to check for accounts without emails, etc. I haven’t tried it yet but I’m wondering if that may not also improve processing speed. In my environment this script takes about 90 minutes to process. The other ones a was working with ran in a just a few minutes. They weren’t dealing with FGPP however so that may also be impacting things. Any thoughts as to what actually takes up the time? I’m looking at about 1000 users total, about 600 with emails.
Thanks again for a great tool.
Hi, Thanks a lot for the script, it is really helpful.
Just a quick question, if I schedule the script to run daily and set the DaysToWarn = 7, will it only send email on the 7th day once? Or it will send email once daily on the 7th, 6th, 5th, 4th …etc day till the exact expiry day?
FYI, I would like the email remind user one week before their password is about to expire, then again when there are two days remaining to expire.
Thank you.
1 It will send the email daily until the expiration date
2 The easiest solution is running two scripts one that runs weekly and one that runs daily
Well I have got this wonderful script running except as a scheduled task. I can run it in demo perfect. I can run it in preview mode perfect. I can just run it in regular mode (no switches) perfect. My environment is 2008r2 DFL and the script is on one of my domain controllers at the moment. I used the install switch and that worked perfectly. I am running the task as my domain admin account and have the run with highest privileges box checked. in the task history it appears to run and complete just fine however there is no associated even in the application log stating that the script processed x number of users and no one recieves an email. Version 2.6 of the script. Any ideas?
Hi,
Getting this error now..
v2.7 running in the EMC on Server 2008 R2
Cannot bind argument to parameter ‘accountIdentity’ because it is null.
Any help appreciated
Andy
Works great in -preview -previewuser mode to myself
The above error is in -demo mode..
Cannot test the script in normal mode as I need to test I have the OU$ parameter is right before hand so as not to annoy other admins in other OU’s ;-))
Hope that makes sense.
I’ve used the command Set-ExecutionPolicy RemoteSigned, but I still get a signature error when running.
Also I’ve tried setting the OU command using:
[string]$ou = “OU=Faulty\,\ Staff\ &\ Misc,DC=MyDomain,DC=ORG”
But still get an error.
Ignore spelling mistake in “Faculty”
Fixed the signature issue, by copying all the text from the script and place it into a new locally created text file.
Fixed – I had a typo in mu OU string!! – working great – many thanks.
This is proper fantastic! Was really sick of users being locked out during the middle of the day because they didn’t see the Win7 balloon informing them their password was about to expire.
Setup was a breeze as well. Really big thanks!
Any way to get this to work with Microsoft Online Services?
Not that I’m aware of.
I must be a bit thick here as far as the OU is concerned.
I have a Forest with three Child Domains. Users are only in the Child Domains. When I leave the $OU blank I only get a notice about one user in the Forest Root, but none in the Child domains.
If I try to set one of the Child Domains in the $OU I get an error.
I tried: $OU = “OU=Users,OU=Domain Users,DC=XXXXX,DC=internal”
I am getting the following error;
“Get-AdUser : The supplied distinguishedName must belong to one of the following partition(s): ‘DC=XXXXXX,DC=internal , CN=Configuration,DC=XXXXXX,DC=internal ,
CN=Schema,CN=Configuration,DC=XXXXXX,DC=internal , DC=DomainDnsZones,DC=XXXXXX,DC=internal ,
DC=ForestDnsZones,DC=XXXXXX,DC=internal’.
At C:\Users\XXXXXX.XXXXXX\Desktop\New-PasswordReminder.ps1:423 char:12
+ $users = Get-AdUser -filter * -SearchScope subtree -SearchBase $ou -ResultSetS …
What happens when you run it from within one of the child domains?
Hello Richard,
I am struggling to get this to work when I run
PS C:\> .\New-PasswordReminder.ps1 -demo -v
VERBOSE: Setting variables
VERBOSE: Defining functions
VERBOSE: Checking for ActiveDirectory module
VERBOSE: Getting Domain functional level
VERBOSE: Filtering users to OU=Users,OU=SubAcme,DC=Acme,DC=local
VERBOSE: Demo mode
User Expires Policy
======================== ======= ===========
VERBOSE: Setting event log configuration
VERBOSE: Getting password policy configuration
VERBOSE: Getting the user info for user1
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user2
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user3
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
VERBOSE: Getting the user info for user4
VERBOSE: verifying that the password is not expired, and the user is not set to PasswordNeverExpires
VERBOSE: Verifying if the date the password was last set is available
it runs against every users but I get no results.
domain level server 2008
Ex 2010
server 2008r2
I have a pso with max password age 365 days applied to all members of a group which is working fine.
Pat,
We are getting an error in PS that states ‘The parameter “TranscriptFilename” is declared in parameter-set “_AllParameter Sets” multiple times.’
Any ideas?
What version are you using?
Hi Richard,
if you are replying to my Post it is version 2.7
No, I was replying to Marshall.
Hello,
Thx for the lovely script.I wondering If i can send email in arabic content. I tried pasting some arabic content in the script but all i get is ???????.
Pls advice.
How could this script be altered to check for users in a specific Security Group?
You’d have to enumerate the members of the security group, then query the password info for each member. Unfortunately, I don’t have the resources to implement that.
Great Script Pat! Please clarify something for me though. Is the process capable of reading a 2008 R2 AD Custom Password Expiration GPO or only the Default Domain Policy with the Password Expiration set? Reason I ask is I created a custom one and linked it to different OU’s and in the demo mode and demo -v mode the OU’s are correctly read but the Password Expiration Custom GPO isn’t. Only when I apply a Password Expiration policy to the Default Domain Policy does the demo mode show the expected results. Thank You.
The demo mode does show the expected results. Unfortunately, I have been unable to figure out how to read the granular policies. It’s on my to-do list.
Thanks for the clarification Pat!
Goodmorning Pat,
I tried to add it in the scheduled job with my admin account.
I added it manually and with the adminsitrators account.
I can run it manually but for some reason the task won’t run as a scheduled job.
I run it with the highest privilleges but no luck.
The settings are:
Program/Script: c:\windows\system32\windowspowershell\v1.0\powershell.exe
Add arguments(optional): -psconsolefile “C:\Program Files\Microsoft\Exchange Server\V14\Bin\exshell.psc1” -command “New-PasswordReminder.ps1”
Start in: E:\website
Do you have any suggestions?
Hi Pat,
I think I figured it out. I will share the solution with you. After the command switch you have to include the entire path to the ps script. You should ignore the start in option in the scheduled task. After making this change ( in quotes ) it runs like a charm.
Thanks for this great piece of script, Pat.
I’m having some issues with special characters (ã, á, é, õ, ç) within the message body.
I’ve checked the header and the charset is UTF-8 but it doesn’t seem to work.
Could anybody please test it or tell me how to enable these characters?
Kind regards.
Excellent. Works well.
One thing we would like is to know that the script ran, emailed these perople, and was successfull. Maybe email a status to an admin email address with a summary??
Want to use this password expiry notification script but soon upgrading infrastructure to windows 2012 and exchange 2013 – will it still work? thanks
It should work fine.
Sorry if this post comes up twice but I got a timeout error the first time.
Is there a way of excluding a specific child OU beneath the target? Or perhaps specifying multiple target OUs?
Not at this time.
Pat – I’ve put your fantastic script in to a live environment after successful testing. I am getting an Exception calling “WriteEntry” with “3” arguments: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security
I notice a long long thread on technet where you were having this problem:
http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/e172f039-ce88-4c9f-b19a-0dd6dc568fa0/
Is there anything I can do to get rid of this message? Will it cause a problem with the scheduled task running nightly?
The password email is received correctly by the -preview user but dont want this error.
Thanks
Nathan
Сергей Попов – are you talking about my problem “WriteEntry” ?
Thank you for the script! I wonder if you or anyone else can help me. Is there a way to change from the Display name to a combination of given and sn?
There is always a way with PowerShell. Unfortunately, I don’t have much free time now.
Hello,
I ran the .ps1 script ( v2.8 ) with the -demo option and no errors are displayed on screen. No list of users either
PS C:\xxxxxxxxxxx> .\New-ADPasswordReminder.ps1 -demo
User Expires Policy
======================== ======= ===========
PS C:\xxxxxxxxxxx>
Running Windows Server 2008 R2 Forest Functional Level and Exchange 2010
Kind Regards
Edward
Are you positive you have users with passwords expiring soon?
Hello Pat,
That was the problem. Thanks for the help. Everything appears to be working. I have yet to see the scheduled task kick in but have checked the highest privileged checkbox and will see how it goes.
Kind Regards,
Edward
Hello Where would you specify the encrytion Unicode? when saving the file?
Is there a reason why?
For example, if i write in Russian in the email. In this case, email will be unreachable.
By far the best notification script out there. 1000+ users and it works flawlessly! Great job!
First of all thanks for the script. Can I suggest a modification to the user search filter from * to {(objectclass -eq “User”) -and (Enabled -eq “True”) } in order to only return the non disabled users as there is no point to inform disabled users that their password will expire.
Thanks
Pat
Fantastic script. Works really well as designed
Thanks again for you efforts
I really good script, thanks.
What i would like to have is a builtin “variable”/Funktion so i can install the script towards different domains, i have now in the script changed all the rows that have something with get-ad….. with extension “-server domain.local”.
Yeah, I might need to add an encoding option to the parameters.
hi,
Thanks very much for this script.
How can i modify the script to send the mail only to specific user ?
Hi Pat. I have a domain that is used for terminal services only and has no Exchange server. Will this script be able to work in a domain with out a exchange server but with an SMTP Virtual Server? will it require the Exchange Management tools?
In theory, as long as you have an SMTP server to send to, it should work.
Hey Pat, I am one of your great follower and the scripts have made my line of work so easy. Keep up the good work. my issue here is do you have scripts for office 365. we have just migrated and I do not seem to be receiving the password change email.
I do not have anything for O365 at this time.
See this link, don’t you have the default setting? Password reminder 14 days before?
http://community.office365.com/en-us/wikis/manage/changing-and-resetting-passwords-for-office-365.aspx
creating the automated scheduled tasks does’nt work to well
the parameters for manualy creating the scheduleds task are
scheduled task
action
start a program
program
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
argument
-ExecutionPolicy Bypass -File passwordreminder.ps1
Start in
C:\powershellscripts\
Hey Pat, this is the best, i had just implemented this at my office. because we are a big organization, we were asked to migrate to office 365, now i can not receive password expiry mails. How do i integrate this with office365.
That has not been attempted or tested with this script. Sorry.
Thanks for a great script. How do I get it to work on my child domains?
It needs to be installed in each domain at this point.
I am trying to get this working on my Exchange 2010 Server running on Win Svr 2008 R2 Enterprise with no luck.
I receive the following when I run in Demo mode:
Exception calling “WriteEntry” with “3” argument(s): “The source was not found, but some or all event logs could not be
searched. Inaccessible logs: Security.”
At C:\Scripts\New-ADPasswordReminder.ps1:459 char:16
+ $evt.WriteEntry <<<< ($EventLogText,$infoevent,70)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Any ideas?
Have you changed the permissions on your security event log? If it can’t access the log, it can’t see if the source is available so that it can write to event logs.
I tried changing the perms on the log, but I still can not get it to work. Part of the issue is that I am not sure what user/group/service etc. I should be adding or changing. What should I change exactly? I tried adding domain admins (which should allow my account write access), Local service, network service, Exchange servers, etc… All with no joy.
I had the same issue until I restarted power shell and selected “run as administrator”.
Yep – most of the issues with it not running are resolved when it’s run with elevated rights.
Test the script manually in an elevated session. I see that error when it’s not an elevated session.
It needs to be run as an administrator.
Brilliant – worked first time on our Exchange 2013 and WIn2K8 environment. Well done Sir !
Hi all!
we had the issue that the script lists all the “hidden” AD users which are created internally for domain trusts. As those users are managed by the AD itself but don’t have a password that never expires they are listed..if you try to mail them..it fails because they don’t have a mail address.. I altered the filter to exclude those users from the get-aduser command.
I used the following LDAPFilter: -ldapfilter ‘(!(name=*$))’ instead of the -filter * part.
Change that in line 423 or 425, whichever you use.
Probably that can be included in the next version..
It’s been added to v2.9. Thanks for the info.
Hey Pat!
Not sure if you saw my last post, but is there a way to have this run against a single OU instead of the whole domain forest?
I’ve been working with this and during testing it works flawlessly. I’ve run into an odd problem however when the scheduled task runs. It runs, and it appears to do it’s job just fine, but a spot check with some of my users revealed that they weren’t getting the notification emails. I tweaked the script to bcc my test account with all the emails and in this morning’s run, despite the fact that there were 14 users with expiring passwords that should have been notified, only 2 emails got delivered. I ran the script manually and all 14 go through with no problems. Very odd. I’d understand if it didn’t work at all, etc., but why piecemeal? Any ideas?
Thanks
Is there anyway to limit this to run against users in a specific OU
HI Pat, I am trying to use the script on Server 2012 with exchange 2010 but i am getting the error as below. please suggest
Import-Module : The ‘C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.psd1’ module cannot be imported because its manifest contains one or more members that are not valid. The valid manifest members are (‘ModuleToProcess’, ‘NestedModules’, ‘GUID’, ‘Author’, ‘CompanyName’, ‘Copyright’, ‘ModuleVersion’, ‘Description’, ‘PowerShellVersion’, ‘PowerShellHostName’, ‘PowerShellHostVersion’, ‘CLRVersion’, ‘DotNetFrameworkVersion’, ‘ProcessorArchitecture’, ‘RequiredModules’, ‘TypesToProcess’, ‘FormatsToProcess’, ‘ScriptsToProcess’, ‘PrivateData’, ‘RequiredAssemblies’, ‘ModuleList’, ‘FileList’, ‘FunctionsToExport’, ‘VariablesToExport’, ‘AliasesToExport’, ‘CmdletsToExport’). Remove the members that are not valid (‘HelpInfoUri’), then try to import the module again.At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:121 char:17
+ Import-Module <<<< -Name "$name" + CategoryInfo : InvalidData: (C:\Windows\syst…eDirectory.psd1:String) [Import-Module], InvalidOperatio nException + FullyQualifiedErrorId : Modules_InvalidManifestMember,Microsoft.PowerShell.Commands.ImportModuleCommand
Get-AdDomain : The term 'Get-AdDomain' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:391 char:28
+ $global:dfl = (Get-AdDomain <<<< ).DomainMode
+ CategoryInfo : ObjectNotFound: (Get-AdDomain:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Get-AdUser : The term 'Get-AdUser' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:398 char:22
+ $users = Get-AdUser <<<< -filter * -ResultSetSize $null
+ CategoryInfo : ObjectNotFound: (Get-AdUser:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
User Expires Policy
======================== ======= ===========
Get-ADDefaultDomainPasswordPolicy : The term 'Get-ADDefaultDomainPasswordPolicy' is not recognized as the name of a cmd let, Junction, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:420 char:65
+ $DefaultDomainPasswordPolicy = Get-ADDefaultDomainPasswordPolicy <<<<
+ CategoryInfo : ObjectNotFound: (Get-ADDefaultDomainPasswordPolicy:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PasswordComplexity : Cannot convert value "" to type "System.Boolean", parameters of this type only accept booleans or numbers, use $true, $false, 1 or 0 instead. At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:423 char:26
+ [bool]$PasswordComplexity <<<< = $DefaultDomainPasswordPolicy.ComplexityEnabled
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
Get-ADUserPasswordExpirationDate : Cannot bind argument to parameter 'accountIdentity' because it is null. At C:\Program Files\Microsoft\Exchange Server\V14\Scripts\New-PasswordReminder.ps1:427 char:34
+ Get-ADUserPasswordExpirationDate <<<
Open a new elevated PowerShell session, and try running Import-Module ActiveDirectory. Does it succeed without error?
HI Pat, just tried and it went to next line without any errors
but still dosent work :/
Hi Pat, I would like to use this in my organisation. However I want to use it with the -noimages switch. It works correctly except I would like it to use a font that isn’t Times new roman in the body. Is there an easy way I can set this? Sorry I have no HTML knowledge and my fumblings have achieved nothing useful.
Thanks and great job, this is really useful stuff.
i got this error while run in demo.
[PS] C:\New-ADPasswordReminder.v2.9>.\New-ADPasswordReminder.ps1 -demo
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automation.CmdletBindingAttribute’.
At C:\New-ADPasswordReminder.v2.9\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $True, SupportsPaging = $True)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Let me guess. It’s running on a server that’s not Windows 2012? Look for the line that reads
SupportsShouldProcess = $True, SupportsPaging = $True
and change it to
SupportsShouldProcess = $True
It works, thank you..
Regarding this – it says “requires v2”. This should say “requires v3” since supportspaging is a Powershell V3 command
Actually, everything else in the script support v2. If you remove the supportspaging part, it runs fine in v2. Next update will resolve that.
Do you mean change it to false?
No – remove the “SupportsPaging = $True” part.
Oh, you mean remove “SupportsPaging = $True” from line 86. Duh.
I am trying to schedule the task to send emails with no image but it dosent seems to run when i add -noimage at the end
Thank you, the script worked well , but am having user getting an email even though they changed password.
do you have to have OWA?
We don’t use Outlook 🙁
No. This script has nothing to do with HOW you change your passwords. You just have to have a method to change them, and edit the script accordingly.
Hi Tony,
I’m getting an error in Powershell when trying to run this script in demo mode. I’m running Powershell as an admin in Windows 7.
This is the error –
PS C:\ADPasswordReminder> .\New-ADPasswordReminder.ps1 -demo
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automatio
n.CmdletBindingAttribute’.
At C:\ADPasswordReminder\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $True, SupportsPaging = $True)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
I've tried googling around for this error but I cannot find anything on it. Any ideas? I tried the previous versions of the script and they worked fine, this is the latest version and it's failing.
I do not intend to run this on an exchange server, is that the reason why I'm getting this error?
I am getting this same error. I am running this on a 2008r2 Terminal Server with the Exchange management tools and other mentioned requisites installed.
Is there an easy way to have it so that the line “ALERT: You must change your password today or you will be locked out!” only shows up on the last day? It would great if I could replace it with “ALERT: If you don’t change your password in days, you will be locked out!” Is this possible?
Anything is possible in PowerShell. 🙂
I’ll add it to the wish list.
Quick Question… will this script ignore accounts that have their password set to never expire? If not, I can work around that as I really should put them in their own OU for organizational reasons.
It should ignore those. Let me know if you see otherwise.
Excellent. And am I right in gather that this script is intended to be run from the exchange server itself? Could I modify the receiver configuration and run it from a different server?
It doesn’t have to run from an Exchange server. The line that begins
[string]$PSEmailServer
is where you define the email server.
Another question, how do I have this display the message in Chinese, German and Portuguese? Is this possible?
sometimes people give you a really cool gift for free and you still want the world on a silver platter.
There is no support for other languages, and unfortunately, I have no time to adapt it for that.
Ok, thanks. Great script btw.
Love the script, and have it running against a pilot OU right now. I’d like to have one scheduled task that send out a notification only if a user’s password is at 10 days to expiration, and then another at 5 days or less (5,4,3,2,1). Having problems with this though, what’s the best way to modify the script to be able to accomplish this?
When I try to run .\New-ADPasswordReminder.ps1 -Install on Windows 2008 R2 Enterprise I get below error message
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automation.CmdletBindingAttribute’.
At C:\Scripts\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $True, SupportsPaging = $True)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
My server already have AD Module for Windows Powershell installed
Open the script in notepad. Find the line
[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True)]
replace it with
[CmdletBinding(SupportsShouldProcess = $True)]
Hi Pat,
Thanks for your help and this has resolved my problem. One question will it be possible for me to test for single user as when I try to execute “.\New-ADPasswordReminder.ps1 -Preview -PreviewUser UserADID” I get below error message
C:\Scripts\New-ADPasswordReminder.ps1 : Missing an argument for parameter ‘PreviewUser’. Specify a parameter of type ‘S
ystem.String’ and try again.
At line:1 char:38
+ .\New-ADPasswordReminder.ps1 -Preview <<<< -PreviewUser paliathv -NoImages
+ CategoryInfo : InvalidArgument: (:) [New-ADPasswordReminder.ps1], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,New-ADPasswordReminder.ps1
My email address is in the script header. Send me an email with a screenshot.
Hi Pat,
I have managed to fix my account issue, however when I run .\New-ADPasswordReminder.ps1 -Demo I get below error message
[PS] C:\Scripts>.\New-ADPasswordReminder.ps1 -Demo
Import-Module : The following error occurred while loading the extended type data file:
Microsoft.PowerShell, C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.Types.ps1xml :
File skipped because it was already present from “Microsoft.PowerShell”.
Microsoft.PowerShell, C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.Types.ps1xml :
File skipped because it was already present from “Microsoft.PowerShell”.
Microsoft.PowerShell, C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.Types.ps1xml :
File skipped because it was already present from “Microsoft.PowerShell”.
At C:\Scripts\New-ADPasswordReminder.ps1:131 char:17
+ Import-Module <<<< -Name "$name"
+ CategoryInfo : InvalidOperation: (:) [Import-Module], RuntimeException
+ FullyQualifiedErrorId : FormatXmlUpateException,Microsoft.PowerShell.Commands.ImportModuleCommand
The term 'Get-AdDomain' is not recognized as the name of a cmdlet, function, script file, or operable program. Check th
e spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Scripts\New-ADPasswordReminder.ps1:419 char:28
+ $global:dfl = (Get-AdDomain <<<< ).DomainMode
+ CategoryInfo : ObjectNotFound: (Get-AdDomain:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
The term 'Get-AdUser' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Scripts\New-ADPasswordReminder.ps1:428 char:22
+ $users = Get-AdUser <<<< -ldapfilter '(!(name=*$))' -ResultSetSize $null
+ CategoryInfo : ObjectNotFound: (Get-AdUser:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Maybe you can share how you solved the account problem.
I am having the same problem!
I was getting the above error – troubleshooting the issue by running the command in PowerShell suggested the Extensions were not loading. Spent ages troubleshooting the extensions issue and ended up running the with Extensions then pointed me to ADWS not running – Sure enough ADWS had stopped on both DC’s and with a restart of that service, this works again 🙂
http://theadminsguide.net/2012/08/30/error-initializing-default-drive-unable-to-find-a-default-server-with-active-directory-web-services-running/
Thanks for that great script. But it do not work.
Can you please help me with this error?
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automation.CmdletBindingAttribute’.
At C:\Scripts\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $true, SupportsPaging = $true)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
Regards
That’s discussed in the comments here.
yes sorry… i didnt see it before…..Script is working great.
Thank you very much.
regards
Many thanks for the great script!. It works like a real smoothie… I had a query regarding our environment. We have an OU which contains non-mail Exchange users, they have external email add configured in the email property of AD account. Is it possible to send mail to external users? Cheers
Hi, Kudos and thank you for the awesome script, this makes things soo easy!!. I am currently facing an issue while running this script int the demo mode. It is showing incorrect value of 180 days whereas the Policy is set to 60 days. Could you please point me to the right direction. Thanks!
Love this script it saved me from having to rewrite the one we were using and broke. One thing though you should check for account disabled since those accounts should not get reminder emails and frequently their email is forwarded to other users so could lead to confusion. This is easy to add in case anyone else wants to just modify the ForEach ($user in $users) loop as follows:
ForEach ($user in $users){
If ($user.Enabled)
{
Get-ADUserPasswordExpirationDate $user.samaccountname
}
}
When I try to run C:\New-ADPasswordReminder.ps1 -Preview -PreviewUser username
I receive this error
C:\New-ADPasswordReminder.ps1 : Missing an argument for parameter ‘PreviewUser’. Specify a parameter of type ‘System.St
ring’ and try again.
At line:1 char:39
+ C:\New-ADPasswordReminder.ps1 -Preview <<<< -PreviewUser ant
+ CategoryInfo : InvalidArgument: (:) [New-ADPasswordReminder.ps1], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,New-ADPasswordReminder.ps1
Any ideas?
Leave out “-preview”, leaving just “-previewuser “.
Hi,
This doesn’t seem to filter ‘disabled’ accounts, how could I modify it to do so?
Cheers,
That’s coming in a future release.
Excellent. A ‘report’ feature might be nice as well, to send a list of passwords expiring within the next few days to an admin account.
Thank you, it’s already saved me a ton of work!
Nice script. Thank you. A minor point: The preview syntax seems to be just “-previewuser” (not “-preview” as the in-script documentation states at lines 43 and 44).
I chose the add the following lines after the Send-MailMessage line (actually after ‘$global:UsersNotified++’), so we can see who got sent them emails and when:
$EventLogText = “Password expiry email sent to $emailto ($DaysTillExpire days(s) until expiry)”
$evt.WriteEntry($EventLogText,$infoevent,71)
So, after each run of the script you’ll get an Event ID 70 summarising how many mails were sent and the same number of ID 71s detailing each individual who got the email. Sweet!
Hi thanks for your efforts on this promising looking script. When I run it in -demo mode I get the following error.
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automatio
n.CmdletBindingAttribute’.
At D:\Password Expire Script\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $True, SupportsPaging = $True)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
I am running this on the exchange server which is Windows 2008 R2 with powershell 2.0. I have the "Active Directory modeule for powershell" installed. Any help would be greatly appreciated.
thanks
Chris
I have had this script running great on my 2008 R2 server for a year and a half. I’m retiring that old server, and moving this to a 2012 server running Exchange 2010. In my testing I’m having issues getting the script to run. I execute with the -demo parameter and get this:
“Import-Module : The ‘C:\Windows\system32\WindowsPowerShell\v1.0\Module\ActiveDirectory\ActiveDirectory.psd1’ module cannot be imported because its manifest contains one or more members that are not valid….. It then lists the valid members and fails on a bunch of other cmdlets.
So, questions. Will this script run on a 2012 server running Exchange 2010? If yes, what do I need to do to make it work? I have confirmed that the AD Module for PowerShell is installed and am running the script as the admin. I’ve tested the old script, and also downloaded the latest version.
I know this thread hasn’t had any activity for a year, but hopefully someone knows something. Thank you.
Hey Pat. We’ve been using this script in our Exchange 2007 environment flawlessly and it has cut down on the amount of servicedesk related tickets for password resets. I would like to sincerely thank you for your work on this script. We have recently migrated to Office 365 (very painfully) and obviously this has broken the password reminder script from emailing our users as our old Exchange server is no longer in production. Any info on how to get this up and running or will I have to contact Microsoft to try and get this to work with their email servers. I’ve tried to point the email server to the correct new address, but still receiving an error: “Unable to read data from the transport connection: net_io_connectionclosed.”. Please tell me there is a chance to get this working with Office 365 servers!
Thank you,
Kyle
Pat never mind this comment. Since we use dirsync I have figured a way to get this to work without any major changes. Your script is a life saver and now back in business!
Thanks again,
Kyle
Anyone know if this works on Exchange 2013?
Yes
how to remove table format & set in Normal mail body?
Awesome script. Is there a way to add in searching for accounts which passwords have expired and then emailing an address, in this case our helpdesk, so they can then reach out to users proactively?
Not at this time. I can add it as a feature request.
Hi Pat,
Thanks for writing this script, it works perfectly. You have saved a lot of admin from the headache of password reset/account lockout issues. I was wondering if you have a place to donate to your work? I checked the page, but didn’t seem to find one. Also, I read through the comments and saw a particular feature that would be helpful. I would like to add a CC of the email to a manager of the person that has their password expiration notice sent. Would you mind assisting with this or is that a feature you might add?
Regards!
can i install it on another machine then exhange?
we are working with o365,
the .\install installs -psconsolefile \Bin\exshell.psc1 (but i dont have exchange)
Pat this looks great. I can’t wait to try this out. Will let you know the results. We run exchange 2010 on 2008R2 servers on a 2008R2 functional level domain.
Send-MailMessage : The specified string is not in the form required for an e-mail address.
Why do I get this error when i run this script and also in preview mode?
Hi!
Could do it with variable too 🙂 (didn’t notice that post above till now, uhoh)
Added variable $enc and a switch -Encoding $enc to the Send-MailMessage.
To the start where variables are defined:
# Set encoding to one of these values: System.Text.ASCIIEncoding, System.Text.UnicodeEncoding, System.Text.UTF32Encoding, System.Text.UTF7Encoding, System.Text.UTF8Encoding
$enc = New-Object System.Text.utf8encoding
And the send-command:
Send-MailMessage -To $emailto -Subject “Salasanasi vanhenee {$DaysTillExpire}:n päivän päästä” -Body $emailbody -From $EmailFrom -Priority High -BodyAsHtml -Encoding $enc
Hi,
great work and tnx for sharing.
Is there away to have the script search in current domain and ALL subdomains? something like “IgnoreDefaultScope” ?!?
Regards.
Red.
@Nathan
Was there a fix for this ?
I understood that this script ought to take fine grained password policy into consideration too, but at least in demo-mode it doesn’t seem to do that. Couldn’t find a definitive answer from here does it support that or not?
@Markus
Yes we use fine grain password policy and it works great!
Hi!
How to restrict email messages only to active user accounts? So Disabled user accounts would be skipped
Thanks!
Hi, trying to run this on a Windows 2008 server, getting error.
Property ‘SupportsPaging’ cannot be found for type ‘System.Management.Automation.CmdletBindingAttribute’.
At E:\adpwscript\New-ADPasswordReminder.ps1:86 char:15
+ [CmdletBinding <<<< (SupportsShouldProcess = $True, SupportsPaging = $True)]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
You have a version of Powershell that’s too old.
Get-AdUser : The object name has bad syntax
At \\98pwdsct001\c$\scripts\FirstQ_PasswordExpiration.ps1:384 char:12
+ $users = Get-AdUser -filter * -SearchScope Subtree -SearchBase $ou #-ResultSet …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException
+ FullyQualifiedErrorId : The object name has bad syntax,Microsoft.ActiveDirectory.Management.Commands.GetADUser
User Expires Policy
======================== ======= ===========
What happens when you run it directly from that machine, instead of via UNC path?
I’ve now read every post above looking for an answer.
Running on 2012 R2 and it is a Hybrid Exchange for our o365.
When running Preview or Demo it works great. Get a nicely formatted email from preview and demo does find the users needing the emails as they should. Freaking awesome script.
I’m having an issue when the task runs. It completes as it should no error, but it sends an email to everyone in the company everyday, not just the users under 14 days. The email they get is also only the footer image and the helpdesk link message.
Preview shows everything in the test email correctly.
I’m sure it is something that I have dorked up while editing the code. I am not what you might call well acquainted with Powershell so you might need to use small words.
@zabolyx
Figured out my issue. Must have broken it when editing the HTML.
Started from scratch and rebuild the email portion and it seems to be working like a champ.
Now to mod another copy of it to disable users email access to o365 when their password expires and send an email to helpdesk about the user’s lack to comply.
Awesome script. Thanks
Hi, first of all,thanks a lot.
Script running fine on 2012R2 Exchange 2013 BUT expiration date calculation is wrong. always get: Your xxxx password expires in 1 day(s),
tried with several users in -preview mode.
Any suggestion on this?
thanks!
Preview mode always shows the 1 day warning by design.
@Pat Richard
BAAAM! Thanks a lot!
Hi!
Script works grate, except for users that have FGPP. The expiration time is shorter than in the default policy. Could that be the problem?
When I tested by removing the check has password expired, those users came up as well.
@Markus
*great (not grate 😀 )
I cant seem to figure out how to install it with the -noimage flag active? Anyone care to help?
HI Richard,
Thank you for such great post.
I need your help.
the notification sent out should have two headings;
1. in red colour mentioning the action required.
2. in green colour mentioning the steps to change the password.
any help would be appreciated.
Thanks.
@Pat Richard
This works great, but like many others we are moving to O365. Any chance you will be working on an updated version for O365?
Highly unlikely.
@Kyle
Hi Kyle, How do you have this setup with O365 as we will be migrating our Exchange to O365 soon and would like to keep this notification in play.
Thanks,
Jon.
^^ I got this to work with Office365, but clients AD for still on sites just the exchange is on Office365.
http://o365info.com/smtp-relay-in-office-365-environment/
REF# Part 1 – Implementing SMTP mail relay using IIS server
Hi, is there a way to CC the administator in this email, so that we can doublecheck that the email arrives at the users.
Greetings, Ron
I have issue about Turkish character. How to fix it?
For example
“Değişim zaman”ı seems like “De?i?im zaman?!”
I changed in Get-AdUserPasswordExpirationDate.ps1
to
not working. How to fix it?
how do i include the credentials for the smtp sender id in it. without which i will not be able to send the mails.
The scheduled task runs with credentials. You configure it there.