Hi ! I’ve recently found an interesting script from here
“Browse code samples | Microsoft Learn”
This script will email a user in the event that their password is due to expire in x number of days.
It was adopted in our company and works fine, however, when we have problems with format date inside the body of this notification, it is written in American English format i.e MM/dd/yyyy whereas it should be in European dd/MM/YYY HH:mm tt.
i.e
Your password will expire in 3 days at 01/31/2019 10:55:47 it should be 31/01.2019 10:55:47
I tried to put en-GB localisation into the script or use GET-DATE instead od “[datetime]::Now” but I get errors when the script is processed.
I tried to change ui-culture of the system, but it did not help
PS C:\Users\user> Get-UICulture
LCID Name DisplayName
PS C:\Users\USER> get-DATE
28 January 2019 10:46:37
Any Ideas how to do it ? I couldn’t find an answer on the technet. Please help, below is the script:
[pre]
<# .Synopsis Script to Automated Email Reminders when Users Passwords due to Expire. .DESCRIPTION Script to Automated Email Reminders when Users Passwords due to Expire. Robert Pearman / WindowsServerEssentials.com Version 2.9 August 2018 Requires: Windows PowerShell Module for Active Directory For assistance and ideas, visit the TechNet Gallery Q&A Page. http://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27/view/Discussions#contentAlternativley visit my youtube channel, https://www.youtube.com/robtitlerequired
Videos are available to cover most questions, some videos are based on the earlier version which used static variables, however most of the code
can still be applied to this version, for example for targeting groups, or email design.Please take a look at the existing Q&A as many questions are simply repeating earlier ones, with the same answers!
.EXAMPLE
PasswordChangeNotification.ps1 -smtpServer mail.domain.com -expireInDays 21 -from “IT Support <support@domain.com>” -Logging -LogPath “c:\logFiles” -testing -testRecipient support@domain.comThis example will use mail.domain.com as an smtp server, notify users whose password expires in less than 21 days, send mail from support@domain.com
Logging is enabled, log path is c:\logfiles
Testing is enabled, and test recipient is support@domain.com.EXAMPLE
PasswordChangeNotification.ps1 -smtpServer mail.domain.com -expireInDays 21 -from “IT Support <support@domain.com>” -reportTo myaddress@domain.com -interval 1,2,5,10,15This example will use mail.domain.com as an smtp server, notify users whose password expires in less than 21 days, send mail from support@domain.com
Report is enabled, reports sent to myaddress@domain.com
Interval is used, and emails will be sent to people whose password expires in less than 21 days if the script is run, with 15, 10, 5, 2 or 1 days remaining untill password expires.#>
param($smtpServer Enter Your SMTP Server Hostname or IP Address
[Parameter(Mandatory=$True,Position=0)]
[ValidateNotNull()]
[string]$smtpServer,Notify Users if Expiry Less than X Days
[Parameter(Mandatory=$True,Position=1)]
[ValidateNotNull()]
[int]$expireInDays,From Address, eg “IT Support <support@domain.com>”
[Parameter(Mandatory=$True,Position=2)]
[ValidateNotNull()]
[string]$from,
[Parameter(Position=3)]
[switch]$logging,Log File Path
[Parameter(Position=4)]
[string]$logPath,Testing Enabled
[Parameter(Position=5)]
[switch]$testing,Test Recipient, eg recipient@domain.com
[Parameter(Position=6)]
[string]$testRecipient,Output more detailed status to console
[Parameter(Position=7)]
[switch]$status,Log file recipient
[Parameter(Position=8)]
[string]$reportto,Notification Interval
[Parameter(Position=9)]
[array]$interval
)
###################################################################################################################Time / Date Info
$start = [datetime]::Now
$midnight = $start.Date.AddDays(1)
$timeToMidnight = New-TimeSpan -Start $start -end $midnight.Date
$midnight2 = $start.Date.AddDays(2)
$timeToMidnight2 = New-TimeSpan -Start $start -end $midnight2.DateSystem Settings
$textEncoding = [System.Text.Encoding]::UTF8
$today = $startEnd System Settings
Load AD Module
try{
Import-Module ActiveDirectory -ErrorAction Stop
}
catch{
Write-Warning “Unable to load Active Directory PowerShell Module”
}Set Output Formatting - Padding characters
$padVal = “20”
Write-Output “Script Loaded”
Write-Output “*** Settings Summary ***”
$smtpServerLabel = “SMTP Server”.PadRight($padVal," “)
$expireInDaysLabel = “Expire in Days”.PadRight($padVal,” “)
$fromLabel = “From”.PadRight($padVal,” “)
$testLabel = “Testing”.PadRight($padVal,” “)
$testRecipientLabel = “Test Recipient”.PadRight($padVal,” “)
$logLabel = “Logging”.PadRight($padVal,” “)
$logPathLabel = “Log Path”.PadRight($padVal,” “)
$reportToLabel = “Report Recipient”.PadRight($padVal,” “)
$interValLabel = “Intervals”.PadRight($padval,” ")Testing Values
if($testing)
{
if(($testRecipient) -eq $null)
{
Write-Output “No Test Recipient Specified”
Exit
}
}Logging Values
if($logging)
{
if(($logPath) -eq $null)
{
$logPath = $PSScriptRoot
}
}Output Summary Information
Write-Output “$smtpServerLabel : $smtpServer”
Write-Output “$expireInDaysLabel : $expireInDays”
Write-Output “$fromLabel : $from”
Write-Output “$logLabel : $logging”
Write-Output “$logPathLabel : $logPath”
Write-Output “$testLabel : $testing”
Write-Output “$testRecipientLabel : $testRecipient”
Write-Output “$reportToLabel : $reportto”
Write-Output “$interValLabel : $interval”
Write-Output ““.PadRight(25,””)Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
To target a specific OU - use the -searchBase Parameter -https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser
You can target specific group members using Get-AdGroupMember, explained here https://www.youtube.com/watch?v=4CX9qMcECVQ
based on earlier version but method still works here.
$users = get-aduser -filter {(Enabled -eq $true) -and (PasswordNeverExpires -eq $false)} -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress | where { $_.passwordexpired -eq $false }
Count Users
$usersCount = ($users | Measure-Object).Count
Write-Output “Found $usersCount User Objects”Collect Domain Password Policy Information
$defaultMaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy -ErrorAction Stop).MaxPasswordAge.Days
Write-Output “Domain Default Password Age: $defaultMaxPasswordAge”Collect Users
$colUsers = @()
Process Each User for Password Expiry
Write-Output “Process User Objects”
foreach ($user in $users)
{Store User information
$Name = $user.Name
$emailaddress = $user.emailaddress
$passwordSetDate = $user.PasswordLastSet
$samAccountName = $user.SamAccountName
$pwdLastSet = $user.PasswordLastSetCheck for Fine Grained Password
$maxPasswordAge = $defaultMaxPasswordAge
$PasswordPol = (Get-AduserResultantPasswordPolicy $user)
if (($PasswordPol) -ne $null)
{
$maxPasswordAge = ($PasswordPol).MaxPasswordAge.Days
}Create User Object
$userObj = New-Object System.Object
$expireson = $pwdLastSet.AddDays($maxPasswordAge)
$daysToExpire = New-TimeSpan -Start $today -End $ExpiresonRound Expiry Date Up or Down
if(($daysToExpire.Days -eq “0”) -and ($daysToExpire.TotalHours -le $timeToMidnight.TotalHours))
{
$userObj | Add-Member -Type NoteProperty -Name UserMessage -Value “today.”
}
if(($daysToExpire.Days -eq “0”) -and ($daysToExpire.TotalHours -gt $timeToMidnight.TotalHours) -or ($daysToExpire.Days -eq “1”) -and ($daysToExpire.TotalHours -le $timeToMidnight2.TotalHours))
{
$userObj | Add-Member -Type NoteProperty -Name UserMessage -Value “tomorrow”
}
if(($daysToExpire.Days -ge “1”) -and ($daysToExpire.TotalHours -gt $timeToMidnight2.TotalHours))
{
$days = $daysToExpire.TotalDays
$days = [math]::Round($days)
$userObj | Add-Member -Type NoteProperty -Name UserMessage -Value “in $days days.”
}
$daysToExpire = [math]::Round($daysToExpire.TotalDays)
$userObj | Add-Member -Type NoteProperty -Name UserName -Value $samAccountName
$userObj | Add-Member -Type NoteProperty -Name Name -Value $Name
$userObj | Add-Member -Type NoteProperty -Name EmailAddress -Value $emailAddress
$userObj | Add-Member -Type NoteProperty -Name PasswordSet -Value $pwdLastSet
$userObj | Add-Member -Type NoteProperty -Name DaysToExpire -Value $daysToExpire
$userObj | Add-Member -Type NoteProperty -Name ExpiresOn -Value $expiresOnAdd userObj to colusers array
$colUsers += $userObj
}Count Users
$colUsersCount = ($colUsers | Measure-Object).Count
Write-Output “$colusersCount Users processed”Select Users to Notify
$notifyUsers = $colUsers | where { $_.DaysToExpire -le $expireInDays}
$notifiedUsers = @()
$notifyCount = ($notifyUsers | Measure-Object).Count
Write-Output “$notifyCount Users with expiring passwords within $expireInDays Days”Process notifyusers
foreach ($user in $notifyUsers)
{Email Address
$samAccountName = $user.UserName
$emailAddress = $user.EmailAddressSet Greeting Message
$ExpiryTime=$user.ExpiresOn
$name = $user.Name
$messageDays = $user.UserMessageSubject Setting
$subject=“Your password will expire in $messageDays”
Email Body Set Here, Note You can use HTML, including Images.
examples here https://youtu.be/iwvQ5tPqgW0
$body ="
<font face=““verdana””>
Dear $name,
<p> Your password will expire at $ExpiryTime <br>
To change your password on a PC press CTRL ALT Delete and choose ‘Change Password’ <br>
<p>
<br>
Don’t forget to Update the password on your Mobile Devices as well!<br><p>Thanks<br>
</P>
IT Support
itsupport |
</font>"If Testing Is Enabled - Email Administrator
if($testing)
{
$emailaddress = $testRecipient
} # End TestingIf a user has no email address listed
if(($emailaddress) -eq $null)
{
$emailaddress = $testRecipient
}# End No Valid Email
$samLabel = $samAccountName.PadRight($padVal," ")
try{If using interval paramter - follow this section
if($interval)
{
$daysToExpire = [int]$user.DaysToExpirecheck interval array for expiry days
if(($interval) -Contains($daysToExpire))
{if using status - output information to console
if($status)
{
Write-Output “Sending Email : $samLabel : $emailAddress”
}Send message - if you need to use SMTP authentication watch this video https://youtu.be/_-JHzG_LNvw
Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding -ErrorAction Stop
$user | Add-Member -MemberType NoteProperty -Name SendMail -Value “OK”
}
else
{if using status - output information to console
No Message sent
if($status)
{
Write-Output “Sending Email : $samLabel : $emailAddress : Skipped - Interval”
}
$user | Add-Member -MemberType NoteProperty -Name SendMail -Value “Skipped - Interval”
}
}
else
{if not using interval paramter - follow this section
if using status - output information to console
if($status)
{
Write-Output “Sending Email : $samLabel : $emailAddress”
}
Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding -ErrorAction Stop
$user | Add-Member -MemberType NoteProperty -Name SendMail -Value “OK”
}
}
catch{error section
$errorMessage = $_.exception.Message
if using status - output information to console
if($status)
{
$errorMessage
}
$user | Add-Member -MemberType NoteProperty -Name SendMail -Value $errorMessage
}
$notifiedUsers += $user
}
if($logging)
{Create Log File
Write-Output “Creating Log File”
$day = $today.Day
$month = $today.Month
$year = $today.Year
$date = “$day-$month-$year”
$logFileName = “$date-PasswordLog.csv”
if(($logPath.EndsWith("")))
{
$logPath = $logPath -Replace “.$”
}
$logFile = $logPath, $logFileName -join ""
Write-Output “Log Output: $logfile”
$notifiedUsers | Export-CSV $logFile
if($reportTo)
{
$reportSubject = “Password Expiry Report”
$reportBody = “Password Expiry Report Attached”
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
}
}
}
$notifiedUsers | select UserName,Name,EmailAddress,PasswordSet,DaysToExpire,ExpiresOn | sort DaystoExpire | FT -autoSize$stop = [datetime]::Now
$runTime = New-TimeSpan $start $stop
Write-Output “Script Runtime: $runtime”End
[/pre]