Exchange Online administration

How to bulk add members to a distribution group

Add members to distribution groups from a CSV file with Exchange Online PowerShell, add people to 1 group in the Exchange admin centre, or run Add members on many groups in Altivane.

By the Published

To bulk add members to a distribution group, run Add-DistributionGroupMember for each group and member pair in a CSV file, after exporting the current members as your backup and skipping anyone already in the group. The cmdlet adds 1 member per call, and it cannot add a Microsoft 365 group or a user who is not mail-enabled. Check first that your account can change groups it does not own, which takes a more privileged role.

Choose the method that fits the job
MethodBest fit
PowerShellMany group and member pairs in a CSV file, with a backup of each group's members and a results file.
Admin centreAdding several people to 1 group, 1 group at a time.
AltivaneRecommended for bulk changes to items you choose from a list, with every result in a change log.

Before you start

Microsoft lists the Organization Management and Recipient Management role groups for distribution groups. The script adds -BypassSecurityGroupManagerCheck, so you need not own each group; Microsoft says that switch needs Organization Management or the Security Group Creation and Membership role. Remove it where you own the groups.

The examples change the tenant, so try them on 1 or 2 test groups first. Keep the CSV the script writes before it changes anything: it records who was in each group, and you need it to undo the change.

A distribution group can hold mailboxes, mail users, mail contacts and other mail-enabled groups. A dynamic distribution group has no member list to change.

Option 1

Bulk add members to a distribution group with PowerShell

List the pairs in ./group-members.csv, with a Group column and a Member column, each a name or an email address. These rows are made up.

CSV
Group,Member
sales@example.com,alex.morgan@example.com
sales@example.com,sam.lee@example.com
support@example.com,sam.lee@example.com

Install the module once, then run the script. It exports the current members of every group in the file first, then adds each person who is not already in the group. Add-DistributionGroupMember has a -WhatIf switch, so the script previews until you change $preview to $false.

PowerShell
# Install once, if the module is not already installed.
Install-Module ExchangeOnlineManagement -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
$preview = $true   # Change to $false to make the changes.
$rows = @(Import-Csv -Path './group-members.csv')
if ($rows.Count -eq 0) { throw 'group-members.csv has no rows.' }
Connect-ExchangeOnline -ShowBanner:$false
try {
    # 1. The backup: today's members of every group in the file, written before any change.
    $groups = @($rows.Group | Where-Object { $_ } | ForEach-Object { $_.Trim() } |
        Sort-Object -Unique)
    $members = @{}
    $unread = @{}
    $backup = @()
    foreach ($name in $groups) {
        try {
            $found = @(Get-DistributionGroupMember -Identity $name -ResultSize Unlimited)
            $members[$name] = @($found | ForEach-Object { "$($_.PrimarySmtpAddress)" })
            $backup += $found | Select-Object @{ Name = 'Group'; Expression = { $name } },
                Name, PrimarySmtpAddress, RecipientType
        } catch {
            $unread[$name] = $_.Exception.Message
        }
    }
    $backup | Export-Csv -Path './group-members-before.csv' -NoTypeInformation -Encoding utf8

    # 2. Add each person who is not already in the group. One failure does not stop the others.
    $results = @(foreach ($row in $rows) {
        $name = "$($row.Group)".Trim()
        $person = "$($row.Member)".Trim()
        try {
            if (-not $name -or -not $person) { throw 'The Group or Member cell is blank.' }
            if ($unread.ContainsKey($name)) { throw $unread[$name] }
            $recipient = @(Get-EXORecipient -Identity $person -ResultSize 2)
            if ($recipient.Count -ne 1) { throw "$person does not match exactly 1 recipient." }
            $address = "$($recipient[0].PrimarySmtpAddress)"
            if ($members[$name] -contains $address) {
                $result = 'Already a member'
            } else {
                $add = @{ Identity = $name; Member = $address; WhatIf = $preview
                          BypassSecurityGroupManagerCheck = $true }
                Add-DistributionGroupMember @add | Out-Null
                $members[$name] += $address
                $result = if ($preview) { 'Would add' } else { 'Added' }
            }
        } catch {
            $result = "Failed: $($_.Exception.Message)"
        }
        [pscustomobject]@{ Group = $name; Member = $person; Result = $result }
    })
    $results | Export-Csv -Path './group-members-results.csv' -NoTypeInformation -Encoding utf8
    $failed = @($results | Where-Object { $_.Result -like 'Failed*' }).Count
    Write-Output "$($results.Count) rows processed, $failed failed."
} finally {
    Disconnect-ExchangeOnline -Confirm:$false
}

Run it as it is first: group-members-results.csv says Would add for each person who would be added, and Already a member for those in the group. Then set $preview to $false and run it again. Only direct members count as already in the group. A row that matches no recipient, or more than 1, is recorded as a failure and the script goes on.

Option 2

Add members to a group in the admin centre

  1. Open the Exchange admin centre for the correct tenant.
  2. Go to Recipients > Groups > Distribution list, or Mail-enabled security for a security group.
  3. Select the group by clicking anywhere in its row, then open the Members tab.
  4. Under Members, select View all and manage members, then + Add members.
  5. Select the people to add, several at once if you like, then select Add and close the pane.

Microsoft's steps work on 1 group at a time, so this suits adding several people to 1 group. It cannot add a Microsoft 365 group or a user who is not mail-enabled.

Common questions

Why did a row fail?

The Result column says why. The usual causes are a name that matches no recipient or more than 1, a member the group cannot hold, such as a Microsoft 365 group, and an account without permission to change the group.

How do I undo it?

Run Remove-DistributionGroupMember -Identity sales@example.com -Member alex.morgan@example.com -Confirm:$false for each row that says Added, or remove the people in the admin centre. In Altivane, run Remove members on the same groups. The backup CSV lists who was in each group before the change.

How do I check the groups afterwards?

Export the members again and compare them with the backup, as in how to export distribution group members.

Microsoft references

Technical references checked on 20 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us