I have an array of users and managers and I want to group by manager

I have an array of users and managers and I want to send 1 email to a manager with a list of their users. Currently my script sends 1 email to the manager for every user they manage, so in my example below john.doe a_)contessa,com receives 3 individual emails for his 3 users.
Goal:
james.bond a_)contessa,com will receive 1 email with the names Bob Barker and Jerry Springer in the email body.
john.doe a_)contessa.com will receive 1 email with the names Jerry Springer, John Holmes, and Joe Mama in the email body.
jane.mansfield a_)contessa,com will receive 1 email with the name Edit Bunker in the email body.

My array (example):

Manager                                User
-------                                ----
james.bond a_)contessa,com             bob barker
james.bond a_)contessa,com             Jerry Springer
john.doe a_)contessa,com               John Holmes
john.doe a_)contessa,com               Joe Mama
john.doe a_)contessa,com               Archie Bunker
jane.mansfield a_)contessa,com         Edith Bunker

Do you have a text or csv file containing your manager/user list? Will you paste the code you have tried? This can be solved using the Group-Object and Send-MailMessage cmdlets.

# Example 
$array = @"
Manager                                User
-------                                ----
james.bond a_)contessa,com             bob barker
james.bond a_)contessa,com             Jerry Springer
john.doe a_)contessa,com               John Holmes
john.doe a_)contessa,com               Joe Mama
john.doe a_)contessa,com               Archie Bunker
jane.mansfield a_)contessa,com         Edith Bunker
"@ -split "`n"

$mylist = 
$array.Trim().Where({$_ -notmatch '^-'}) -replace ' a_\)','@' -replace ',','.' -replace '\s{2,}',','

 $group = $mylist | ConvertFrom-Csv | Group-Object -Property Manager | 
 Select-Object Name, @{n='User';exp={$_.Group.User | Out-String}} | Format-List

Thank you for helping! Yes, I can export the array to a .csv file. Here is the code I am currently using. This sends 1 email for each expiring user to the their manager. So if the manager has 25 expiring user accounts, the manager will receive 25 emails. Yikes!

#Import AD Module
Import-Module ActiveDirectory
 
#Create warning dates for future account expiration
$days = 1
$WarnDate = (get-date).adddays($days).ToLongDateString()
$today=(Get-Date)

#Define some Variables
$usernames=[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$username= $usernames.substring(11 , $usernames.length - 11)
$MailSender = (Get-AdUser -Identity $Username -Properties * | Select -ExpandProperty Mail)
$CCMailrecipient = ""

write-host "`nUsername:" $username "`n"
$a = Read-Host -Prompt "Please enter your password" -assecurestring
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $a
$Password = $Credentials.GetNetworkCredential().Password

$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)

If ($domain.name -eq $null){
    write-host "`nERROR: Authentication failed - please verify your username and password." -ForegroundColor Red
    read-host -prompt "`nPress enter to close application."
	Exit
    }

$EmailStub1 = "Dear "
$Emailstub2 = ",<br><br>We wish to inform you of a time sensitive matter which requires your immediate attention. "
$EmailStub3 = "'s account expires on "
$EmailStub4 = "  and in order to avoid any inconvenience we kindly ask that you do one of the following as it applies to their status: <br><br>1) If they will be continuing employment please submit a <b><u>Incident ticket ASAP</u></b> requesting their account be extended and note in the ticket that you <b>APPROVE</b> the request.<br><br>2) If they are no longer employed, please submit an On-boarding/Off Boarding request to have the user removed from the system.<br><br>As always, we are here for you.<br><br>PLEASE DO NOT RESPOND TO THIS EMAIL."

$SMTPServer = '10.1.1.11'
#$Password = ($Filepath + $Username + 'EmailPassword.txt')
#$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, (Get-Content $Password | ConvertTo-SecureString)
$MailPassword = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, ($MailPassword | ConvertTo-SecureString)

#Find accounts that are enabled and expiring
$users = Get-ADUser -filter {(Enabled -eq $True) -and (PasswordNeverExpires -eq $False) -and (PasswordLastSet -gt 0) -and (accountExpires -ne 0) -and (accountExpires -ne 9223372036854775807)} -Properties "Name", "SamAccountName", "AccountExpirationDate" ,"accountExpires" | Select-Object -Property "Name", "SamAccountName", "AccountExpirationDate"
 
$Group = "SeniorLeadership"
$Executives = Get-ADGroupMember -Identity $group -Recursive | Get-ADUser -Properties Mail | Select-Object -ExpandProperty Mail

#check account expiration date and send email on match
$results = @()
foreach ($user in $users) {
   $MailRecipient = ""
   $MailRecipientFirstName=""
   If ($user.AccountExpirationDate) {
        $ExpiryDate=$user.AccountExpirationDate
        $DaysLeft=($ExpiryDate-$Today).days
        If ($DaysLeft -eq $days){
            $Mailrecipient = Get-ADUser (Get-ADUser $user.samaccountname -properties manager).manager -properties Mail | Select-Object -ExpandProperty Mail
            $MailRecipientFirstName = Get-ADUser (Get-ADUser $user.samaccountname -properties manager).manager -properties GivenName | Select-Object -ExpandProperty GivenName
            $Subject = "IMMEDIATE ACTION NEEDED - " + $user.name + "'s account expires " + $WarnDate
            $EmailBody = $EmailStub1, $MailRecipientFirstName, $Emailstub2, $user.name, $EmailStub3, $WarnDate, $EmailStub4 -join ''
            $i = ""
            ForEach ($Executive in $Executives){
                IF ($MailRecipient -eq $Executive){
                    $i = 1
                    $Member = $Executive
                    }
                }

            If (($MailRecipient) -and ($i -ne 1)) {write-host $user.name ' - ' $ExpiryDate ' - ' $Daysleft ' - ' $WarnDate ' - ' $Mailrecipient ' - ' $MailRecipientFirstName
                $Details = @{
                    UserName = $user.Name
                    Manager = $Mailrecipient
                    }
                    $results += New-Object PSObject -Property $details   
                }


            If (($MailRecipient) -and ($i -eq 1)) {Write-host $user.Name"'s manager," $Member "is an Executive."}
            If (!($MailRecipient)) {Write-host $user.name ' - HAS NO MANAGER ASSIGNED'}

            If (($MailRecipient) -and ($i -ne 1)) {Send-MailMessage -SmtpServer $SMTPServer -Credential $Cred -To $Mailrecipient -CC $CCMailRecipient -From $MailSender -Subject $Subject -Body $EmailBody -BodyAsHtml}
            }
        }
 }
$results | export-csv -Path $Filename -NoTypeInformation
$Results

The issue is caused by your for loop executing the send-mail cmdlet for each user rather than each manager. Export array to csv (1 manager column, 1 user column, each with a header) and run a loop for each manager like below.

$manager = Import-Csv .\manager.csv | Group-Object -Property Manager | 
Select-Object Name,@{n='User';exp={$_.Group.User | Out-String}}

foreach ($m in $manager){
    $EmailBody = $EmailStub1, $MailRecipientFirstName, $Emailstub2, 
    $m.User, $EmailStub3, $WarnDate, $EmailStub4 -join ''
    
    $splat = @{
        SmtpServer = $SMTPServer
        Credential = $Cred
        To = $m.Name 
        CC = $CCMailRecipient
        From = $MailSender
        Subject = $Subject
        Body = $EmailBody
        BodyAsHtml = $true        
    }
    Send-MailMessage @splat
}

Thank you very much! I will give it a try and let you know my results.

Hello. Your code worked perfectly! I will post my finished code shortly!

#Import AD Module
Import-Module ActiveDirectory
 
#Create warning dates for future account expiration
#$days can be set higher. 7 days would return accounts expiring 7 days from today.
$days = 1
$WarnDate = (get-date).adddays($days).ToLongDateString()
$today=(Get-Date)

#Define some Variables
$usernames=[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$username= $usernames.substring(11 , $usernames.length - 11)
$MailSender = (Get-AdUser -Identity $Username -Properties * | Select -ExpandProperty Mail)
$Temppath = $env:TEMP
$ManagerFile = $TempPath + '\manager.csv'

#Get user credentials with access to send emails
write-host "`nUsername:" $username "`n"
$a = Read-Host -Prompt "Please enter your password" -assecurestring
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $a
$Password = $Credentials.GetNetworkCredential().Password

#Checks credentials to make sure they are valid
$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)
If ($domain.name -eq $null){
    write-host "`nERROR: Authentication failed - please verify your username and password." -ForegroundColor Red
    read-host -prompt "`nPress enter to close application."
	Exit
    }

#format the email that will be sent
$Subject = 'IMMEDIATE ACTION NEEDED - User account(s) expiring on ' + $Warndate
$EmailStub1 = "Dear "
$Emailstub2 = ",<br>We wish to inform you of a time sensitive matter which requires your immediate attention.<br>The following user account(s) will be expiring on " + $Warndate + ":<br><br>"
$EmailStub4 = "<br>In order to avoid any inconvenience we kindly ask that you do one of the following as it applies to their status: <br>1) If they will be continuing employment please submit a <b><u>Incident ticket ASAP</u></b> requesting their account be extended and note in the ticket that you <b>APPROVE</b> the request.<br>2) If they are no longer employed, please submit an On-boarding/Off Boarding request to have the user removed from the system.<br>As always, we are here for you. Please reach out to us for any further assistance.<br><br>PLEASE DO NOT RESPOND TO THIS EMAIL."

#email server
$SMTPServer = '0.0.0.0'
$Username, (Get-Content $Password | ConvertTo-SecureString)
$MailPassword = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, ($MailPassword | ConvertTo-SecureString)

#Find accounts that are enabled and expiring
$users = Get-ADUser -filter {(Enabled -eq $True) -and (PasswordNeverExpires -eq $False) -and (PasswordLastSet -gt 0) -and (accountExpires -ne 0) -and (accountExpires -ne 9223372036854775807)} -Properties "Name", "SamAccountName", "AccountExpirationDate" ,"accountExpires" | Select-Object -Property "Name", "SamAccountName", "AccountExpirationDate"

# these variables are optional. For example, if you want to exclude a group(s) from receiving these emails, such as VIPs add them here
$Group = "YourCompanyExecutives"
$Executives = Get-ADGroupMember -Identity $group -Recursive | Get-ADUser -Properties Mail | Select-Object -ExpandProperty Mail

#check account expiration date and send email on match
$results = @()
foreach ($user in $users) {
   $MailRecipient = ""
   $MailRecipientFirstName=""
   If ($user.AccountExpirationDate) {
        $ExpiryDate=$user.AccountExpirationDate
        $DaysLeft=($ExpiryDate-$Today).days
        If ($DaysLeft -eq $days){
            $Mailrecipient = Get-ADUser (Get-ADUser $user.samaccountname -properties manager).manager -properties Mail | Select-Object -ExpandProperty Mail
            $MailRecipientFirstName = Get-ADUser (Get-ADUser $user.samaccountname -properties manager).manager -properties GivenName | Select-Object -ExpandProperty GivenName
            
#this is where your exclusion groups will be parsed out. If $i =1 it will skip sending an email.
#            $i = ""
#            ForEach ($Executive in $Executives){
#                IF ($MailRecipient -eq $Executive){
#                    $i = 1
#                    $Member = $Executive
#                    }
#                }

#Some additional clean up and some traps
            $j=""
            If (($MailRecipient) -and ($i -eq 1)) {
                Write-host $user.Name"'s manager," $Member "is an Executive."
                $j = 1
                }
            
            If (!($MailRecipient)) {
                Write-host $user.name ' - HAS NO MANAGER ASSIGNED'
                $j = 1
                }

#Creates the array of users and their managers. Note the <br>. When you format the email bodyashtml, this will put the users in a neat list within the email.
            If (($MailRecipient) -and ($i -ne 1) -and ($j -ne 1)) {write-host $user.name ' - ' $ExpiryDate ' - ' $Daysleft ' - ' $WarnDate ' - ' $Mailrecipient ' - ' $MailRecipientFirstName
                $Details = @{
                    User = $user.Name + '<br>'
                    Manager = $Mailrecipient
                    }
                $results += New-Object PSObject -Property $details   
                }         
          }
    }
}
#exports the array to a .csv then imports and groups users with their managers so that managers receive 1 email with a list of their users
If (Test-Path $ManagerFile) {
    Remove-Item $ManagerFile
    }
$results | export-csv -Path $ManagerFile -NoTypeInformation
$manager = Import-Csv $ManagerFile | Group-Object -Property Manager | Select-Object Name,@{n='User';exp={$_.Group.User | Out-String}}

If ($results){
    foreach ($M in $manager){
        $EmailBody = $EmailStub1, ($m.name.Substring(0,$m.name.IndexOf("."))), $Emailstub2, $m.User, $EmailStub4 -join ''
        $splat = @{
            SmtpServer = $SMTPServer
            Credential = $Cred
            To = $m.Name
            #To = $MailSender
            CC = $CCMailRecipient
            From = $MailSender
            Subject = $Subject
            Body = $EmailBody
            BodyAsHtml = $true        
        }
    Send-MailMessage @splat
    }
}

If (Test-Path $ManagerFile) {
    Remove-Item $ManagerFile
    } 

I know there may be fancier ways of doing this, but I wanted code that is the absolute bare minimum using the least amount of includes with the simplest logic. This is so ‘beginners’ such as myself can follow through it and understand it better. Special thanks to Random-CommandLine for the help!!!