In Exchange Server administration, one of the most common reporting needs is listing all Distribution Groups together with their members. This information is especially important during audit processes, migration planning, mail flow analysis, group cleanup, permission reviews, and general Exchange documentation.
Although it is possible to check Distribution Group membership manually from the Exchange Admin Center, this method is not practical in environments with many groups. A much faster and more reliable method is to use Exchange Management Shell and export the required information into a CSV file.
With the PowerShell script below, you can export all On-Prem Exchange Server Distribution Groups together with their members in a structured CSV format.
The script has been tested and confirmed to provide accurate data.
What Does This Script Do?
This script retrieves all Distribution Groups in the Exchange organization and checks the members of each group one by one.
The output includes both group information and member information.
The exported CSV file contains the following columns:
| Column | Description |
|---|---|
| GroupName | Display name of the Distribution Group |
| GroupAlias | Alias of the group |
| GroupPrimarySMTP | Primary SMTP address of the group |
| GroupType | Type of the group |
| MemberName | Display name of the group member |
| MemberAlias | Alias of the member |
| MemberSMTP | Primary SMTP address of the member |
| MemberType | Recipient type of the member |
This makes it easy to analyze Distribution Group membership using Microsoft Excel or another reporting tool.
PowerShell Script
Run the following script in Exchange Management Shell:
$Out = "C:\Temp\Exchange_Distribution_Groups_Members.csv"
$Groups = Get-DistributionGroup -ResultSize Unlimited
$Result = foreach ($Group in $Groups) {
$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue
if ($Members) {
foreach ($Member in $Members) {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = $Member.DisplayName
MemberAlias = $Member.Alias
MemberSMTP = $Member.PrimarySmtpAddress
MemberType = $Member.RecipientType
}
}
}
else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}
}
$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8
Write-Host "Export completed: $Out"
How the Script Works
The first line defines the output path:
$Out = "C:\Temp\Exchange_Distribution_Groups_Members.csv"
In this example, the CSV file will be created under the C:\Temp directory. Before running the script, make sure that this folder exists. If the folder does not exist, the export process may fail.
Next, the script retrieves all Distribution Groups from the Exchange organization:
$Groups = Get-DistributionGroup -ResultSize Unlimited
The -ResultSize Unlimited parameter is important because Exchange cmdlets may return a limited number of results by default. With this parameter, all Distribution Groups in the environment are included.
Then, the script processes each group one by one:
$Result = foreach ($Group in $Groups) {
For every Distribution Group, the script retrieves its members:
$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue
The -ErrorAction SilentlyContinue parameter prevents the script from stopping completely if a specific group causes an error. This can happen because of permission issues, unresolved objects, or special group conditions.
Handling Groups with Members
If the Distribution Group has members, the script writes each member as a separate row in the CSV file.
For example, if a Distribution Group contains 25 members, the CSV output will contain 25 rows for that group. The group information will be repeated on each row, while the member information will be different.
This format is very useful for reporting because it allows you to filter and analyze the data easily in Excel.
For example, you can quickly answer questions such as:
- Which users are members of a specific Distribution Group?
- Which groups contain a particular user?
- Are there nested groups inside Distribution Groups?
- Are there mail-enabled security groups in the membership?
- Are there empty or unused Distribution Groups?
Handling Empty Distribution Groups
One useful feature of this script is that it does not skip empty groups.
If a Distribution Group has no members, the script still adds the group to the CSV file, but the member-related fields remain empty.
This helps you identify unused, empty, or forgotten Distribution Groups in the Exchange environment.
The relevant part of the script is:
else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}
This is especially useful during cleanup or migration preparation projects.
CSV Export Process
At the end of the script, the collected data is exported to a CSV file:
$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8
The -NoTypeInformation parameter prevents PowerShell from adding object type information to the beginning of the CSV file. This keeps the file clean and ready for Excel.
The -Encoding UTF8 parameter is also important, especially if group names or user names contain non-English characters. It helps preserve special characters correctly in the exported file.
Finally, the script displays a completion message:
Write-Host "Export completed: $Out"
Output File
After the script completes, the CSV file will be created at the following location:
C:\Temp\Exchange_Distribution_Groups_Members.csv
When opened in Excel, the file will contain columns similar to the following:
GroupName, GroupAlias, GroupPrimarySMTP, GroupType, MemberName, MemberAlias, MemberSMTP, MemberType
You can then use Excel filters, sorting, pivot tables, or search functions to analyze the data.
Important Notes Before Running the Script
This script should be executed from Exchange Management Shell, not from a standard PowerShell window.
If you run it in a normal PowerShell session without the Exchange cmdlets loaded, you may receive errors such as:
Get-DistributionGroup is not recognized
The account running the script must also have sufficient Exchange permissions. In most environments, one of the following roles is usually required:
Recipient Management
View-Only Organization Management
Organization Management
In large Exchange environments, the script may take some time to complete. This depends on the number of Distribution Groups and the number of members in each group.
What If the C:\Temp Folder Does Not Exist?
If the C:\Temp directory does not exist, you can create it manually or run the following command:
New-Item -Path "C:\Temp" -ItemType Directory -Force
You can also modify the script to create the folder automatically.
Example:
$OutFolder = "C:\Temp"
$Out = "$OutFolder\Exchange_Distribution_Groups_Members.csv"
if (!(Test-Path $OutFolder)) {
New-Item -Path $OutFolder -ItemType Directory -Force | Out-Null
}
This ensures that the output folder exists before the CSV export begins.
Improved Version of the Script
The following version checks whether the output folder exists and creates it automatically if needed:
$OutFolder = "C:\Temp"
$Out = "$OutFolder\Exchange_Distribution_Groups_Members.csv"
if (!(Test-Path $OutFolder)) {
New-Item -Path $OutFolder -ItemType Directory -Force | Out-Null
}
$Groups = Get-DistributionGroup -ResultSize Unlimited
$Result = foreach ($Group in $Groups) {
$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue
if ($Members) {
foreach ($Member in $Members) {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = $Member.DisplayName
MemberAlias = $Member.Alias
MemberSMTP = $Member.PrimarySmtpAddress
MemberType = $Member.RecipientType
}
}
}
else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}
}
$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8
Write-Host "Export completed: $Out" -ForegroundColor Green
This version is more practical because it prevents export errors caused by a missing output folder.
Nested Group Membership
In some Exchange environments, a Distribution Group may contain another Distribution Group or a Mail-Enabled Security Group as a member. This is called nested group membership.
This script does not expand nested group members recursively.
For example, if Group-A contains Group-B, the script lists Group-B as a member of Group-A. However, it does not automatically list the users inside Group-B under Group-A.
This behavior is often useful because it clearly shows the real membership structure. However, if you need a fully expanded recursive membership report, the script must be modified accordingly.
Dynamic Distribution Groups
This script is designed for standard Distribution Groups.
Dynamic Distribution Groups work differently. Their membership is not manually assigned. Instead, members are calculated dynamically based on recipient filters.
Because of this, Dynamic Distribution Group membership cannot be listed in the same way as standard Distribution Groups.
For Dynamic Distribution Groups, you need to evaluate the recipient filter and retrieve the matching recipients separately.
Common Use Cases
This script is useful in many Exchange administration scenarios, including:
- Exchange migration preparation
- Microsoft 365 migration planning
- Distribution Group documentation
- Audit and compliance reporting
- Group membership review
- Mail flow troubleshooting
- Cleanup of unused or empty groups
- Identifying nested group structures
- Reviewing mail-enabled security groups
- User offboarding processes
- Disaster recovery documentation
- Active Directory and Exchange inventory studies
For organizations planning to migrate from On-Prem Exchange Server to Microsoft 365, exporting Distribution Group memberships before the migration is a very important preparation step.
Common Errors and Troubleshooting
1. Get-DistributionGroup Is Not Recognized
This usually means the script was executed in a standard PowerShell window instead of Exchange Management Shell.
To resolve this, run the script from Exchange Management Shell.
2. The CSV File Is Not Created
The most common reason is that the C:\Temp folder does not exist.
Create the folder using:
New-Item -Path "C:\Temp" -ItemType Directory -Force
Or use the improved version of the script that creates the folder automatically.
3. Some Groups Appear Without Members
There may be several reasons for this:
- The group is actually empty.
- The group is a Dynamic Distribution Group.
- The account running the script does not have enough permissions.
- The group contains unresolved or deleted objects.
- The membership is based on nested groups.
4. Special Characters Are Not Displayed Correctly in Excel
The script uses UTF-8 encoding, which usually handles special characters correctly. However, depending on Excel regional settings, characters may still appear incorrectly.
In that case, import the CSV file into Excel using:
Data > From Text/CSV
Then select UTF-8 encoding during the import process.
In On-Prem Exchange Server environments, regularly reporting Distribution Group memberships is important for administration, auditing, cleanup, migration planning, and documentation.
With this PowerShell script, you can quickly export all Distribution Groups and their members into a CSV file. The result can be opened in Excel and analyzed easily using filters, sorting, and pivot tables.
Instead of checking groups manually one by one, this script provides a fast, reliable, and repeatable reporting method. It is especially useful in large Exchange environments where manual control is time-consuming and error-prone.
![[EN] Exporting Distribution Groups with Their Members in an On-Prem Exchange Server Environment](https://kadirkozan.com/wp-content/uploads/2026/03/exchange-server-1.png)
![[TR] Windows 11 Güncellemesi Sonrası Mavi Ekran veya LSASS.exe Çökmesi: “STATUS_IMAGE_CHECKSUM_MISMATCH”](https://kadirkozan.com/wp-content/uploads/2026/03/windows-11-150x150.jpg)