-
-
Save geegeek/8d2926145e8eeae898bd1cde9cbdb043 to your computer and use it in GitHub Desktop.
Revisions
-
cloudcap10 revised this gist
May 30, 2022 . 3 changed files with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes.File renamed without changes.File renamed without changes. -
cloudcap10 revised this gist
May 30, 2022 . 2 changed files with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes.File renamed without changes. -
cloudcap10 revised this gist
May 30, 2022 . No changes.There are no files selected for viewing
-
cloudcap10 revised this gist
May 18, 2022 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,7 @@ This version is a highly modified fork of the original **v1.4** by Robert Pearma New in this version: - Added Office 365 SMTP - Password-Expiration-Notifications-office365.ps1 - No SMTP Authentication - Password-Expiration-Notifications.ps1 - A SearchBase is required. - When logging, the CSV will always be overwritten. - Accounts with recently-expired passwords can be notified by specifying a "negativedays" value. -
cloudcap10 revised this gist
May 18, 2022 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,7 @@ Password-Expiration-Notifications.ps1 is a powerShell script designed to be run This version is a highly modified fork of the original **v1.4** by Robert Pearman from https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27. Pearman's 2.x version was completely re-written. New in this version: - Added Office 365 SMTP - Password-Expiration-Notifications-office365.ps1 - A SearchBase is required. - When logging, the CSV will always be overwritten. - Accounts with recently-expired passwords can be notified by specifying a "negativedays" value. -
cloudcap10 revised this gist
May 18, 2022 . 1 changed file with 242 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,242 @@ ################################################################################################################# # # Modified by: talzcloning # # Originally from v1.4 @ https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 # Robert Pearman (WSSMB MVP) # TitleRequired.com # Script to Automated Email Reminders when Users Passwords due to Expire. # # Requires: Windows PowerShell Module for Active Directory # ################################################################################################################## # Please Configure the following variables.... $SearchBase="DC=domain,DC=com" $smtpServer="smtp.office365.com" $SMTPPort = "587" $SMTPUsername = "[email protected]" $GetPassword = Get-Content "C:\temp\password.txt" #File with password has restricted access $SMTPPassword = $GetPassword | ConvertTo-SecureString -AsPlainText -Force $SMTPCredentials = new-object Management.Automation.PSCredential ($SMTPUsername,$SMTPPassword) $expireindays = 10 #number of days of soon-to-expire paswords. i.e. notify for expiring in X days (and every day until $negativedays) $negativedays = -1 #negative number of days (days already-expired). i.e. notify for expired X days ago $from = "Password Expiry <[email protected]>" $logging = $true # Set to $false to Disable Logging $logNonExpiring = $false $logFile = "C:\Logs\PS-pwd-expiry.csv" # ie. c:\mylog.csv $testing = $true # Set to $false to Email Users $adminEmailAddr = "[email protected]" #multiple addr allowed but MUST be independent strings separated by comma $sampleEmails = 1 #number of sample email to send to adminEmailAddr when testing ; in the form $sampleEmails="ALL" or $sampleEmails=[0..X] e.g. $sampleEmails=0 or $sampleEmails=3 or $sampleEmails="all" are all valid. # ################################################################################################################### # System Settings $textEncoding = [System.Text.Encoding]::UTF8 $date = Get-Date -format yyyy-MM-dd $starttime=Get-Date #need time also; don't use date from above Write-Host "Processing `"$SearchBase`" for Password-Expiration-Notifications" #set max sampleEmails to send to $adminEmailAddr if ( $sampleEmails -isNot [int]) { if ( $sampleEmails.ToLower() -eq "all") { $sampleEmails=$users.Count } #else use the value given } if (($testing -eq $true) -and ($sampleEmails -ge 0)) { Write-Host "Testing only; $sampleEmails email samples will be sent to $adminEmailAddr" } elseif (($testing -eq $true) -and ($sampleEmails -eq 0)) { Write-Host "Testing only; emails will NOT be sent" } # Create CSV Log if ($logging -eq $true) { #Always purge old CSV file Out-File $logfile Add-Content $logfile "`"Date`",`"SAMAccountName`",`"DisplayName`",`"Created`",`"PasswordSet`",`"DaystoExpire`",`"ExpiresOn`",`"EmailAddress`",`"Notified`"" } # Get Users From AD who are Enabled, Passwords Expire Import-Module ActiveDirectory $users = get-aduser -SearchBase $SearchBase -Filter {(enabled -eq $true) -and (passwordNeverExpires -eq $false)} -properties sAMAccountName, displayName, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress, lastLogon, whenCreated $DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge $countprocessed=${users}.Count $samplesSent=0 $countsent=0 $countnotsent=0 $countfailed=0 # Process Each User for Password Expiry foreach ($user in $users) { $dName = $user.displayName $sName = $user.sAMAccountName $emailaddress = $user.emailaddress $whencreated = $user.whencreated $passwordSetDate = $user.PasswordLastSet $sent = "" # Reset Sent Flag $PasswordPol = (Get-AduserResultantPasswordPolicy $user) # Check for Fine Grained Password if (($PasswordPol) -ne $null) { $maxPasswordAge = ($PasswordPol).MaxPasswordAge } else { # No FGPP set to Domain Default $maxPasswordAge = $DefaultmaxPasswordAge } #If maxPasswordAge=0 then same as passwordNeverExpires, but PasswordCannotExpire bit is not set if ($maxPasswordAge -eq 0) { Write-Host "$sName MaxPasswordAge = $maxPasswordAge (i.e. PasswordNeverExpires) but bit not set." } $expiresOn = $passwordsetdate + $maxPasswordAge $today = (get-date) if ( ($user.passwordexpired -eq $false) -and ($maxPasswordAge -ne 0) ) { #not Expired and not PasswordNeverExpires $daystoexpire = (New-TimeSpan -Start $today -End $expiresOn).Days } elseif ( ($user.passwordexpired -eq $true) -and ($passwordSetDate -ne $null) -and ($maxPasswordAge -ne 0) ) { #if expired and passwordSetDate exists and not PasswordNeverExpires # i.e. already expired $daystoexpire = -((New-TimeSpan -Start $expiresOn -End $today).Days) } else { # i.e. (passwordSetDate = never) OR (maxPasswordAge = 0) $daystoexpire="NA" #continue #"continue" would skip user, but bypass any non-expiry logging } #Write-Host "$sName DtE: $daystoexpire MPA: $maxPasswordAge" #debug # Set verbiage based on Number of Days to Expiry. Switch ($daystoexpire) { {$_ -ge $negativedays -and $_ -le "-1"} {$messageDays = "has expired"} "0" {$messageDays = "will expire today"} "1" {$messageDays = "will expire in 1 day"} default {$messageDays = "will expire in " + "$daystoexpire" + " days"} } # Email Subject Set Here $subject="$sName Windows Login password $messageDays" # Email Body Set Here, Note You can use HTML, including Images. $body=" <p>Your Active Directory password for your <b>$sName</b> account $messageDays. After expired, you will not be able to login until your password is changed.</p> <p>Please visit selfservice.example.com to change your password. Alternatively, on a Windows machine, you may press Ctrl-Alt-Del and select `"Change Password`".</p> <p>If you do not know your current password, <a href='https://selfservice.example.com/?action=sendtoken'>click here to email a password reset link</a>.</p> <p>Thank you,<br> Example.com Administrator<br> [email protected]<br> www.example.com/support/<br> </p> " # If testing-enabled and send-samples, then set recipient to adminEmailAddr else user's EmailAddress if (($testing -eq $true) -and ($samplesSent -lt $sampleEmails)) { $recipient = $adminEmailAddr } else { $recipient = $emailaddress } #if in trigger range, send email if ( ($daystoexpire -ge $negativedays) -and ($daystoexpire -lt $expireindays) -and ($daystoexpire -ne "NA") ) { # Send Email Message if (($emailaddress) -ne $null) { if ( ($testing -eq $false) -or (($testing -eq $true) -and ($samplesSent -lt $sampleEmails)) ) { try { Send-Mailmessage -smtpServer $smtpServer -from $from -to $recipient -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding -ErrorAction Stop -ErrorVariable err -port $SMTPPort -UseSsl -Credential $SMTPCredentials } catch { write-host "Error: Could not send email to $recipient via $smtpServer" $sent = "Send fail" $countfailed++ } finally { if ($err.Count -eq 0) { write-host "Sent email for $sName to $recipient" $countsent++ if ($testing -eq $true) { $samplesSent++ $sent = "toAdmin" } else { $sent = "Yes" } } } } else { Write-Host "Testing mode: skipping email to $recipient" $sent = "No" $countnotsent++ } } else { Write-Host "$dName ($sName) has no email address." $sent = "No addr" $countnotsent++ } # If Logging is Enabled Log Details if ($logging -eq $true) { Add-Content $logfile "`"$date`",`"$sName`",`"$dName`",`"$whencreated`",`"$passwordSetDate`",`"$daystoExpire`",`"$expireson`",`"$emailaddress`",`"$sent`"" } } else { #if ( ($daystoexpire -eq "NA") -and ($maxPasswordAge -eq 0) ) { Write-Host "$sName PasswordNeverExpires" } elseif ($daystoexpire -eq "NA") { Write-Host "$sName PasswordNeverSet" } #debug # Log Non Expiring Password if ( ($logging -eq $true) -and ($logNonExpiring -eq $true) ) { if ($maxPasswordAge -eq 0 ) { $sent = "NeverExp" } else { $sent = "No" } Add-Content $logfile "`"$date`",`"$sName`",`"$dName`",`"$whencreated`",`"$passwordSetDate`",`"$daystoExpire`",`"$expireson`",`"$emailaddress`",`"$sent`"" } } } # End User Processing $endtime=Get-Date $totaltime=($endtime-$starttime).TotalSeconds $minutes="{0:N0}" -f ($totaltime/60) $seconds="{0:N0}" -f ($totaltime%60) Write-Host "$countprocessed Users from `"$SearchBase`" Processed in $minutes minutes $seconds seconds." Write-Host "Email trigger range from $negativedays (past) to $expireindays (upcoming) days of user's password expiry date." Write-Host "$countsent Emails Sent." Write-Host "$countnotsent Emails skipped." Write-Host "$countfailed Emails failed." if ($logging -eq $true) { #sort the CSV file Rename-Item $logfile "$logfile.old" import-csv "$logfile.old" | sort ExpiresOn | export-csv $logfile -NoTypeInformation Remove-Item "$logFile.old" Write-Host "CSV File created at ${logfile}." #email the CSV and stats to admin(s) if ($testing -eq $true) { $body="<b><i>Testing Mode.</i></b><br>" } else { $body="" } $body+=" CSV Attached for $date<br> $countprocessed Users from `"$SearchBase`" Processed in $minutes minutes $seconds seconds.<br> Email trigger range from $negativedays (past) to $expireindays (upcoming) days of user's password expiry date.<br> $countsent Emails Sent.<br> $countnotsent Emails skipped.<br> $countfailed Emails failed. " try { Send-Mailmessage -smtpServer $smtpServer -from $from -to $adminEmailAddr -subject "Password Expiry Logs" -body $body -bodyasHTML -Attachments "$logFile" -priority High -Encoding $textEncoding -ErrorAction Stop -ErrorVariable err -port $SMTPPort -UseSsl -Credential $SMTPCredential } catch { write-host "Error: Failed to email CSV log to $adminEmailAddr via $smtpServer" } finally { if ($err.Count -eq 0) { write-host "CSV emailed to $adminEmailAddr" } } } # End -
meoso revised this gist
Apr 12, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ ################################################################################################################# # # Password-Expiration-Notifications v20180412 # Highly Modified fork. https://gist.github.com/meoso/3488ef8e9c77d2beccfd921f991faa64 # # Originally from v1.4 @ https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 -
meoso revised this gist
Apr 12, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ ################################################################################################################# # # Password-Expiration-Notifications v20180329 # Highly Modified fork. https://gist.github.com/meoso/3488ef8e9c77d2beccfd921f991faa64 # # Originally from v1.4 @ https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 -
meoso revised this gist
Apr 12, 2018 . No changes.There are no files selected for viewing
-
meoso revised this gist
Apr 12, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ Password-Expiration-Notifications.ps1 is a powerShell script designed to be run on a schedule to automatically email Active Directory users of soon-to-expire and recently-expired passwords. This version is a highly modified fork of the original **v1.4** by Robert Pearman from https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27. Pearman's 2.x version was completely re-written. -
meoso revised this gist
Apr 12, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ Password-Expiration-Notifications.ps1 is a powerShell script designed to be run on a schedule to automatically email Active Directory users of upcoming password expirations and recently expired passwords. This version is a highly modified fork of the original **v1.4** by Robert Pearman from https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27. Pearman's 2.x version was completely re-written. New in this version: - A SearchBase is required. -
meoso revised this gist
Apr 12, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ Password-Expiration-Notifications.ps1 is a powerShell script designed to be run on a schedule to automatically email Active Directory users of upcoming password expirations and recently expired passwords. This version is a highly modified fork of the original **v1.4** by Robert Pearman from https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27. RPearman's 2.x version was completely re-written. New in this version: - A SearchBase is required. -
meoso revised this gist
Apr 12, 2018 . 2 changed files with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,8 +14,8 @@ # Please Configure the following variables.... $SearchBase="DC=EXAMPLE,DC=COM" $smtpServer="smtp.example.com" $expireindays = 7 #number of days of soon-to-expire paswords. i.e. notify for expiring in X days (and every day until $negativedays) $negativedays = -3 #negative number of days (days already-expired). i.e. notify for expired X days ago $from = "Administrator <[email protected]>" $logging = $true # Set to $false to Disable Logging $logNonExpiring = $false This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,7 +5,7 @@ This version is a highly modified fork of the original v1.4 by Robert Pearman fr New in this version: - A SearchBase is required. - When logging, the CSV will always be overwritten. - Accounts with recently-expired passwords can be notified by specifying a "negativedays" value. - Email attempts will handle basic errors. - Accounts with MaxPasswordAge 00:00:00 (never) are skipped. (Same as PasswordNeverExpires.) - Testing-mode will allow a specified number of sample notifications to be emailed to the Administrator(s). (Rather than defaulting to all expirations.) -
meoso revised this gist
Apr 12, 2018 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -41,8 +41,10 @@ if ( $sampleEmails -isNot [int]) { } #else use the value given } if (($testing -eq $true) -and ($sampleEmails -ge 0)) { Write-Host "Testing only; $sampleEmails email samples will be sent to $adminEmailAddr" } elseif (($testing -eq $true) -and ($sampleEmails -eq 0)) { Write-Host "Testing only; emails will NOT be sent" } # Create CSV Log -
meoso revised this gist
Mar 9, 2017 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -41,10 +41,8 @@ if ( $sampleEmails -isNot [int]) { } #else use the value given } if ($testing -eq $true) { Write-Host "Testing only; $sampleEmails email samples will be sent to $adminEmailAddr" } # Create CSV Log -
meoso revised this gist
Mar 1, 2017 . No changes.There are no files selected for viewing
-
meoso revised this gist
Mar 1, 2017 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -199,13 +199,14 @@ Write-Host "$countsent Emails Sent." Write-Host "$countnotsent Emails skipped." Write-Host "$countfailed Emails failed." if ($logging -eq $true) { #sort the CSV file Rename-Item $logfile "$logfile.old" import-csv "$logfile.old" | sort ExpiresOn | export-csv $logfile -NoTypeInformation Remove-Item "$logFile.old" Write-Host "CSV File created at ${logfile}." #email the CSV and stats to admin(s) if ($testing -eq $true) { $body="<b><i>Testing Mode.</i></b><br>" } else { -
meoso revised this gist
Mar 1, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -164,7 +164,7 @@ foreach ($user in $users) { $countnotsent++ } } else { Write-Host "$dName ($sName) has no email address." $sent = "No addr" $countnotsent++ } -
meoso revised this gist
Mar 1, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ ################################################################################################################# # # Password-Expiration-Notifications v20170301 # Highly Modified fork. https://gist.github.com/meoso/3488ef8e9c77d2beccfd921f991faa64 # # Originally from v1.4 @ https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 # Robert Pearman (WSSMB MVP) -
meoso revised this gist
Mar 1, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -119,9 +119,9 @@ foreach ($user in $users) { $body=" <p>Your Active Directory password for your <b>$sName</b> account $messageDays. After expired, you will not be able to login until your password is changed.</p> <p>Please visit selfservice.example.com to change your password. Alternatively, on a Windows machine, you may press Ctrl-Alt-Del and select `"Change Password`".</p> <p>If you do not know your current password, <a href='https://selfservice.example.com/?action=sendtoken'>click here to email a password reset link</a>.</p> <p>Thank you,<br> Example.com Administrator<br> -
meoso revised this gist
Mar 1, 2017 . 1 changed file with 13 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,13 @@ Password-Expiration-Notifications.ps1 is a powerShell script designed to be run on a schedule to automatically email Active Directory users of upcoming password expirations and recently expired passwords. This version is a highly modified fork of the original v1.4 by Robert Pearman from https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 New in this version: - A SearchBase is required. - When logging, the CSV will always be overwritten. - Accounts with recently expired passwords can be notified by specifying a "negativedays" value. - Email attempts will handle basic errors. - Accounts with MaxPasswordAge 00:00:00 (never) are skipped. (Same as PasswordNeverExpires.) - Testing-mode will allow a specified number of sample notifications to be emailed to the Administrator(s). (Rather than defaulting to all expirations.) - Processing information and basic statistics are written to console. - When logging, the CSV file and basic statistics will be emailed to the specified Administrator(s). -
meoso created this gist
Mar 1, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,235 @@ ################################################################################################################# # # Password-Expiration-Notifications v20170301 # Highly Modified fork. https://github.com/meoso # # Originally from v1.4 @ https://gallery.technet.microsoft.com/Password-Expiry-Email-177c3e27 # Robert Pearman (WSSMB MVP) # TitleRequired.com # Script to Automated Email Reminders when Users Passwords due to Expire. # # Requires: Windows PowerShell Module for Active Directory # ################################################################################################################## # Please Configure the following variables.... $SearchBase="DC=EXAMPLE,DC=COM" $smtpServer="smtp.example.com" $expireindays = 7 #number of days prior notice to email notification $negativedays = -3 #negative number of days (days already expired) to email notification $from = "Administrator <[email protected]>" $logging = $true # Set to $false to Disable Logging $logNonExpiring = $false $logFile = "c:\PS-pwd-expiry.csv" # ie. c:\mylog.csv $testing = $true # Set to $false to Email Users $adminEmailAddr = "[email protected]","[email protected]","[email protected]" #multiple addr allowed but MUST be independent strings separated by comma $sampleEmails = 1 #number of sample email to send to adminEmailAddr when testing ; in the form $sampleEmails="ALL" or $sampleEmails=[0..X] e.g. $sampleEmails=0 or $sampleEmails=3 or $sampleEmails="all" are all valid. # ################################################################################################################### # System Settings $textEncoding = [System.Text.Encoding]::UTF8 $date = Get-Date -format yyyy-MM-dd $starttime=Get-Date #need time also; don't use date from above Write-Host "Processing `"$SearchBase`" for Password-Expiration-Notifications" #set max sampleEmails to send to $adminEmailAddr if ( $sampleEmails -isNot [int]) { if ( $sampleEmails.ToLower() -eq "all") { $sampleEmails=$users.Count } #else use the value given } if (($testing -eq $true) -and ($sampleEmails -ge 0)) { Write-Host "Testing only; $sampleEmails email samples will be sent to $adminEmailAddr" } elseif (($testing -eq $true) -and ($sampleEmails -eq 0)) { Write-Host "Testing only; emails will NOT be sent" } # Create CSV Log if ($logging -eq $true) { #Always purge old CSV file Out-File $logfile Add-Content $logfile "`"Date`",`"SAMAccountName`",`"DisplayName`",`"Created`",`"PasswordSet`",`"DaystoExpire`",`"ExpiresOn`",`"EmailAddress`",`"Notified`"" } # Get Users From AD who are Enabled, Passwords Expire Import-Module ActiveDirectory $users = get-aduser -SearchBase $SearchBase -Filter {(enabled -eq $true) -and (passwordNeverExpires -eq $false)} -properties sAMAccountName, displayName, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress, lastLogon, whenCreated $DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge $countprocessed=${users}.Count $samplesSent=0 $countsent=0 $countnotsent=0 $countfailed=0 # Process Each User for Password Expiry foreach ($user in $users) { $dName = $user.displayName $sName = $user.sAMAccountName $emailaddress = $user.emailaddress $whencreated = $user.whencreated $passwordSetDate = $user.PasswordLastSet $sent = "" # Reset Sent Flag $PasswordPol = (Get-AduserResultantPasswordPolicy $user) # Check for Fine Grained Password if (($PasswordPol) -ne $null) { $maxPasswordAge = ($PasswordPol).MaxPasswordAge } else { # No FGPP set to Domain Default $maxPasswordAge = $DefaultmaxPasswordAge } #If maxPasswordAge=0 then same as passwordNeverExpires, but PasswordCannotExpire bit is not set if ($maxPasswordAge -eq 0) { Write-Host "$sName MaxPasswordAge = $maxPasswordAge (i.e. PasswordNeverExpires) but bit not set." } $expiresOn = $passwordsetdate + $maxPasswordAge $today = (get-date) if ( ($user.passwordexpired -eq $false) -and ($maxPasswordAge -ne 0) ) { #not Expired and not PasswordNeverExpires $daystoexpire = (New-TimeSpan -Start $today -End $expiresOn).Days } elseif ( ($user.passwordexpired -eq $true) -and ($passwordSetDate -ne $null) -and ($maxPasswordAge -ne 0) ) { #if expired and passwordSetDate exists and not PasswordNeverExpires # i.e. already expired $daystoexpire = -((New-TimeSpan -Start $expiresOn -End $today).Days) } else { # i.e. (passwordSetDate = never) OR (maxPasswordAge = 0) $daystoexpire="NA" #continue #"continue" would skip user, but bypass any non-expiry logging } #Write-Host "$sName DtE: $daystoexpire MPA: $maxPasswordAge" #debug # Set verbiage based on Number of Days to Expiry. Switch ($daystoexpire) { {$_ -ge $negativedays -and $_ -le "-1"} {$messageDays = "has expired"} "0" {$messageDays = "will expire today"} "1" {$messageDays = "will expire in 1 day"} default {$messageDays = "will expire in " + "$daystoexpire" + " days"} } # Email Subject Set Here $subject="Your password $messageDays" # Email Body Set Here, Note You can use HTML, including Images. $body=" <p>Your Active Directory password for your <b>$sName</b> account $messageDays. After expired, you will not be able to login until your password is changed.</p> <p>Please visit selfservice.example.com to change your password.</p> <p>If you do not know your current password, <a href='https://selfservice.example.com/?action=sendtoken'>click here to email a password reset link</a>. The email containing the reset link will be sent to your email address.</p> <p>Thank you,<br> Example.com Administrator<br> [email protected]<br> www.example.com/support/<br> </p> " # If testing-enabled and send-samples, then set recipient to adminEmailAddr else user's EmailAddress if (($testing -eq $true) -and ($samplesSent -lt $sampleEmails)) { $recipient = $adminEmailAddr } else { $recipient = $emailaddress } #if in trigger range, send email if ( ($daystoexpire -ge $negativedays) -and ($daystoexpire -lt $expireindays) -and ($daystoexpire -ne "NA") ) { # Send Email Message if (($emailaddress) -ne $null) { if ( ($testing -eq $false) -or (($testing -eq $true) -and ($samplesSent -lt $sampleEmails)) ) { try { Send-Mailmessage -smtpServer $smtpServer -from $from -to $recipient -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding -ErrorAction Stop -ErrorVariable err } catch { write-host "Error: Could not send email to $recipient via $smtpServer" $sent = "Send fail" $countfailed++ } finally { if ($err.Count -eq 0) { write-host "Sent email for $sName to $recipient" $countsent++ if ($testing -eq $true) { $samplesSent++ $sent = "toAdmin" } else { $sent = "Yes" } } } } else { Write-Host "Testing mode: skipping email to $recipient" $sent = "No" $countnotsent++ } } else { Write-Host "`n$dName ($sName) has no email address." $sent = "No addr" $countnotsent++ } # If Logging is Enabled Log Details if ($logging -eq $true) { Add-Content $logfile "`"$date`",`"$sName`",`"$dName`",`"$whencreated`",`"$passwordSetDate`",`"$daystoExpire`",`"$expireson`",`"$emailaddress`",`"$sent`"" } } else { #if ( ($daystoexpire -eq "NA") -and ($maxPasswordAge -eq 0) ) { Write-Host "$sName PasswordNeverExpires" } elseif ($daystoexpire -eq "NA") { Write-Host "$sName PasswordNeverSet" } #debug # Log Non Expiring Password if ( ($logging -eq $true) -and ($logNonExpiring -eq $true) ) { if ($maxPasswordAge -eq 0 ) { $sent = "NeverExp" } else { $sent = "No" } Add-Content $logfile "`"$date`",`"$sName`",`"$dName`",`"$whencreated`",`"$passwordSetDate`",`"$daystoExpire`",`"$expireson`",`"$emailaddress`",`"$sent`"" } } } # End User Processing $endtime=Get-Date $totaltime=($endtime-$starttime).TotalSeconds $minutes="{0:N0}" -f ($totaltime/60) $seconds="{0:N0}" -f ($totaltime%60) Write-Host "$countprocessed Users from `"$SearchBase`" Processed in $minutes minutes $seconds seconds." Write-Host "Email trigger range from $negativedays (past) to $expireindays (upcoming) days of user's password expiry date." Write-Host "$countsent Emails Sent." Write-Host "$countnotsent Emails skipped." Write-Host "$countfailed Emails failed." # sort the CSV file if ($logging -eq $true) { Rename-Item $logfile "$logfile.old" import-csv "$logfile.old" | sort ExpiresOn | export-csv $logfile -NoTypeInformation Remove-Item "$logFile.old" Write-Host "CSV File created at ${logfile}." if ($testing -eq $true) { $body="<b><i>Testing Mode.</i></b><br>" } else { $body="" } $body+=" CSV Attached for $date<br> $countprocessed Users from `"$SearchBase`" Processed in $minutes minutes $seconds seconds.<br> Email trigger range from $negativedays (past) to $expireindays (upcoming) days of user's password expiry date.<br> $countsent Emails Sent.<br> $countnotsent Emails skipped.<br> $countfailed Emails failed. " try { Send-Mailmessage -smtpServer $smtpServer -from $from -to $adminEmailAddr -subject "Password Expiry Logs" -body $body -bodyasHTML -Attachments "$logFile" -priority High -Encoding $textEncoding -ErrorAction Stop -ErrorVariable err } catch { write-host "Error: Failed to email CSV log to $adminEmailAddr via $smtpServer" } finally { if ($err.Count -eq 0) { write-host "CSV emailed to $adminEmailAddr" } } } # End