Because of this, I wrote a simple Powershell script that is scheduled to run every day and creates a list of user accounts which passwords will expire in less than 7 days and sends them an e-mail notification that they should change their password. Once a user receives this notification, he can use Outlook Web Access to change his password.
Some notes about the script:
- The script uses System.Globalization.CultureInfo object to format the date returned for Croatian region (hr-HR). If you come from US, you can change hr-HR in the script to en-US
- The $msg.Body property in the script contains HTML formatted text that user receives as an e-mail message body. You can modify this HTML code, for example, to include your company branding
- You can modify the $OU property so that script only scopes your external users, users from a specific department, etc.
- The script does not send e-mail to users whose passwords are already expired or who have "Password never expires" property set
- You can modify how many days are left until password expiry before you start notifying users. Currently, script notifies users whose passwords expire in less than 7 days.
You can modify the following line: $DaysToExpire.Days -lt 7 - The policy works with default domain password policy and with Password Settings Object, a feature of Windows Server 2008 Active Directory
- You must run the script on a domain controller or on a server with Remote Server Administration Tools installed
- You must change the variable $smtpServer to your internal mail server (usually Exchange Hub Transport server) that can send e-mails to your users
Here is the script:
Import-Module ActiveDirectory #System globalization $ci = New-Object System.Globalization.CultureInfo("hr-HR") #SMTP server name $smtpServer = "smtp.domain.local" #Creating SMTP server object $smtp = new-object Net.Mail.SmtpClient($smtpServer) #E-mail structure Function EmailStructure($to,$expiryDate,$upn) { #Creating a Mail object $msg = new-object Net.Mail.MailMessage $msg.IsBodyHtml = $true $msg.From = "administrator@domain.com" $msg.To.Add($to) $msg.Subject = "Password expiration notice" $msg.Body = "<html><body><font face='Arial'>This is an automatically generated message from Service Provider Exchange service.<br><br><b>Please note that the password for your account $upn will expire on $expiryDate.</b><br><br>Please change your password immediately or at least before this date as you will be unable to access the service without contacting your administrator.</font></body></html>" return $msg } #Set the target OU that will be searched for user accounts $OU = "OU=Users,DC=domain,DC=local" $ADAccounts = Get-ADUser -LDAPFilter "(objectClass=user)" -searchbase $OU -properties PasswordExpired, PasswordNeverExpires, PasswordLastSet, Mail, Enabled | Where-object {$_.Enabled -eq $true -and $_.PasswordNeverExpires -eq $false} Foreach ($ADAccount in $ADAccounts) { $accountFGPP = Get-ADUserResultantPasswordPolicy $ADAccount if ($accountFGPP -ne $null) { $maxPasswordAgeTimeSpan = $accountFGPP.MaxPasswordAge } else { $maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge } #Fill in the user variables $samAccountName = $ADAccount.samAccountName $userEmailAddress = $ADAccount.Mail $userPrincipalName = $ADAccount.UserPrincipalName if ($ADAccount.PasswordExpired) { Write-host "The password for account $samAccountName has expired!" } else { $ExpiryDate = $ADAccount.PasswordLastSet + $maxPasswordAgeTimeSpan Write-host "The password for account $samAccountName expires on: $ExpiryDate" $TodaysDate = Get-Date $DaysToExpire = $ExpiryDate - $TodaysDate #Write-Host $DaysToExpire.Days if ($DaysToExpire.Days -lt 7) { $expiryDate = $expiryDate.ToString("d",$ci) #Generate e-mail structure and send message $msg = EmailStructure $userEmailAddress $expiryDate $userPrincipalName $smtp.Send($msg) Write-Host "The expiration notification e-mail was sent to $userEmailAddress" } } }