Tuesday, April 18, 2017

Password Expiration Email Notification Powershell Script

This is a script that will check specific domains in an AD forest and send password notifications out to people before their password expires. The notification email is sent in the user's native language based off the AD attribute for that user. This is based off this script here but with added functionality.
#################################################################################################################
# 
# Original Source: https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27#content
# 
# Script to Send Automated Email Reminders when Users Passwords are due to Expire.
#
# Requires: Windows PowerShell Module for Active Directory
#
# Modified by Dan Dill to support multiple domains through discovery and notifications in multiple languages based 
# on user country lookup.
#
# For country codes see: http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
#
# http://danstechnotes.blogspot.com
# 
##################################################################################################################
# Please Configure the following variables....
$smtpServer="yourmailserver"
$from = "IT <helpdesk-noreply@eample.com>"
$logging = "Enabled" # Set to Disabled to Disable Logging
$logFile = "C:\temp\pwdchgnotification.log" # ie. c:\mylog.csv
$testing = "Disabled" # Set to Disabled to Email Users
$testRecipient = "testrecipient@example.com"
$date = Get-Date -format yyy-MM-dd
$adforest = "adforest.example.biz"
$domainstoexclude = "excludeddomain.example.biz"
# You will also want to scroll down and configure the body of the email notification that goes out to people to match
# your password policy and desired verbiage.
#
##################################################################################################################
#Actions begin here


# Check Logging Settings
if (($logging) -eq "Enabled")
{
    # Test Log File Path
    $logfilePath = (Test-Path $logFile)
    if (($logFilePath) -ne "True")
    {
        # Create CSV File and Headers
        New-Item $logfile -ItemType File
        Add-Content $logfile "Date Run On(yyyy-MM-dd),Name,CountryCode,UserDomain,EmailAddress,DaystoExpire,ExpiresOn"
    }
} # End Logging Check

# Clear Variables
if ($dcs){clear-variable dcs, users}

# Import AD Module
Import-Module ActiveDirectory

# Discover all DCs in forest
$domains = (get-adforest $adforest).domains
$domains.remove($domainstoexclude)

foreach ($d in $domains)
{
    $dcs += (get-ADDomainController -Discover -Domain $d).hostname
}

# Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
# This iterates through the list of DCs, as pwdLastSet is not in the GC by default so
# we can't simply query the GC for all our users
foreach($adserver in $dcs)
{
    $users += get-aduser -filter {(UserPrincipalName -like '*') -and (mail -like '*')} -server $adserver -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress, countryCode, UserPrincipalName  |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }
}

$DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

# Process Each User for Password Expiry
foreach ($user in $users)
{
    $Name = $user.Name
    $country = $user.countrycode
    $emailaddress = $user.emailaddress
    $passwordSetDate = $user.PasswordLastSet
    $PasswordPol = (Get-AduserResultantPasswordPolicy $user)

    #get domain of user by reading and stripping UPN
    $userdomain = $user.UserPrincipalName.substring($user.UserPrincipalName.indexof("@") + 1)

    # Check for Fine Grained Password
    if (($PasswordPol) -ne $null)
    {
        $maxPasswordAge = ($PasswordPol).MaxPasswordAge
    }
    else
    {
        # No FGP set to Domain Default
        $maxPasswordAge = $DefaultmaxPasswordAge
    }

  
    $expireson = $passwordsetdate + $maxPasswordAge
    $today = (get-date)
    $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days
        
    # Set Greeting based on Number of Days to Expiry.

    # Check Number of Days to Expiry
    $messageDays = $daystoexpire

    if (($messageDays) -ge "1")
    {
        switch -regex ($country) 
            { 
                '124|840|36|554' {$messageDays = "in " + "$daystoexpire" + " days"} 
                '76' {$messageDays = "em " + "$daystoexpire" + " dias"} 
                '156' {$messageDays = "$daystoexpire" + " 天后"}
                '392' {$messageDays = "あと" + "$daystoexpire" + "日で"} 
                '410' {$messageDays = "안에" + "$daystoexpire" + " 날짜"}
                default {$messageDays = "in " + "$daystoexpire" + " days"}
            }
    }
    else
    {
        switch -regex ($country) 
            { 
                '124|840|36|554' {$messageDays = "today"}
                '76' {$messageDays = "hoje"} 
                '156' {$messageDays = "今天"}
                '392' {$messageDays = "本日で"}
                '410' {$messageDays = "오늘"}
                default {$messageDays = "today"}
            }
    }

    # Email Subject Set Here
    switch -regex ($country) 
    { 
        '124|840|36|554' {$subject="Your password will expire $messageDays"}  
        '76' {$subject="Sua senha vai expirar $messageDays"} 
        '156' {$subject="提醒:您的密码将在$messageDays 过期"}
        '392' {$subject="$messageDays パスワード期限満了"}
        '410' {$subject="당신의 비밀번호가 만료되면 $messageDays"} 
        default {$subject="Your password will expire $messageDays"}
    }
    
    # Country Code Quick Reference
    # 124=Canada  840=US 36=Australia 554=New Zealand
    # 76=Brazil
    # 156=China
    # 392=Japan
    # 410=Korea
    # 710=South Africa
  
    # Email Body Set Here, Note You can use HTML, including Images.
    switch -regex ($country) 
    { 
        '124|124|840|124|36|124|554|710' {$body = "
                        Dear $name,
                        <p> Your Password for your account in the domain $userdomain will expire $messageDays.<br>
                        To change your password on a PC press CTRL+ALT+Delete and choose Change Password.<br>
                        If you connect in remotely or do not use a company provided device, you may need to use
                        alternate methods to change your network password.<br><br>
                        As a reminder, a valid password will meet these requirements:<br><br>
                        <ul><li>Not contain the user's account name or parts of the user's full name that exceed two consecutive characters</li>
                        <li>Be at least ten characters in length<br>
                        <li>Contain characters from three of the following four categories:<br>
                            <ul><li>English uppercase characters (A through Z)</li>
                            <li>English lowercase characters (a through z)</li>
                            <li>Base 10 digits (0 through 9)</li>
                            <li>Non-alphabetic characters (for example, !, $, #, %)</li></ul>
                        <li>Last  password change was more than 30 days ago</li>
                        <li>Different from the last 4 passwords</li></ul><br>
                        <p>Thanks for helping to keep the company secure.<br><br>
                        IT</P>"
                  }  
        '76' {$body = "
                        Caro $name,
                        <p> Sua senha do domínio $userdomain vai expirar em $messageDays.<br> 
                        <p>Obrigado por ajudar a manter segura.<br><br>
                        IT</P>"
                  } 
        '156' {$body = "
                        $name, 您好!
                        <p> 您的域账号密码将在$messageDays 过期。<br>
                        如需更改密码请在电脑上按下 CTRL+ALT+Delete 并选择&#8220;更改密码&#8221;.<br><br>
                        IT</P>"
                  }
        '392' {$body = "
                        $name 様,
                        <p> ドメイン $userdomain におけるあなたのアカウントのパスワードが、$messageDays 期限満了となります。 <br>
                        IT部門</P>"
                  }
        '410' {$body = "
                        $name,~에게
                        <p> 도메인 $userdomain에서 당신의 계정에 대한 비밀번호가 만료가되면 $messageDays 일 지나서 만료가 되면,<br>
                        IT </P>"
                  }
        default {$body = "
                        Dear $name,
                        <p> Your Password for your account in the domain $userdomain will expire $messageDays.<br>
                        To change your password on a PC press CTRL+ALT+Delete and choose Change Password.<br>
                        If you connect in remotely or do not use a company provided device, you may need to use
                        alternate methods to change your network password.<br><br>
                        As a reminder, a valid password will meet these requirements:<br><br>
                        <ul><li>Not contain the user's account name or parts of the user's full name that exceed two consecutive characters</li>
                        <li>Be at least ten characters in length<br>
                        <li>Contain characters from three of the following four categories:<br>
                            <ul><li>English uppercase characters (A through Z)</li>
                            <li>English lowercase characters (a through z)</li>
                            <li>Base 10 digits (0 through 9)</li>
                            <li>Non-alphabetic characters (for example, !, $, #, %)</li></ul>
                        <li>Last  password change was more than 30 days ago</li>
                        <li>Different from the last 4 passwords</li></ul><br>
                        <p>Thanks for helping to keep our company secure.<br><br>
                        IT</P>"
                  }
    }

   
    # If Testing Is Enabled - Email Administrator
    if (($testing) -eq "Enabled")
    {
        $emailaddress = $testRecipient
    } # End Testing

    # If a user has no email address listed
    if (($emailaddress) -eq $null)
    {
        $emailaddress = $testRecipient    
    }# End No Valid Email

    # Send Email Message
    # This is where you want to set the number of days away from expiration for the email notification to be sent to the user
    # In the example below we send an email on the day it is expiring 0, and also 1, 3, 10, and 21 days away from expiration.
    if ($daystoexpire -eq "0" -or $daystoexpire -eq "1" -or $daystoexpire -eq "3" -or $daystoexpire -eq "10" -or $daystoexpire -eq "21")
    {
         # If Logging is Enabled Log Details
        if (($logging) -eq "Enabled")
        {
            Add-Content $logfile "$date,$Name,$country,$userdomain,$emailaddress,$daystoExpire,$expireson" 
        }
        # Send Email Message
        # Encode as UTF8 for US/AUS/CA/NZL users
        if (($country -eq '124') -or ($country -eq '840') -or ($country -eq '36') -or ($country -eq '554') -or ($country -eq '0'))
        {
        Send-Mailmessage -Encoding UTF8 -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High
        }
        else
        # Encode as unicode for all other country codes
        {
        Send-Mailmessage -Encoding Unicode -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High  
        }
    } # End Send Message
    
} # End User Processing

# End

No comments: