Password expiration notification 1.2

I was talking to a friend of mine also working in IT and somewhere during the conversation the topic of Windows 7 and balloon popups appeared. As those popups tend to get missed in a lot of cases and depending on how the network is secured this means in case of password expirations the user is locked out of the network. To counter the balloon popup issue we run a script on a daily basis that mails users that their password is about to expire. Took some time to rewrite the script we run so it is more flexible in such you can determine which OUs will be scanned and on what days before expiration a notification is being send. Enjoy.

Version 1.1 Update:
Two things are fixed which came to my attention. The first is if you only had a single OU to be scanned the script wouldn’t work. For those that know powershell it was easy to fix. Now there is a check to see if there is only a single OU entry and the script will behave correctly if there is. The second fix is to check if an account has an e-mail address attached to it, otherwise no mail can be send out. If logging is enabled an additional line will be added to the log file in case no e-mail address was found.

Version 1.2 Update:
Code requires version 3 of Powershell, on version 2 .count does not work.

#requires -version 3

<#
Program  : PWExpNoticeMailer.ps1 - Password Expiration Notice Mailer
Author   : Eugene Dullaard (https://eugene.dullaard.nl/?p=409)
Date     : 27-Aug-2013 - version 1.0
           - Initial Script
Update   : 22-Dec-2014 - version 1.1
           - Check for existence of emailaddress and add none-existence to logfile if enabled
           - Check for Array in case of a single line entry, script didn't work for single OU
Update   : 13-May-2015 - version 1.2
           - Changed the required version of powershell to 3.0 due to use of .count

To Do's before running this script in your environment:
- This script should be scheduled on a daily basis in order to run the check once a day.
- You should modify the values of $LogFile,$DaysAdvWarn,$MailServer,$MailSender to what
  is required in your environment
- Change and/or add Organizational Units to be searched
- Change and/or add the above OUs into $ArrOU
- Change the $Subject and $Message so they contain what you require
- For testing purposes, change $_.EmailAddress to your own so you see the results
#>

Import-Module ActiveDirectory

$LogFile = ".\PWExpNoticeMailer.log"       # Logfile location, use "" to disable logging
$DaysAdvWarn = 21,14,7,4,2,1               # Days before expiration to send warning
$MailServer = "mailserver.domain.tld"      # FQDN or IP of mailserver to be used
$MailSender = "itnotification@domain.tld"  # Mail address of sender

# Enter Organizational Units to search for user accounts in LDAP notation
# Name them as you wish and use these names in ArrOU variable as per example
$ou0 = "OU=Abusers,OU=Beavis Corp,DC=domain,DC=tld"
$ou1 = "OU=Loosers,OU=Butthead Inc,DC=domain,DC=tld"

# Build the array of Organizational Units stated above, keep them in sync if you want to use them all
$ArrOU = $ou0,$ou1

# Get the maximum password age and exit if not set
$MaxPWAge = ((Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge).Days
if ($MaxPWAge -eq 0) {Throw "No Domain Password Policy Present"}

# Loop to run through all the Organizational Units to search
for ($a=0;$a -lt ($ArrOU).count;$a++) {

  #Check if Array exists and change searchbase properly in case of a single OU entry
  if ($ArrOU.count -eq 1) {$SearchBase = $ArrOU} else {$SearchBase = $ArrOU[$a]}

  #Get All Users within one of the Organizational Units
  #Not taking people that have disabled or non-expiring accounts
  Get-ADUser -Filter {(Enabled -eq $true) -and (PasswordNeverExpires -eq $false)} -SearchBase $SearchBase `
  -Properties PasswordLastSet,EmailAddress | ForEach-Object {

    # Set variables
    $GivenName = $_.GivenName
    $Name = $_.Name

    # Calculate days left before password change is required
    $PWTimeLeft = (($_.PasswordLastSet - (Get-Date)).Days)+$MaxPWAge

    #Check if Password Time Left equals Advance Warning Days
    if ($DaysAdvWarn -contains $PWTimeLeft) {

      # Add entry in logfile if enabled
      if ($LogFile -ne "") {Add-Content $LogFile "$Name,$PWTimeLeft"}

      # Build up message if mailaddress is present
      # You can add instructions or change the content as you see fit
      if ($_.EmailAddress -ne $null) {
        $Subject = "IT Notification: Your password expires in $PWTimeLeft days"
        $Message = "Dear $GivenName,

Your password is about to expire in $PWTimeLeft days.
Please take the appropiate action bofore your password expires.

Kind Regards,

Your IT Department

(This message is automatically generated, please contact your support desk if you have any questions.)
"

        # Sending Message (Hint: Change $_.EmailAddress to your own for testing purposes)
        Send-MailMessage -to $_.EmailAddress -from $MailSender -Subject $Subject -body $Message `
        -SmtpServer $MailServer
      }
      else {
        if ($LogFile -ne "") {Add-Content $LogFile "$Name,Failure : No Mail Address"}
      }
    }
  }
}

Q & A

Location of log-file?

In the example above the location is set to .\, which means current folder. If you are running this as a scheduled task without a folder set this usually ends up in the System32 folder.

Leave a Reply

Your email address will not be published. Required fields are marked *