powershellactive-directoryget-aduser

Powershell Active Directory Account expiry email notification to manager


I have this PowerShell script that sends out emails to managers if the user's account is expiring within a certain amount of days, however, managers get a separate email for every user. Is there a way to send only one email with the list of users?

Import-Module ActiveDirectory

#Set our non-changing variables for the email
$From = "accountexpiry@company.com"
$CC = "helpdesk@company.com"
$SMTPServer = "mail.company.com"

#Get the start date, which defaults to today, and the end date which is based off the start date
$startDate = Get-Date
$endDate = $startDate.AddDays(7)

#Query AD for all the accounts between our dates and request for a couple additional properties
$Users = Get-ADUser -Filter {AccountExpirationDate -gt $startDate -and AccountExpirationDate -lt $endDate} -Properties AccountExpirationDate, Manager

#Loop through the query results
Foreach($User in $Users)
{

    #The $User.Manager is not a email address, but a Distinguished Name; to get the email we can pass it to Get-Aduser though
    $Manager = Get-ADUser $User.Manager -Properties EmailAddress

    #Set our dynamic variables
    $To = $Manager.EmailAddress
    $Subject = "Account Expiration Notification for " + $User.Name
    $Body = 
    "Hello,
    This notification is to inform you that the account for $($User.Name) will expire on $($User.AccountExpirationDate). 
    If you need to extend this, please contact HR and IT will process the request.

    Thank you,
    IT Help Desk"

    Send-MailMessage -To $To -From $From -Subject $Subject -SmtpServer $SMTPServer -Body $Body
}

Solution

  • As @thepip3r suggested in his comment, a good way to send just one email per Manager could be using Group-Object. Code below should do the trick, haven't tested it but I believe it should work.

    One thing to note is that, this code will assume there is always a list of users that will expire and will send the list of users using the following format:

    This notification is to inform you that the account for the following users are about to expire:
    - user.example1 expires on XX/XX/XXXX
    - user.example2 expires on XX/XX/XXXX
    - user.example3 expires on XX/XX/XXXX

    If you need to extend this, please contact HR and IT will process the request.

    If you want to change the wording of the email for when there is only one user and when there are more than one then you should work on some conditions for that.

    Code

    Import-Module ActiveDirectory
    
    #Set our non-changing variables for the email
    $mailProps = @{
        From = "accountexpiry@company.com"
        CC = "helpdesk@company.com"
        SMTPServer = "mail.company.com"
        BodyAsHTML = $true
    }
    
    #Get the start date, which defaults to today, and the end date which is based off the start date
    $startDate = Get-Date
    $endDate = $startDate.AddDays(7)
    
    #Query AD for all the accounts between our dates and request for a couple additional properties
    $props = @{
        Filter = "AccountExpirationDate -gt '$startDate' -and AccountExpirationDate -lt '$endDate'"
        Properties = 'AccountExpirationDate', 'Manager'
    }
    $Users = Get-ADUser @props
    
    # Save the body on a ScriptBlock for later use
    $bodyScriptBlock = {
        param([string[]]$UserList)
    @"
    Hello,</br>
    This notification is to inform you that the account for the following users are about to expire:</br>
    {0}</br></br>
    If you need to extend this, please contact HR and IT will process the request.</br>
    </br>
    Thank you,</br>
    IT Help Desk</br>
    "@ -f ($UserList -join '</br>')
    }
    
    # Group all users by their Manager
    $Users | Group-Object Manager | ForEach-Object {
        
        # Get this Manager's email address
        $managerEmail = (Get-ADUser $_.Name -Properties EmailAddress).EmailAddress
    
        # Create a string[] with the user's Name and their Account's Expiration Date
        $userList = foreach($user in $_.Group)
        {
            '- {0} expires on {1}' -f $user.Name, $user.AccountExpirationDate
        }
        
        # Execute the Body scriptblock passing this user's list
        $body = & $bodyScriptBlock -UserList $userList
    
        # Set the remaing values for Mail props
        $mailProps.To = $managerEmail
        $mailProps.Subject = "Account Expiration Notification for Managees" # ??? No idea what to put here
        $mailProps.Body = $body
    
        # Send the email with the list of users
        Send-MailMessage @mailProps
    }
    

    Email Example

    exampleEmail