Account Expiration Script

Greetings,

I am trying to find out what is the best way get this script working. This script is looking into accounts and notify users if their account will be expiring in 30 days and again alert them at 45 days before it is deleted.

I have to pull users from multiple locations: certain AD Groups and certain OU’s. Then it will determine their time period and email them.

Here is the script:

[pre]

############################################################################################################ # $smtpServer="smtp.server.coml" $from = "Administrator <noreply@server.com>" $DaysInactive = 45 $Inactive = @() $Groups = "Group1"; "Group2"; "Group3"; $OU = "OU=Standard Users,OU=Users,OU=OUNAME,OU=OUName,OU=OUName,DC=Name,DC=Name,DC=com" # ###################################################################################################################
#-- Get todays's date and go back how many day's inactive --#

$time = (Get-Date).AddDays(-($DaysInactive))

#-- Get list of users in AD Groups --#
ForEach ($Group in $Groups) {
$users = Get-ADGroupMember -Identity $Group -Recursive | Where objectclass -eq ‘user’
}

#-- Get list of users in AD specific OU --#
ForEach ($OUS in $OU) {
$usersfromou = Get-ADUser -SearchBase $OUS -Recursive | Where objectclass -eq ‘user’ | Out-GridView
}

$combined = $users + $usersfromou

$combined

#-- From the AD Group Users, we are pulling certain information --#

ForEach ($user in $combined) {
$Inactive += Get-ADUser -Identity $user -Properties LastLogonDate,Displayname,Enabled,EmailAddress | Where-Object { ($_.LastLogonDate -lt $time) } | Select-Object -Property DistinguishedName,samAccountName,Name,Displayname,Enabled,EmailAddress,LastLogonDate
}

$Inactive

#-- Set the Variables for Each AD Group User --#

ForEach ($user in $Inactive)
{
$Name = $user.Name
$emailaddresses = $user.EmailAddress
$LastLogonTime = $user.LastLogonDate.DateTime

#-- Email Subject Set Here --#
$subject = “Your account will expire soon”

#-- Email Body Set Here --#
$body ="
Dear $name,
<p> Your account will expire $messageDays<br>
To update your account, please complete the following steps:<br>
<p>1. Go to the following location: website <br>
2. At the bottom, you will see a icon called Account Login Validation, please click on this icon. <br>

If your account is disabled, please submit a ticket to enable your account.

<p>We have the following information:<br>
Email: $emailaddresses<br>
Last Date of Login: $LastLogonTime

<p>Thanks, <br>
Support Team
</P>"

Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddresses -subject $subject -body $body -bodyasHTML -priority High

}

[/pre]

 

A couple of questions:

  1. How can combine the $users and $usersfromou and make sure their is no duplicates? I tried $combined = $users + $usersfromou | select -uniq but that did not work.
  2. How can I add notification say for 5 days prior, 4 days prior and so forth?
  3. How can I separate the 30 days between the 45 days? For example, I want user to get an alert at day 27 saying that they account will be expiring but at day 44 say, it will be deleted.
I know this is a lot but I have been hitting dead ends for google searches and Jeff Hicks recommended that I reach out to this group.

 

Thanks for any help that is offered.

I am doing something similar at work to report on users that has not logged on for 90 days, but i am querying all AD controllers and an LDS server to be sure I am getting the correct value (since not all DC’s contain the most recent logonDate).

I am collecting information from all servers into one variable, then i am grouping and getting the newest logon date for users.
You could do something similiar, but since you only need to get unique users you only need to do select-object -unique after filling the variable with all users from both groups and OU’s.

I have not been able to test the example underneath, but in theory i think that should work the way you are looking for.

Example:

# Defining variable to put users in
$combined = @()

# Add all ADGroupMembers to the combined variable
ForEach ($Group in $Groups) {
$combined += Get-ADGroupMember -Identity $Group -Recursive | Where-Object {objectclass -eq 'user'} | Select-Object SamAccountName
}

# Add all ADusers from defines OUs to the combined variable
ForEach ($OUS in $OU) {
$combined += Get-ADUser -SearchBase $OUS -Recursive | Where-Object {objectclass -eq 'user'} | Select-Object SamAccountName
}

# Getting only unique users
$UniqueUser = $combined | Select-Object SamAccountName -Unique

# Then you can proceeed to get inactive users

For the last two questions I haven’t done it myself, but I would imagine you could uses todays date, then calculate the 27th day and the 45th day before you compare/select the users where LastLogonDate matches the calculated values for 27th and 45th day.

Probably not the best way to do it, and maybe not the most efficient, but should get the result you are looking for.

But keep in mind, depending on the number of DC’s in your environment, you can’t be sure that LastLogonDate on a single DC is the actual last time the user logged on since there is a delay in syncing this value between DC’s.
My head started hurting the last time i tried to wrap my head around how this affects a script like this.

line 7 should read

$Groups = "Group1", "Group2", "Group3"

and not

$Groups = "Group1"; "Group2"; "Group3";

Can you tell me why?

$users has objects that come from Get-ADGroupMember which are of type Microsoft.ActiveDirectory.Management.ADPrincipal (use Get-Member or the .GetType() method to see object type)

Get-ADUser does not have -Recursive parameter (are you using your own proxy function?)

$usersfromou has objects that came from Get-ADUser which are of the type Microsoft.ActiveDirectory.Management.ADUser

$users and $usersfromou hold different object types and cannot be added into one collection

What you need for your line to fetch inactives is the DN. Your $combined line can grab DN as the one common property of both objects that you need, as in:

$combined = $users.DistinguishedName + $usersfromou.DistinguishedName 

$Inactive = $combined | Get-ADUser | Where-Object { ($_.LastLogonDate -lt $time) } | 
    Select-Object -Property DistinguishedName,samAccountName,Name,Displayname,Enabled,EmailAddress,LastLogonDate

You can set a scheduled task to run this script and email notify at the required days