Powershell Script to Notify Users of Expired or About to Expire Passwords in Active Directory.

So where I work we use AD for single sign on (sso) for many of our systems both Windows and Nix. Some of our users only access the Nix systems and are not actually on our domain. They have no way of knowing when their passwords are about to expire and when their passwords do expire they just can’t log in without any visible reason why. In order to address that I started looking around the net for a powershell script and found one over at Dan Penning Blog but it didn’t address all of my needs. So using Dan’s script as the basis for a new script I came up with the following.

Synopsis of Goal:
Email the User when their password is about to expire or has expired and Supply a URL Link to reset their password.
Notify the Admin of certain conditions

  • Users Have Expired Passwords And No Primary SMTP Address to notify them
  • Users Password’s is About To Expire That Have No Primary SMTP Address
  • Users With Expired Passwords – Purely to report on it
  • Users Password’s About To Expire
  • Users with no Expiration Date

And Supply the Admin with the Location of the User account in question in the report.

Other Notes:
Included Options in the script without major rewrite

  • Adjust timing to being alerting (default is at 10 days start sending alerts to the user.)
  • Admin report is optional
  • Admin report can be sorted by Password Expiration, First, or Last Name.
  • Alerting Users is optional
  • Assign self service URL
  • Adjustable From Address and Relay Mail Server.
  • Change Font size and style for majority of text
#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: Robert Stacks
# URL: RandomTechMinutia.wordpress.com
# Updated: 06/21/2012
# Version: 1.2
#
# Based on a script by Dan Penning http://danpenning.com
#
# Purpose:
# Powershell script to find out a list of users
# whose password is expiring within x number of days (as specified in $days_before_expiry).
# Email notification will be sent to them reminding them that they need to change their password.
#
# Requirements:
# Quest ActiveRoles cmdlets (http://www.quest.com/powershell/activeroles-server.aspx)
# Powershell 2.0 ~ may work in 1.0 but I haven't tested it.
#
# Script must be run as a user with Permission to view AD Attributes, Domain Admin for example.
#
#=====================================================================================================#
#Add Snapins
Add-PSSnapin "Quest.ActiveRoles.ADManagement" -ErrorAction SilentlyContinue

#Get todays date for use in the script
$date = Get-Date

#===========================#
#User Adjustable Variables  #
#===========================#

# How many Days Advanced Warning do you want to give?
$DaysOfNotice = 10

#Generate a Admin report?
$ReportToAdmin = $true
#$ReportToAdmin = $false

#Sort Report
#===========================#
# 0 = By OU
# 1 = First Name Ascending
# 2 = Last Name Ascending
# 3 = Expiration Date Ascending
# 4 = First Name Descending
# 5 = Last Name Descending
# 6 = Expiration Date Descending
#===========================#
$ReportSortBy=1

#Alert User?
#$AlertUser = $true
$AlertUser = $false

#URL for self Service
$URLToSelfService = "http://"

#Mail Server Variables
$FromAddress = "DoNotReply@yourdomain.com"
$RelayMailServer = "mail.yourdomain.com"
$AdminEmailAddress ="Admin@yourdomain.com"

# Define font and font size
# ` or \ is an escape character in powershell
$font = "<font size=`"3`" face=`"Calibri`">"

# List of users whose Password is about to expire. The following line can be added to limit OU's searched if so desired
#$users += Get-QADUser -SearchRoot 'DN' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}
#$users = Get-QADUser -SearchRoot 'OU= Company USERS,DC=contoso,DC=com' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}
#$users += Get-QADUser -SearchRoot 'OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}

# Search Whole Root
$users = Get-QADUser -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}

#===========================#
#Main Script                #
#===========================#

# Sort Report
Switch ($ReportSortBy)
{
'0' {$users}
'1' {$users = $users | sort {$_.FirstName}}
'2' {$users = $users | sort {$_.LastName}}
'3' {$users = $users | sort {$_.PasswordExpires}}
'4' {$users = $users | sort -Descending {$_.FirstName}}
'5' {$users = $users | sort -Descending {$_.LastName}}
'6' {$users = $users | sort -Descending {$_.PasswordExpires}}
}

if ($ReportToAdmin -eq $true)
{
#Headings used in the Admin Alert
$Title="<h1><u>Password Expiration Status and Alert Report</h1></u><h4>Generated on " + $date + "</h4>"
$Title+="<font color = red><h2><u>Admin Action Required</h2></u></font>"
$Title+="<font size=`"3`" color = red> An Admin needs to update these accounts so that users can be notified of pending or past password experation<br></font>"
$Title_ExpiredNoEmail="<h3><u>Users Have Expired Passwords And No Primary SMTP to Notify Them</h3></u>"
$Title_AboutToExpireNoEmail="<h3><u>Users Password's Is About To Expire That Have No Primary SMTP Address</h3></u>"
$Title2="<br><br><h2><u><font color= red>No Admin Action Required - Email Sent to User</h2></u></font>"
$Title_Expired="<h3><u>Users With Expired Passwords</h3></u>"
$Title_AboutToExpire="<h3><u>Users Password's About To Expire</h3></u>"
$Title_NoExpireDate="<h3><u>Users with no Expiration Date</u></h3>"
}
#For loop to report
foreach ($user in $users)
{

if ($user.PasswordExpires -eq $null)
{
$UsersList_WithNoExpiration += $user.Name + " (<font color=blue>" + $user.LogonName + "</font>) does not seem to have a Expiration Date on their account.<font color=Green> <br>OU Container: " + $user.DN + "</font> <br>"
}
Elseif ($user.PasswordExpires -ne $null)
{
#Calculate remaining days till Password Expires
$DaysLeft = (($user.PasswordExpires - $date).Days)

#Days till password expires
$DaysLeftTillExpire = [Math]::Abs($DaysLeft)

#If password has expired
If ($DaysLeft -le 0)
{
#If the users don't have a primary SMTP address we'll report the problem in the Admin report
if (($user.Email -eq $null) -and ($user.UserMustChangePassword -ne $true) -and ($ReportToAdmin -eq $true))
{
#Add it to admin list to report on it
$UserList_ExpiredNoEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password has expired " + $DaysLeftTillExpire + " day(s) ago</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}

#Else they have an email address and we'll add this to the admin report and email the user.
elseif (($user.Email -ne $null) -and ($user.UserMustChangePassword -ne $true) -and ($AlertUser -eq $True))
{
$ToAddress = $user.Email
$Subject = "Friendly Reminder: Your Corporate Password has expired."
$body = " "
$body = $font
$body += "Greetings, <br><br>"
$body += "This is a auto-generated email to remind you (<font color=blue> " + $user.Name + "</font>) that your Corporate Password for account - <font color=red>" + $user.LogonName + "</font> - has expired. <br><br>"
$body += "This means you will not be able to access any secured system hosted at the Corporate Offices.<br><br> You can log into " + $URLToSelfService + " "
$body += "and reset the password yourself, else you are welcome to contact the Service Desk by Phone for assistance."
$body += "<br><br><br><br>"
$body += " "
$body += "<h4>Never Share Your Password With Others!</h4>"
$body += "<h5>Message generated on: " + $date + ".</h5>"
$body += "</font>"

Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $user.Email -subject $Subject -BodyAsHtml  -body $body

}
if ($ReportToAdmin -eq $true)
{
#Add it to a list
$UserList_ExpiredHasEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password has expired " + $DaysLeftTillExpire + " day(s) ago</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
}
elseif ($DaysLeft -ge 0)
{
#If Password is about to expire but the user doesn't have a primary address report that in the Admin report
if (($user.Email -eq $null) -and ($user.UserMustChangePassword -ne $true) -and ($ReportToAdmin -eq $true))
{
#Add it to admin list
$UserList_AboutToExpireNoEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password is about to expire and has " + $DaysLeftTillExpire + " day(s) left</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
# If there is an email address assigned to the AD Account send them a email and also report it in the admin report
elseif (($user.Email -ne $null) -and ($user.UserMustChangePassword -ne $true) -and ($AlertUser -eq $True) )
{
#Setup email to be sent to user
$ToAddress = $user.Email
$Subject = "Notice: Your Corporate Password is about to expire."
$body = " "
$body = $font
$body += "Greetings, <br><br>"
$body += "This is a auto-generated email to remind you (<font color=blue> " + $user.Name + "</font>) that your Corporate Password for account - <font color=red>" + $user.LogonName + "</font> - will expire in </font color = red>" + $DaysLeftTillExpire +" Day(s). <br><br>"
$body += "This means you will not be able to access any secured system hosted at the Corporate Offices.<br><br> You can log into " + $URLToSelfService + " "
$body += "and reset the password yourself, else you are welcome to contact the Service Desk by Phone for assistance."
$body += "<br><br><br><br>"
$body += "<h4>Never Share Your Password With Others!</h4>"
$body += "<h5>Auto-Generated Message On: " + $date + ".</h5>"
$body += "</font>"

Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $user.Email -subject $Subject -BodyAsHtml  -body $body

}
if ($ReportToAdmin -eq $true)
{
#Add it to admin Report list
$UserList_AboutToExpire += $user.name + "  <font color=blue>(" + $user.LogonName + "</font>) password is about to expire and has " + $DaysLeftTillExpire + " day(s) left</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
}
}
} # End foreach ($user in $users)

if ($ReportToAdmin -eq $true)
{
If ($UserList_AboutToExpire -eq $null)  {$UserList_AboutToExpire = "No Users to Report"}
If ($UserList_AboutToExpireNoEmail -eq $null){ $UserList_AboutToExpireNoEmail = "No Users to Report"}
if ($UserList_ExpiredHasEmail -eq $null) {$UserList_ExpiredHasEmail = "No Users to Report"}
if ($UserList_ExpiredNoEmail -eq $null) {$UserList_ExpiredNoEmail = "No Users to Report"}
if ($UsersList_WithNoExpiration -eq $null) {$UsersList_WithNoExpiration = "No Users to Report"}

#Email Report to Admin
$Subject="Password Expiration Status for " + $date + "."
$AdminReport = $font + $Title + $Title_ExpiredNoEmail + $UserList_ExpiredNoEmail + $Title_AboutToExpireNoEmail + $UserList_AboutToExpireNoEmail + $Title_AboutToExpire + $UserList_AboutToExpire + $Title_Expired + $UserList_ExpiredHasEmail + $Title_NoExpireDate + $UsersList_WithNoExpiration + "</font>"
Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $AdminEmailAddress -subject $Subject -BodyAsHtml -body $AdminReport
}



Sample Email to the user.

Sample of Admin Report

Updated on May 1, 2012

Added feature to sort Admin report by First Name, Last Name, or Password Expiration Date.

Updated on June 21, 2012

Minor code revision to fix logic errors, still debugging/testing.

Advertisements

, ,

  1. #1 by Robert on March 21, 2012 - 8:38 pm

    If you have a question feel free to ask.

    • #2 by pawan on May 1, 2014 - 11:47 pm

      Hi, i wan t to apply this on Two OU can you tell me, how can i add this o specific two OU in this script.

  2. #3 by Cathi on April 30, 2012 - 6:17 pm

    I’d like to know how to sort the admin email report so that users about to expire, in particular, will be listed in the email from least amount of days before password expires to most.

    • #4 by Robert on April 30, 2012 - 7:28 pm

      Hi Cathi.

      Great question!

      I did not take into consideration sorting the report by name or days left when I originally wrote this script. That said, it shouldn’t be too hard to add that feature. Give me a few days to test and I’ll get back to you. Off the cuff I’m going to say we need to add a line of code just before line 096 that sorts the user list before the report.

      Something like

      $users = $users | sort -Descending $users.PasswordExpires
      

      You could also replace the .PasswordExpires with .Name if you wanted to sort by name. The only issue we might run into is the null value and if so the sort will have to occur after we test for null.

      Again I’ll do some testing over the next few days and get back to you on this and/or update the script to take this desired feature into account.

      Robert

    • #5 by pawan on December 29, 2013 - 10:36 am

      hi, i am getting don’t match error in ps3 and not able to run this script can you tell me . the error is

      Get-QADUser : The term ‘Get-QADUser’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:88 char:10

  3. #6 by Cathi on April 30, 2012 - 2:31 pm

    I just had a friend take a look at the script and he figured out how to do it. I just tested it and it works. I also added a sizelimit in case you have over 1000 users:

    $users = Get-QADUser -Searchroot ‘xxxxx/xxxxxx’ -Enabled -PasswordNeverExpires:$false -SizeLimit 0 | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))} | Sort-Object PasswordExpires

    • #7 by Robert on April 30, 2012 - 2:39 pm

      Yep there are several ways to handle that and what you did there should work perfectly. I had not realized there was a size limit with Get-QADUser I will make sure to add that to my list of things to update in this script. Thanks for the update!

  4. #8 by Cathi on April 30, 2012 - 2:38 pm

    I just had a friend take a look at the script and he figured out how to do it. I just tested it and it works. I also added a sizelimit in case you have over 1000 users:

    $users = Get-QADUser -Searchroot ’Domain/Users OU’ -Enabled -PasswordNeverExpires:$false
    -SizeLimit 0 | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))} | Sort-Object PasswordExpires

  5. #9 by Robert on May 1, 2012 - 3:20 pm

    Ok I’ve updated the script so you can now sort by First Name, Last Name, or Expiration Date of the Password. Line 064 is the attribute to adjust depending on how you want it to be sorted. If someone runs into a problem with the sort please let me know.

    Robert

  6. #10 by Bill on May 3, 2012 - 1:57 pm

    Hi Robert, I just tried out your script (tried Dan’s before but it stopped emailing for some reason) It doesn’t seem to be finding users whose password will expire when it emails me. See pic of email.

  7. #11 by Robert on May 3, 2012 - 9:14 pm

    Sure I’m happy to help, this shouldn’t be too hard to figure out. So if you can, open up a powershell prompt from the Domain Controller or run one as a Domain Admin. Then from the prompt run this command: ” Get-QAUser Username ” where username is the AD user you want to test a look up on. If that command does not return anything, you might not have enough rights to look up the information. If you get a error “command not found” my guess is that the Quest was not correctly installed. If it works we’ll move on to another test, but that command is the one that fetches users, lets check that 1st.

    If it works run this:
    Get-QADUser -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays(10))} > C:\ScriptTest.txt

    Open up the text file after its done and see if there is data in it, if so that part too is working if not again there might be something else we can look at.

    Start there and let me know what you find.

    Robert

  8. #12 by Cathi on May 4, 2012 - 9:33 am

    Robert – please remove my post with my domain info I entered accidentally – thank you

    • #13 by Robert on May 4, 2012 - 10:32 am

      I fixed your post to hide your domain info. Thanks for pointing that out to me.

  9. #14 by Todd on May 23, 2012 - 4:27 pm

    Robert – I have not been able to get your script to work. I have performed the Get-QADUser -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays(30))} > C:\ScriptTest.txt test and there is data. When I run an LDAP query on Enabled accounts that will expire in the next 30 days I get 7 accounts. When I run your script with $DaysOfNotice = 30 I get only two accounts in the admin report that DO NOT have email addresses and whose password will expire within 30 days. I know at least one user whose password wilI expire within 30 days who is not being reported. I have tried running this from a DC and locally on my laptop using the Windows Powershell ISE tool and both return the same results. It seems the script has changed from a few days ago? ? ? Any help would be appreciated.

    Todd

    • #15 by Robert on June 12, 2012 - 4:33 pm

      Todd,

      I apologize for not responding sooner. I’ve been in the process of switching jobs and getting my feet under me at my new place of work. I will take a look at the script over the next few days and see if I can determine what the problem is.

      Robert

    • #16 by Robert on June 21, 2012 - 8:46 am

      Todd – I changed a wee bit of the logic in my code. I realize its been a while but you may want to retest.

      Robert

  10. #17 by Aaron Parker on June 5, 2012 - 9:36 am

    It appears that when user alerting is turned off, the resulting admin report is incomplete. The admin report will only contain users who do not have a valid SMTP address populated in AD. The error appears to be introduced on line 146. The step that adds the user to the admin report is only triggered when user alerting is set to true. I believe that simply moving lines 148 – 152 outside the elseif statement they are in will fix the issue. We’re going to do some testing later today to find out for sure.

    Similar logic is also used on line 181. Same holds true here too, moving lines 183-187 outside the elseif statement they are in will probably fix the issue.

    Fantastic script though! Does exactly what we were looking to do in our organization.

    • #18 by Robert on June 12, 2012 - 4:33 pm

      Aaron,

      Thanks for pointing out the errors, I will fix and update in the next day or two.

      Robert

  11. #19 by fred08 on June 6, 2012 - 12:33 pm

    Hello, I have been running a Quest powershell script that is very similar to yours. I have since found out that it does not take into account any fine-grained password policy and not sure on how to “make it so”.
    Many thanks in advance for any assistance.

    • #20 by Robert on June 12, 2012 - 4:38 pm

      Fred,

      I’m not sure what you mean by taking into account fine-grained passwords. The script I wrote does not look at the password field at all, only the expiration data as well as the last changed date. If you can give me a little more detail about what you mean/expect I might be able to help.

      thanks,

      Robert

      • #21 by fred08 on June 14, 2012 - 10:27 am

        Thanks for the reply Robert. We have multiple password policies which complicates things, so a script that just looks at the password expiry doesn’t really work. There is the following cmdlet for MS Powershell but I can’t seem to make it work for Quest:
        Get-ADUserResultantPasswordPolicy. If you would like, I could send you my script however, I’m currently still researching this as I want to learn PS. Its all new to me.
        Cheers.

    • #22 by Aaron Parker on June 13, 2012 - 8:25 am

      Absolutely! We did correct the error by slightly modifying the logic and it seems to be working great. We did find one more error though on line 146. The portion ($user.UserMustChangePassword -eq $true), should be -ne instead of -eq.

      After fixing these two issues and modifying the verbiage for our environment, it’s been working great! I’ll gladly send over a fixed version of the script that we are using if you’d like to take a look at what we’ve done.

      • #23 by Robert on June 21, 2012 - 8:33 am

        Aaron,

        Sorry it has taken me a while to get back to you. I do see the logic error with the -eq vs the -ne, and I will update that in my script in just a moment. I also now see the issues with the errors one 146 and 181 and I will fix them shortly. I very much appreciate your feedback! You are also welcome to forward me a copy of your script I wouldn’t mind taking a look. My email address is robertatrandomtechminutia@gmail.com.

    • #24 by Robert on July 9, 2013 - 1:53 pm

      Fred, after considering this some more the best solution is to have one instance of this script running per Password Policy assuming its done by OU. You can define the Users the script checks in this section of the script # Search Whole Root.

      Robert

  12. #25 by Marc on June 11, 2012 - 5:59 pm

    Hi Robert, Thanks for such a complete script for notifying users of expired passwords. I’m curious if you or anyone else might be able to assist me in figuring out why the reporting feature is not working correctly in my environment. The Get-QADUser command works fine on it’s own and the proper users are returned, but the admin report and the individual user report both do not work correctly. The admin report only shows users with no expiration date for the password and the user report does not send at all.

    To clarify, I do get the Admin report so the issue is not in the SMTP config, but the reports do not contain the correct information even though the Get-QADUser command returns the proper accounts

    • #26 by Robert on June 12, 2012 - 4:37 pm

      Hey Marc,

      Sorry about that, it would appear that there is a logic error in my code which I updated a little while back when I added a feature. I call myself testing my code but apparently not.

      I will work to fix it over the next week and update it.

      thanks for your feedback,

      Robert

    • #27 by Robert on June 21, 2012 - 9:01 am

      Marc,

      I just updated the script, try the new version and let me know what happens.

      Robert

  13. #28 by Bryan Broooks on June 13, 2012 - 11:25 am

    Hey Robert, awesome script! Maybe you can help me out. The report I get is not matching the Get-QADuser command-let.

    Get-QADUser -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays
    10))}

    Name Type DN
    —- —- —
    FIRST LAST user CN=FIRST LAST,OU=Users,OU=Heli-Wiki,DC=heli-max,DC=net
    Support user CN=Support,OU=Service Accounts,OU=Administrative,DC=heli-max,DC=net
    logmein user CN=logmein,OU=Service Accounts,OU=Administrative,DC=heli-max,DC=net
    Quarantine user CN=Quarantine,OU=Service Accounts,OU=Administrative,DC=heli-max,DC=net
    HeliMax PostMaster user CN=HeliMax PostMaster,OU=Service Accounts,OU=Administrative,DC=heli-m…
    testuser user CN=testuser,OU=Users,OU=Heli-Wiki,DC=heli-max,DC=net
    New User user CN=New User,OU=Users,OU=Heli-Wiki,DC=heli-max,DC=net

    Only one user is showing up in the Report:

    Users Password’s About To Expire:
    FIRST LAST (FLAST) password is about to expire and has 1 day(s) left.
    OU Container: CN=FIRST LAST,OU=Users,OU=Heli-Wiki,DC=heli-max,DC=net

    • #29 by Robert on June 21, 2012 - 9:01 am

      Bryan,

      I just updated the script. Try the updated one and let me know what happens.

      Robert

    • #30 by pawan on December 29, 2013 - 10:05 am

      he,
      i am getting same error, can you tell me how i can fixed it server 2012 powershell 3.0

  14. #31 by Robert on June 21, 2012 - 9:00 am

    Script has been updated to fix some bugs. Thank you again Aaron for pointing them out.

    • #32 by bryanbrooks454 on June 21, 2012 - 9:19 am

      Thanks for your help!! I will test it out today! 🙂

  15. #33 by Nick dog on July 10, 2012 - 12:29 pm

    Excellent Script! When I run it though it shows a single user multiple times within the admin report. thoughts?

    • #34 by Robert on July 16, 2012 - 3:45 pm

      If you are running this from a script editor some of the variables might not be getting cleared out every time you run/test it. Most of the time I do not zero out my variables in the scripts so that might cause you to get duplicates. That is the only case I can think of off the top of my head.

  16. #35 by Mike Steinke on August 3, 2012 - 2:48 pm

    How can I run this against multiple domains in a forest? I would also like to not run it against the domain I am logged in with since we use a control domain for admin accounts. Thank you in advance!

  17. #36 by Mike Steinke on August 3, 2012 - 4:01 pm

    I figured it out, use Connect-QADService. Thanks, great script!

  18. #37 by Robert Benton on April 9, 2013 - 11:05 am

    Robert,

    Thanks for the script. I have searched several and yours is a complete run of everything I was looking for. I have one question.

    I am able to receive the admin report but the users do not receive the email. The 1st test I ran was on a user the admin report states as expiring in 5 days. I looked and no email to the user. The admin gets his report of the expiring user though.

    I then set the threshold to 30 days received more expiring users and still nothing on the users email. Running Exchange 2010 in local AD environment. The only change I had to make was since we have multiple departments I set the OU to only DC=mydomain,dc=com vs using a specific OU.

    I have 0 programming experience, but the script makes sense.

    Thanks

    RobertB

    • #38 by Robert on April 15, 2013 - 5:37 pm

      At the very top of the script did you change:
      #Alert User?
      #$AlertUser = $true
      $AlertUser = $false

      to

      #Alert User?
      $AlertUser = $true
      #$AlertUser = $false

      Robert

  19. #39 by Mark Fischer on April 15, 2013 - 2:59 pm

    Thanks for the useful script.

    I’m using sort feature with ‘Expiration Date Ascending'(3) but it doesn’t work with the following categories;

    – Users Have Expired Passwords And No Primary SMTP to Notify Them
    – Users With Expired Passwords

    Just for those it sorts in descending order instead of ascending.

    • #40 by Robert on April 15, 2013 - 6:01 pm

      Mark,

      If you run the same report with option 6 descending is the reverse true? In other words it sorts everything normally descending except those last two are ascending?

      Pretty sure I see what the problem is but I’ll need you to confirm if the above is true for me to be sure.

      Robert

      • #41 by Mark Fischer on April 16, 2013 - 2:43 am

        Hi Robert,

        Yes as you wrote if I use option 6 it reverse, it sorts everything descending except those last two are ascending.

        Thanks,

        Mark

  20. #42 by Mark Fischer on April 16, 2013 - 2:42 am

    Hi Robert,

    Yes as you wrote if I use option 6 it reverse, it sorts everything descending except those last two are ascending.

    Thanks,

    Mark

    • #43 by Robert on April 16, 2013 - 5:09 pm

      Mark,

      The issue is with the way the password expiration is sorted. I did a basic sort of the users before they go into the main loop to determine what action to take.

      In order to fix it I’ll need to rewrite the script so that rather than building the report in the main loop, I’ll have to passing the users to a variable and then create another loop to sort and then build the reports. At least for the users that have gone past the expiration date with or without a email address.

      It may take me a week or two to get to this as I have several major projects going on. But that’s the brunt of it.

      thanks,

      Robert

  21. #44 by Gary on June 20, 2013 - 6:31 pm

    I am having an issue that I suspect is related to fine grained password policy (FGGP). Accounts that fall under the default domain policy (max pw age = 90 days) report correctly. Those that are impacted by the FGGP (max pw age = 120) are showing that there account expired x-number of days ago. But yet there account is not going to expire for x-number days in the future.

    I see one other comment concerning FGGP dated June 6, 2012 and understand what you are saying about the fields you use but it seems like something is missing when it comes to accounts with FGGP applied to them compared to ones the fall under the default domain. Any help would be appreciated in understanding this.

    Thanks.

    • #45 by Robert on July 9, 2013 - 1:51 pm

      The best way to handle this is to have twoinstances of this script run daily. One for the guys set to 90 days and one set to 120. You can define the list of users reviewed by the script under # Search Whole Root section.

      Short of rebuilding the script to take into account password policies per OU that’s going to be your best option.

      Robert

  22. #46 by pawan on December 29, 2013 - 10:03 am

    hi, i am getting don’t match error in ps3 and not able to run this script can you tell me . the error is

    Get-QADUser : The term ‘Get-QADUser’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:88 char:10

  23. #48 by Tom on February 19, 2014 - 1:03 am

    Hi Thanks for the script! I’m about to use it in my organisation but i would like to make one change. With the URLtoSelfService part – is there a way to display a title saying “Self Service” rather than the full hyperlink in the email that is sent out to users?

    • #49 by Robert on February 19, 2014 - 8:24 am

      You should be able to replace

      $URLToSelfService = "http://"

      with something like

      $URLToSelfService = '<a href="http://www.site.com">Name of Site</a>'

      It should accept standard html markup. You may note I replaced the ” with ‘ because we want the inner ” around the site name.

      You may have to tinker with it to get it to work as I haven’t tested but I have done this before.

  24. #50 by Mato on April 30, 2014 - 6:23 am

    Perfect script, Thanks.
    For Unicode characters in mail you need to add this to script:
    #encoding of mail
    $enc = New-Object System.Text.utf8encoding

    And for all 3 Send-MailMessage you have to add -Encoding $enc. Like this:
    Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $user.Email -subject $Subject -BodyAsHtml -body $body -Encoding $enc

  25. #51 by Tom J on April 30, 2014 - 11:46 pm

    Hi, I am trying to implement this script within my organization but when testing – the alert comes to the test users every day instead of just once (7 days before password expiry). Any ideas? Thanks

    • #52 by Robert on May 7, 2014 - 9:17 am

      Pretty simple answer here. The script isn’t smart enough to know if it sent the user a email already. So if you run the script every day, then every day the user will get a email about their password nearing its expiration. Generally this is what is desired anyway.

      IE
      10 days till expiration user gets email about pw expiration in 10 days
      then the next day 9 days left
      day after that 8 days left etc

      Are you getting something different?

      Robert

  26. #53 by Tom J on April 30, 2014 - 11:53 pm

    Hi, I am using this script within my organization. Our pw policy is set for pw’s to expiry every 42 days. When I target an OU with a specific test user that I have created – it sends the notification email every day even though it has past the 42 days. Can anyone help?

    • #54 by pawan on May 1, 2014 - 11:43 pm

      first check expiry days policy in script and change it according to you

    • #55 by Robert on May 7, 2014 - 9:22 am

      See my above comment.

      You are sort of implying you have a user that doesn’t want to reset set their password and at the same time you don’t want to send them the email?

      If you really wanted you could create a flat database of sorts in a text file, have the script check to see if the user already has gotten a email and if so not send one to them the next day.

      IE users would get one email about expiring passwords only once ever. No reminders then just the one. This is generally counter to the idea the script help remind your users they need to reset passwords but if that is the right fit for your company/needs it can be done.

      It would take some doing but you could rewrite the script to do this.

      Robert

  27. #56 by Michael H on December 31, 2014 - 12:05 pm

    Great Script! Thanks. It works on Windows 8.1/ The Quest ActiveRoles module is tough to find these days. Luckily we have a copy of the MSI already downloaded from 2013.

  28. #58 by Will on July 24, 2015 - 10:55 am

    Does this work without the Quest tools?

    • #59 by Robert on July 24, 2015 - 1:36 pm

      The way its written today it will not. I wrote this before some of the newer powershell features where released and have not had a reason to go back and revisit. (I don’t work at the job where I rolled this out.) It might be possible to re-write part of it to do it without the Quest tools. Those tools are free however and don’t take any real resources on a Windows server.

  29. #60 by Kren on July 28, 2015 - 1:52 pm

    Hi, the script seems to run but I never receive the email report or email alerts.

    I am not receiving any error messages and I have tested the Send-MailMessage functionality.

    However, is an smtp relay server necessary? I am able to send messages from my localhost by omitting the smtp server information. If so, how can I do this using the script?

    • #61 by Robert on July 28, 2015 - 5:52 pm

      Yes the smtp relay server is needed for the very last step in the script is to send a email based on this line $RelayMailServer = “mail.yourdomain.com”

      The email is then sent over SMTP \ Port 25 without trying to authenticate to your email server. So the server where you run the scrip must be able to relay off your email server.

      Most emails systems have rules that allow/block relaying from specific hosts. If you have the Relay String configured but not getting email you might look on the email server. You can test to see if you are allowing relay by telneting from the server with the script to SMTP, just google test SMTP via telnet: One such example https://technet.microsoft.com/en-us/library/Aa995718%28v=EXCHG.65%29.aspx

      Another way you can test is to use the Send-mailmessage via powershell command line and test it directly. If you get the email it worked if not again it might be the mail server.

      Sorry for the long response there are a lot of variables that can come into play here. We didn’t even touch on the possibility that email is working and your AD setup is not working so you never get a email. I am sorry to say when I wrote this I didn’t write up a lot of error testing in the code.

      • #62 by Kren on July 29, 2015 - 8:06 am

        Thank you for the reply.

        I have tested using the Send-MailMessage using my “localhost, 127.0.0.1” as my smtp server because we use google apps for business and our email is through this service as well.

        however, when I attempt to use google as my smtp server it either fails at the credentials or I get a startTLS message although I have port 587 set as my delivery port.

        so can I do the same using my localhost as the relay server? I have tried but again never receive the email using your code.

        Thanks in advance.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: