Question

So basically, what I have here is a script that will scan a CSV that it imports, and for every entry in the spreadsheet, except for people in the RANDOM.DOMAIN, it will find the managers email address and send an automated email to the manager telling them user XYZ is about to expire soon, and they need to do something about it.

If the managers email is unavailable for some reason, then it defaults to sending the email to me. This script works well.

The problem I am running into is, I want to make it so only one email is sent to each manager, despite multiple users (or entries) from the spreadsheet, list them as the manager.

I.e. if Joe Bloggs has a manager Aaron T and Jane Doe has the manager Aaron T, then Aaron T will get two emails, one email for each user.

MY QUESTION:

Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?

$datai = Import-Csv "Soon-to-expire User Accounts22.csv" | select 'Display Name',Manager,'Domain Name','Account Expiry Time'
Connect-QADService -Service another.DC | Out-Null
$expiringUsers = @{}



foreach ($i in $datai) {
        $dn = $i.'Display Name'
        $dn1 = $i.'Domain Name'
        $man = $i.'Manager'
        $aet = $i.'Account Expiry Time'
        $subject = "Account about to expire: $dn"



$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail

if ($man -eq "-" -or $man -like 'CN=*' -or $getmail -eq $null -or $man -eq "") {
$man = "Aaron T"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
}



if ($expiringUsers.Contains($emailAD)) {
  $expiringUsers[$emailAD]["dn"] += $dn += "`n"
  $expiringUsers[$emailAD]["aet"] += $aet += "`n"
  $expiringUsers[$emailAD]["man"] += $man += "`n"
} else {
  $expiringUsers[$emailAD] = @{
    #"dn1" = $dn1
    #"aet" = $aet
   #"man" = $man
  # "dn"  = @( $dn )
     }
  }
}


$expiringUsers | fc #as suggested


foreach ($emailAD in $expiringUsers.Keys) {
$dn  = $expiringUsers[$emailAD]["dn"]
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account/s About to Expire!"
$content = @"
Hi,
$dn `n
$dn1 `n
$man `n
$aet `n

$emailAD `n
Technology Services
 "@
 Send-MailMessage -from "aaron@website.com" `
-To $emailAD `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer "relay.server"


#using this as a test instead of sending mass emais all the time
Write-Host $content
}

UPDATED with the new script as requested.... still having issues.

Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?

Was it helpful?

Solution 2

So I finally decided to revisit this script, after many, many months. I'm get a little better at PowerShell and while I'm sure this isn't the most effective way to do it, this is something that works for me.

I've also changed the input method; it pulls the information directly from AD, instead of using a CSV file that used to be generated from an application called 'AD Manager Plus' (Hate it).

Remember, using Quest CMDlets here because we don't have a 2008 environment. (so using Get-QADUser instead of Get-ADuser)

FYI, I have only posted the code here which sorts out the data into separate tables - you can decide how you want to utilize those results. For our environment, I have it build an nice HTML table and body, then send it to the appropriate manager to deal with.

#user data input
$data = get-qaduser -SizeLimit 0 -includedproperties accountexpires | where {$_.AccountExpires -ne $null -and $_.AccountExpires -le ((Get-Date).AddDays(45)) }

#get a list of managers, unique.
$uniqueMan = $data | select Manager -Unique

#foreach manager from $uniqueman
Foreach ($manager in $uniqueman) {
    #create the array variable / clear it out for the next manager.
    $myarray = @()
            #foreach User found in in $data query
            Foreach ($user in $data) {

            #Search the $user's query for people with the same manager as that of the $uniqueman list.
            If ($user.Manager -eq $manager.Manager) {

                    #do what with the result.
                    #add the person to an array
                    $myarray += New-Object psobject -Property @{
                        Name = $user.'Name'
                        UserName = $user.'SAMAccountName'
                        AccountExpires = $user.'AccountExpires'
                        Manager = $user.Manager
                        }


            }


    #for testing, to output the results to an HTML file.
    #$myarray | ConvertTo-Html | Out-File ("C:\test\" + $manager.Manager + ".html")

        }


}

OTHER TIPS

For this you need to defer e-mail processing. Collect the users in a hashtable, e.g. by manager e-mail address:

...

$expiringUsers = @{}

foreach ($i in $datai) {
  If ($i.'Domain Name' -notmatch "RANDOM.DOMAIN") {
    ...
    if ($expiringUsers.Contains($emailAD)) {
      $expiringUsers[$emailAD]["dn"] += $dn
    } else {
      $expiringUsers[$emailAD] = @{
        "dn1" = $dn1
        "aet" = $aet
        "man" = $man
        "dn"  = @( $dn )
      }
    }
  }
}

and move the actual e-mail processing outside the loop:

foreach ($emailAD in $expiringUsers.Keys) {
  $dn1 = $expiringUsers[$emailAD]["dn1"]
  $man = $expiringUsers[$emailAD]["man"]
  $aet = $expiringUsers[$emailAD]["aet"]
  $subject = "Account about to expire: $($expiringUsers[$emailAD]["dn"])"
  $content = @"
Hi,
...
Technology Services
"@
  Send-MailMessage -from "Test Script - Powershell <email@test.com>" `
    -To "$emailAD" `
    -Subject $subject `
    -Body $content `
    -Priority high `
    -smtpServer servername
  Write-Host "Mail Sent to $man"
}

Note that for simplicity reasons the above code only records the expiry date of the first user. If you want the expiry date of each user recorded separately, you'll have to take additonal steps, e.g.

$expiringUsers[$emailAD]["expiry"] += @{
  "name" = $dn;
  "date" = $aet;
}

instead of

$expiringUsers[$emailAD]["dn"] += $dn
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top