Send-MailMessage Get-ADUser Filter confusion

by Other Horse at 2013-03-12 05:49:31

Hi,

I’m making a script to get the users whose password is soon to expire.
I was happy with it at first, but want to enhance it a little if possible.

What I want to achieve:
Part one gets users whose pwd expires next day, part two is supposed to get users for the next day after based on those who are left out of the script before. But that does not work.

Part 1:
$date = ((Get-Date).AddDays(-89)).ToString()
$adr = Get-ADUser -Filter "(PasswordLastSet -lt '$date')" -Properties EMailAddress -SearchBase 'OU=UserAccounts,DC=TEST,DC=LOCAL' | Select-Object -ExpandProperty EmailAddress
ForEach ($address in $adr) {
Send-MailMessage -To $address -From noreply@test.local -Subject "Null" -Body $messagebody -BodyAsHtml -SmtpServer [hostname]
}



This works good, dont mind the -gt operator

Part 2:

$date = ((Get-Date).AddDays(-88)).ToString()
Foreach ($address in $adr) {
$adr2 = Get-ADUser -Filter "(PasswordLastSet -lt '$date' -AND EMailAddress -notlike '$address')" -Properties EMailAddress -SearchBase 'OU=UserAccounts,DC=TEST,DC=LOCAL' | Select-Object -ExpandProperty EmailAddress
}



So, when part 1 is run, the variable $adr contains x, y and z address.
Then I run part 2, and the variable $adr2 contains x and y.

Now, because the foreach works in the mail part of part 1 (it sends successfully to each of the emailaddresses from $adr with the $address variable), I would assume it would also work to filter out the emailaddresses from $adr, in $adr2.
I.e I expected $adr2 to be empty.


I think my brain figured out why this wouldn’t work:
I guess the problem is that the loop overwrites the $adr2 for each address.
So only the last address from $adr is ultimately filtered out from $adr2…

Any suggestions?
I didn’t get it to use the exact date to find the users, but if there is a way to do that, that’d be great and make things a litte simpler.



Thanks!
by MasterOfTheHat at 2013-03-12 07:15:05
Your brain is absolutely right! Because you have the assignment inside your foreach loop, you are overwriting $adr2 on each iteration of the loop. That means that $adr2 will contain everything that $adr contains except for the last address that was processed in the loop.

If I understand you correctly, you want a list of all users whose password expires "tomorrow" and then a list of all users whose password expires "the day after tomorrow". If that’s what you’re looking for, I don’t see how your filter is giving you the results you expect. Assuming your org uses a 90 day password policy, and assuming $date = (today - 90 days), then "(PasswordLastSet -gt ‘$date’)" will give you every user whose password has been reset within the last 90 days. That would be a list of everyone whose password expires between today and (today + 90 days).

Anyway, to get a list of users whose password will expire tomorrow, you would need to get a list of users whose password was set (today - 89 days) ago. To do that with Get-ADUser, modify the filter similar to the following, (I had to use 3/30/2013 so that I would actually get some results in my environment):
$89days = ((get-date '03/30/2013').adddays(-89)).ToString('d')
$88days = ((get-date '03/30/2013').adddays(-88)).ToString('d')

get-aduser -filter "(passwordlastset -gt '$89Days') -and (passwordlastset -lt '$88days')" -property passwordlastset


Now to get the users whose password expires the day after tomorrow, use the same logic with $88days and $87days:
$88days = ((get-date '03/30/2013').adddays(-88)).ToString('d')
$87days = ((get-date '03/30/2013').adddays(-87)).ToString('d')

get-aduser -filter "(passwordlastset -gt '$88Days') -and (passwordlastset -lt '$87days')" -property passwordlastset


If I’ve misunderstood you completely and your example code is giving you pretty close to what you are looking for, then you could look at using Compare-Object to get the list.
$90days = ((get-date '03/31/2013').adddays(-90)).ToString('d')
$60days = ((get-date '03/30/2013').adddays(-60)).ToString('d')

$adr1 = Get-ADUser -Filter "(PasswordLastSet -gt '$90days')" -Properties EmailAddress | Select-Object EmailAddress
$adr2 = Get-ADUser -Filter "(PasswordLastSet -gt '$60days')" -Properties EmailAddress | Select-Object EmailAddress
Compare-Object -ReferenceObject $adr1 -DifferenceObject $adr2

In that example, $adr1 will be an array of email addresses for all users whose password was reset within the last 90 days and $adr2 will be an array of email addresses for all users whose password was reset within the last 60 days. To get a list of email addresses for all users whose password was reset in the 30 days between those 2 dates, use the Compare-Object cmdlet.
by Other Horse at 2013-03-12 08:10:48
Oops, sorry. I see I forgot the date part in part 1 (and 2 actually)…
And was a little unclear on the date part in general. Corrected it now.
(I had -gt just for testing in a small lab I set up, so wouldn’t get any users if I used -lt, since the users were newly created)

You understood me correctly the first time :slight_smile: [quote]"you want a list of all users whose password expires "tomorrow" and then a list of all users whose password expires "the day after tomorrow"."[/quote]

I’ll take a closer look at your suggestions when I get home, oh no, missed my bus…
Thanks so far! Good info.

edit.
Just tested the solution by using:
$89days = ((Get-Date).AddDays(-89).ToString(‘d’)
$88days = ((Get-Date).AddDays(-88).ToString(‘d’)
[…] -Filter "(PasswordLastSet -gt ‘$89days’ -AND PasswordLastSet -lt ‘$88days’)"
etc…

Seems to be working alright, thanks!