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
@ccedrick
Copy link

@ALL

I wanted to test this script, it would really a big help for me. may I know if required to provision a Mail Server for the email notification?

Thanks and Best Regards!

@MadRegime
Copy link

@ALL

I wanted to test this script, it would really a big help for me. may I know if required to provision a Mail Server for the email notification?

Thanks and Best Regards!

Yes you do or a SMTP service

@MadRegime
Copy link

MadRegime commented Sep 10, 2021

@ALL ,

Thanks,

I used the script but getting below error

[....redacted.....]

Thanks and Best Regards.

Maybe you are not authorized to send mail via that mailsever

@CalebMeyer45
Copy link

@ALL

How can this code be adjusted to just set this up for one specific user in AD rather than every user?

@meoso
Copy link
Author

meoso commented Sep 15, 2021

@ALL

How can this code be adjusted to just set this up for one specific user in AD rather than every user?

weird request, but you change the filter specs for get-aduser
look at the line with $users = get-aduser -filter * [...] google cmdlet get-aduser

@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