Skip to content

Instantly share code, notes, and snippets.

@meoso
Last active February 25, 2024 23:49
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save meoso/de56bdc68eced50a65d38e99e306ee42 to your computer and use it in GitHub Desktop.
Save meoso/de56bdc68eced50a65d38e99e306ee42 to your computer and use it in GitHub Desktop.
#################################################################################################################
#
# Version 1.4 February 2016
# Robert Pearman (WSSMB MVP)
# TitleRequired.com
# Script to Automated Email Reminders when Users Passwords due to Expire.
#
# 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#content
# Or Checkout my Youtube Channel - https://www.youtube.com/user/robtitlerequired
#
##################################################################################################################
# Please Configure the following variables....
$smtpServer="mail.server.com"
$expireindays = 21
$from = "Company Administrator <support@mycompany.com>"
$logging = "Enabled" # Set to Disabled to Disable Logging
$logFile = "<log file path>" # ie. c:\mylog.csv
$testing = "Enabled" # Set to Disabled to Email Users
$testRecipient = "testuser@company.com"
#
###################################################################################################################
# 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,Name,EmailAddress,DaystoExpire,ExpiresOn,Notified"
}
} # End Logging Check
# System Settings
$textEncoding = [System.Text.Encoding]::UTF8
$date = Get-Date -format ddMMyyyy
# End System Settings
# Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
Import-Module ActiveDirectory
$users = get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |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
$emailaddress = $user.emailaddress
$passwordSetDate = $user.PasswordLastSet
$PasswordPol = (Get-AduserResultantPasswordPolicy $user)
$sent = "" # Reset Sent Flag
# 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) -gt "1")
{
$messageDays = "in " + "$daystoexpire" + " days."
}
else
{
$messageDays = "today."
}
# Email Subject Set Here
$subject="Your password will expire $messageDays"
# Email Body Set Here, Note You can use HTML, including Images.
$body ="
Dear $name,
<p> Your Password will expire $messageDays<br>
To change your password on a PC press CTRL ALT Delete and choose Change Password <br>
<p>Thanks, <br>
</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
if (($daystoexpire -ge "0") -and ($daystoexpire -lt $expireindays))
{
$sent = "Yes"
# If Logging is Enabled Log Details
if (($logging) -eq "Enabled")
{
Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"
}
# Send Email Message
Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding
} # End Send Message
else # Log Non Expiring Password
{
$sent = "No"
# If Logging is Enabled Log Details
if (($logging) -eq "Enabled")
{
Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"
}
}
} # End User Processing
# End
@meoso
Copy link
Author

meoso commented Sep 15, 2021

Can we use below script as well for notification alert on password expiry.

Sorry i was not available to reply for many days. Since this is a completely different script you've posted, you should probably ask the source. It's not really polite to ask about a completely different script, although it is certainly similar.
That said, Get-ADDefaultDomainPasswordPolicy and Get-ADUser are not working because you need to import-module activedirectory.

@Belgithup
Copy link

I hope someone can help. I ran a test after modifying the script on windows server 2019 and got - error: could not send email to me@wlfs.com via smtp.office365.com. I went into the sender's account and unchecked Authenticated SMTP to see if helps but did not.

@meoso
Copy link
Author

meoso commented Mar 3, 2022

I hope someone can help. I ran a test after modifying the script on windows server 2019 and got - error: could not send email to me@wlfs.com via smtp.office365.com. I went into the sender's account and unchecked Authenticated SMTP to see if helps but did not.

i would suggest experimenting with simple Send-Mailmessage test-code using PowerShell ISE until you find a working result that you could integrate into the script. i suspect authentication is your issue, which is outside of the scope of this gist. here are some resources for Send-Mailmessage :

@StrongDoBongSoon
Copy link

StrongDoBongSoon commented Sep 14, 2022

Two questions: 1) How do I exclude certain email addresses or groups? 2)How do I stop the email from sending 1 day after the expiration date so it doesn't keep sending an email intermittently? Thank you.

This script is just a copy of Robert Pearman's original script. i prefer not to offer "support" for someone else's work.
However, i do have a highly modified version here: https://gist.github.com/meoso/3488ef8e9c77d2beccfd921f991faa64 which does account for question #2.
As far question #1, i would presume you could resolve this in a number of ways including modifying the original $user = get-aduser -Filter ... command , or maybe filtering $users by piping to a where-object filtering by group membership or by an OU. but this is something for you as the end-user to research how.

@Odakolo
Copy link

Odakolo commented Feb 28, 2023

Hi, How can I modify this code to send out notification to a security group?

@meoso
Copy link
Author

meoso commented Feb 28, 2023

Hi, How can I modify this code to send out notification to a security group?

maybe useful: https://activedirectoryfaq.com/2021/02/sending-e-mail-to-members-of-an-ad-group/

@Odakolo
Copy link

Odakolo commented Feb 28, 2023

Hi, How can I modify this code to send out notification to a security group?

maybe useful: https://activedirectoryfaq.com/2021/02/sending-e-mail-to-members-of-an-ad-group/

Thanks meoso, I know I have to edit this part of the code
Import-Module ActiveDirectory
**$users = get-aduser -filter *** -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$.Enabled -eq "True"} | where { $.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

But I am not sure of how to.
I have tried other things like "Get-ADGroupMember".
I want the new code to look in a particular security group and email the users in that security at the times I want them to be notified.

@meoso
Copy link
Author

meoso commented Feb 28, 2023

Hi, How can I modify this code to send out notification to a security group?

maybe useful: activedirectoryfaq.com/2021/02/sending-e-mail-to-members-of-an-ad-group

Thanks meoso, I know I have to edit this part of the code Import-Module ActiveDirectory **$users = get-aduser -filter *** -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$.Enabled -eq "True"} | where { $.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

But I am not sure of how to. I have tried other things like "Get-ADGroupMember". I want the new code to look in a particular security group and email the users in that security at the times I want them to be notified.

Try some variation of (Get-ADGroup -Identity $GroupName -properties members).Members | Get-ADUser,
where this format of (Get-ADGroup -Identity $GroupName -properties members).Members is a workaround for a 5000 user-count limitation existing in Get-ADGroupMember -Identity $GroupName

@Odakolo
Copy link

Odakolo commented Feb 28, 2023

**Try some variation of [...]

I tried it but it didnt work.

@meoso
Copy link
Author

meoso commented Feb 28, 2023

I tried it but it didnt work.

so

$users = (Get-ADGroup -Identity $GroupName -properties members).Members | get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

where $GroupName is set for your group, still fails?

EDIT: do not use -filter *

@Odakolo
Copy link

Odakolo commented Feb 28, 2023

$users = (Get-ADGroup -Identity $GroupName -properties members).Members | get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

Thanks, my bad. I missed something. After fixing it, it runs but it gets notification for everyone not the people in the specific security group I specified.

@meoso
Copy link
Author

meoso commented Mar 1, 2023

[...]] it runs but it gets notification for everyone not the people in the specific security group I specified.

try without the -filter *. This is an interesting use-case. maybe i should do some coding/testing myself.

@Odakolo
Copy link

Odakolo commented Mar 1, 2023

try without the -filter *. This is an interesting use-case. maybe i should do some coding/testing myself.

Thanks! I will try that and let you know.

@meoso
Copy link
Author

meoso commented Mar 1, 2023

@Odakolo , i just tested without -filter *; It works.

$users = (Get-ADGroup -Identity $GroupName -properties members).Members | get-aduser -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

image

where my group had 4 users. 1 of which with a soon to expire password.

seems like there would be a way to simplify this as well, rather than piping, but i'm happy enough with that line.

@Odakolo
Copy link

Odakolo commented Mar 2, 2023

@Odakolo , i just tested without -filter *; It works.

THANKS! it works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment