Password Expiry Email Notification

This script will email a user in the event that their password is due to expire in X number of days.

 
 
 
 
 
4.6 Star
(153)
80,510 times
Add to favorites
Active Directory
8/7/2018
E-mail Twitter del.icio.us Digg Facebook
Sign in to ask a question


  • Multiple email domains, one AD domain
    7 Posts | Last post May 21, 2019
    • Great script, been using it for several months now and the amount of requests from users who are locked out because they didn't change their password in time has decreased. However, I just noticed that some folks aren't getting the notification because their email domain is not the same as the primary domain. My AD domain is mycompany.int. User log-in accounts are first.last@mycompany.com, or a subsidiary company first.last@othercompany.com. I happen to have @othercompany.com for my email address. I received the pop-up to change my password as it was expiring in the taskbar, so I do get Windows alerts. I did not notice my address in the daily password report I run, and I also noticed no other users with @othercompany.com addresses have appeared. I think they did at one time, and so maybe it's an O365 change, as I didn't make a change in your script. Would there be some reason why your script only sends to @mycompany.com email addresses? The account I use to send the alerts to users and the daily report is password.reminder@mycompany.com. The only time an email wasn't sent out was when the email field of the user account was blank. Any way to make sure all users, even the @mycompany.int ones, which I know will fail, will get an email? The @mycompany.int accounts are admin accounts, and I can email those user's regular account to let them know to change the admin account password. Thanks again for the great script.
    • It will attempt to send the message to whatever $emailAddress is set as. The log should tell you what address the notification was sent to, or attempted to be sent to.
      
      It is possible if the domain is external it wont allow you to relay emails, and you will need to use authentication.
    • Log doesn't show attempts to send to any of the @othercompany.com domains - they are still internal, just another domain on the DC. Users with the @othercompany.com domain are mixed in the same OU, so it's not having to check a specific one.
      
      Is there a way to run the script to check for a specific user? Then I see if it finds the handful of @othercompany.com users.
    • Might need more info on your environment.
      
      Are all your email domains on Office 365?
      Are all the email addresses stored in AD?
    • Sorry for late reply. Email domains on O365, email addresses stored in the "E-Mail Address" field on local AD. I run the script from the DC as well.
    • Are you able to use powershell send-mailmessage to email that domain seperately to the script?
    • Yes, Tried a test message to @othercompany.com from password.reminder@mycompany.com, and it came through. I get the daily reports as well, and my email is myemail@othercompany.com.
  • clarification about the testing parameter
    2 Posts | Last post May 20, 2019
    • hi Robert
      
      I will be trying your script for first time
      If I run the script with 'testing' enabled and specify a 'testrecipient' then the script will send mail only to the test recipient with the list of users that will be sent reminder mail ?
      
      thanks
    • It should send the individual emails that would otherwise go to each user, to the test recipient.
  • Results in Body no Attachment
    2 Posts | Last post May 10, 2019
    • Hey Robert,
      
      Thanks for this helpful script. Is there a way to place the results into the body of the email that gets sent to IT, rather than an attachment. It would be easier to view on mobile devices if the results were just in the body.
      
      Thanks again,
      Shane
    • Yes you could do something like...
      
          {
              $reportSubject = "Password Expiry Report"
              $reportBody = "<html>
                             <table>
                             <th>UserMessage</th>
                             <th>UserName</th>
                             <th>Name</th>
                             <th>Email</th>
                             <th>PasswordSet</th>
                             <th>DaysToExpire</th>
                             <th>ExpiresOn</th>
                             <th>SendMail</th>"
                             
      
              foreach ($obj in $notifiedUsers)
              {
                  $rmessage = $obj.UserMessage
                  $ruserName = $obj.UserName
                  $rname = $obj.Name
                  $rEmail = $obj.Email
                  $rPasswordSet = $obj.PasswordSet
                  $rDaysToExpire = $obj.DaystoExpire
                  $rSendMail = $obj.SendMail
                  $reportBody = $reportBody + "<tr><td>$rUsername</td><td>$rName</td><td>$rEmail</td><td>$rPasswordSet</td><td>$rDaysToExpire</td><td>$rSendMail</td><td>$rUserMessage</td></tr>"
              }
              $reportBody = $reportBody + "</table></html>"
              try{
                  Send-Mailmessage -smtpServer $smtpServer -from $from -to $reportTo -subject $reportSubject -body $reportbody -bodyasHTML -priority High -Encoding $textEncoding -Attachments $logFile -ErrorAction Stop 
              }
              catch{
                  $errorMessage = $_.Exception.Message
                  Write-Output $errorMessage
              }
          }
  • Negative Values
    2 Posts | Last post May 10, 2019
    • Any way to set this up to ignore users with a negative DaysToExpire value?  It sends emails to those users with a message that just says "Your Password Will Expire" without a date or time frame.
    • Negative values have always been a pain, and im not sure i really fully understand how they come about.
      
      What i think they mean is that a password was set on never expire, and then a password policy was applied and never expire was removed. Which would mean, password last set + max age, is a date in the past. In theory that user should not be able to login because their password has expired.
      
      Or, it means we are not correctly excluding people who do have password never expire set.
      
      So, do you have anyone who has PasswordNeverExpires set as 'True' when you run this command, get-aduser -filter {(Enabled -eq $true) -and (PasswordNeverExpires -eq $false)}
      
      Alternatively to just work around the issue, you could do something like this..
      
      $notifyUsers = $colUsers | where { ($_.DaysToExpire -ge 0 ) -and ($_.DaysToExpire -le $expireInDays)}
  • for already expired account or 0 day
    3 Posts | Last post May 09, 2019
    • Thanks Mr. your script is really great and easy to use.
      I have question, how to add into this script for user which already has password expired or 0 day expiry?
      
      Would appreciate your help so much!
    • Well, in theorey they wouldn't get the notification as they wouldnt be able to log in.
    • Thank for replying sir.
      Actually I am deploying this to AD on-premise with synchronization to Office 365 account.
      User not actually login using this AD account, so we need a notification system to notice them their password is already expired.
      The expired password will not affect Office 365.
      
      Big help if you can advice me how to get expired password as well.
      Like adding interval 0?
      
  • Regarding schedulling...
    2 Posts | Last post May 06, 2019
    • First, great script, works like a charm!
      I have question about scheduling...
      Let's say I schedule it to run daily, with parameter -expireInDays 21 set, but I also add -interval 3,7,14
      If script "catches" user with expiry in 21 days, on some day and if -interval is set, will user be notified only on interval days, or will he also get an email again on the next day, when script runs in its scheduled time again?
      Thanks!
    • Lets say on day 1 a user has 21 days left.
      You run the script daily with the settings you specify.
      
      Day 1, notified.
      Day 2, not notified.
      Day 3 - 7, not notified.
      Day 8, Notified - 14 days remaining.
      Day 9 - 14, not notified.
      Day 15, notified 7 days remaining.
      Day 16, 17, 18 not notified.
      Day 19, notified 3 days remaining.
      Day 19 would be the last notification.
      
      So i would always include 0,1 in the interval.
      
  • -reportto is not working
    2 Posts | Last post April 24, 2019
    • this is my script:
      
      c:\scripts\PasswordChangeNotification.ps1 -smtpServer aspmx.l.google.com -expireInDays 10 -from "IT Support <it_support@XXX.com>" -reportTo itservice@XXX.com -interval 1,2,3,4,5,6,8,10 -Logging -LogPath "C:\Scripts\passwordexpirelog" 
      
      everything is working great except for the -reportTo itservice@XXX.com im not getting emails.
      i want to receive emails as CC when a user get notifications...
    • So you dont get the reports and you also want a CC to the password reminders?
      
      Are the reports going to junk or not received at all? is this a custom domain on gmail?
  • Scheduled Task Interval Failure
    2 Posts | Last post April 18, 2019
    • Robert,
      
      This is working fantastically from powershell ISE but from a scheduled task the interval parameter is failing.  Writing to the logfile, each line finishes with ,"Skipped - Interval".
      
      I'm running powershell.exe with the following argument:
      -file c:\scripts\scheduled\AD-User-Password-Expire-Notification\PasswordChangeNotification.ps1 -smtpServer mail.domain.com -expireInDays 14 -from "Service Desk <no-reply@domain.com>" -Logging -LogPath "c:\scripts\logfiles\Password-reset-reminder" -testing -testRecipient me@domain.com -interval 1,3,5,7,14
      
      Followed advice of an earlier poster I tried wrapping the command with "" and parameters wrapped with ''.  This actually failed to run.
      
      Any ideas what I maybe doing wrong?
      
      Cheers,
      Joe
      
      
      
      
    • lol.  silly error.  changed -file for -command.  all good.  
      Joe
  • Cannot validate argument on parameter 'To'.
    6 Posts | Last post April 13, 2019
    • Hey Robert,  I have configured and tested w/o issue.  I receive my test notifications and all looks great.  When I go to run this live, I am receiving the following error when attempting to send to a user:
      
      Cannot validate argument on parameter 'To'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
      
      No email goes out.  I do not see a To parameter anywhere in the script however.  
      
      Where do I need to look?  or update?
      
      Thanks
      JH
      
    • -to is a parameter in Send-MailMessage, it is set to use $emailAddress.
      
      So, i would guess that one or more of your users does not have an emailaddress stored in Active Directory.
    • I am assuming you are referring to the 'mail' attribute in AD correct?  I show in the report that there are email addresses populated.  Here is one example:
      
      in 5 days.	zografoss	Sheila Zografos	zografoss@sd5.k12.mt.us	9/10/2018 7:06	5	3/9/2019 7:06	Cannot validate argument on parameter 'To'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
      
      The EmailAddress column is showing the correct address for the user. 
      
      
      
    • Are you able to use Send-MailMessage on it's own to that recipient?
    • Yes I am able to send test messages using Send-MailMessage through the relay.
    • Hey Robert.  So I went back and sent a test email from the script w/o any modifications and was able to successfully send.  
      
      So started reviewing each modification from the originally edited script, and line 54 - the $testing string, I had = "Disabled".  I removed the = "Disabled" from this line and retested and was successful in sending the emails!  
      
      Not sure why this line would have an affect but it is working now.  Thanks for your time on this!
  • if no expiring password is found no log is written
    1 Posts | Last post April 11, 2019
    • if no user are found the script thrown this error:
      
      You cannot call a method on a null-valued expression.
      At c:\scripts\PasswordChangeNotification.ps1:228 char:41
      +     $samLabel = $samAccountName.PadRight <<<< ($padVal," ")
          + CategoryInfo          : InvalidOperation: (PadRight:String) [], RuntimeException
          + FullyQualifiedErrorId : InvokeMethodOnNull
      
      Add-Member : Cannot bind argument to parameter 'InputObject' because it is null.
      At c:\scripts\PasswordChangeNotification.ps1:266 char:31
      +             $user | Add-Member <<<<  -MemberType NoteProperty -Name SendMail -Value "OK"
          + CategoryInfo          : InvalidData: (:) [Add-Member], ParameterBindingValidationException
          + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCommand
      
      Creating Log File
      Log Output: .\11-4-2019-PasswordLog.csv
      Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
      At c:\scripts\PasswordChangeNotification.ps1:296 char:32
      +     $notifiedUsers | Export-CSV <<<<  $logFile
          + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
          + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand
      
      
      
31 - 40 of 534 Items