A RecipientType -eq 'MailUser is not an external user. Thats a remote mailbox that represents the mailbox in Exchange Online for your internal users.
script runs for hours without any output
Hi All,
I am using an Exchange 2016 hybrid environment. I have a CSV file containing Exchange on-premises DL email addresses, including distribution lists and mail-enabled security groups. I want to export all the DLs that contain mail contacts, mail users, or external users to a CSV file. However, when I execute the script below, it runs for hours without producing any output. I am using this script in the on-premises Exchange environment. Additionally, I would like to fetch the same information for Exchange Online DLs as well. Please guide me.
# Import the CSV file containing distribution group names
$ExchangeDLs = Import-Csv -Path "C:\input.csv"
$DLsWithExtUsers = @()
foreach ($DL in $ExchangeDLs) {
# Get the distribution group by name from the CSV
$DistributionGroup = Get-DistributionGroup -Identity $DL.Alias -ResultSize Unlimited
# Get members of the distribution group
$Members = Get-DistributionGroupMember -Identity $DistributionGroup.Identity -ResultSize Unlimited
foreach ($Member in $Members) {
# Check if the member is external
if ($Member.RecipientType -eq 'MailContact' -or $Member.RecipientType -eq 'MailUser' -or $Member.ExternalEmailAddress) {
$DLsWithExtUsers += [PSCustomObject]@{
GroupName = $DistributionGroup.DisplayName
MemberName = $Member.DisplayName
MemberType = $Member.RecipientType
MemberEmail = $Member.PrimarySmtpAddress
}
}
}
}
# Export the results to a CSV file
$DLsWithExtUsers | Export-Csv -Path "C:\output.csv" -NoTypeInformation
Write-Host "Export completed. File saved to C:\output.csv.csv"
4 answers
Sort by: Most helpful
-
-
Roger Roger 6,691 Reputation points
2025-01-24T15:56:30.99+00:00 is the below syntax correct for both onprem and online. i have removed -or $Member.RecipientType -eq 'MailUser'. else please help me with correct syntax.
# Import the CSV file containing distribution group names $ExchangeDLs = Import-Csv -Path "C:\input.csv" $DLsWithExtUsers = @() foreach ($DL in $ExchangeDLs) { # Get the distribution group by name from the CSV $DistributionGroup = Get-DistributionGroup -Identity $DL.Alias -ResultSize Unlimited # Get members of the distribution group $Members = Get-DistributionGroupMember -Identity $DistributionGroup.Identity -ResultSize Unlimited foreach ($Member in $Members) { # Check if the member is external if ($Member.RecipientType -eq 'MailContact' -or $Member.ExternalEmailAddress) { $DLsWithExtUsers += [PSCustomObject]@{ GroupName = $DistributionGroup.DisplayName MemberName = $Member.DisplayName MemberType = $Member.RecipientType MemberEmail = $Member.PrimarySmtpAddress } } } } # Export the results to a CSV file $DLsWithExtUsers | Export-Csv -Path "C:\output.csv" -NoTypeInformation Write-Host "Export completed. File saved to C:\output.csv.csv"
-
Jake Zhang-MSFT 8,400 Reputation points Microsoft Vendor
2025-01-27T02:35:26.55+00:00 Hi @Roger Roger ,
Welcome to the Microsoft Q&A platform!
Based on your description, your script takes a long time to run, which may be due to the large number of distribution groups and members to process. Here are some suggestions for optimizing your script and ensuring it runs efficiently:
- Including a progress indicator can help you monitor the progress of the script and identify any bottlenecks. You can use Write-Progress to display the progress of the script.
- Running the script as a background job can prevent it from blocking your PowerShell session. You can use Start-Job to run the script in the background and Receive-Job to get the results.
- You can filter the members directly when retrieving them instead of checking each one individually.
Here is an optimized version of the script with a progress indicator and filtering capabilities:
# Import the CSV file containing distribution group names $ExchangeDLs = Import-Csv -Path "C:\input.csv" $DLsWithExtUsers = @() $totalDLs = $ExchangeDLs.Count $currentDL = 0 foreach ($DL in $ExchangeDLs) { $currentDL++ Write-Progress -Activity "Processing Distribution Groups" -Status "$currentDL out of $totalDLs" -PercentComplete (($currentDL / $totalDLs) * 100) # Get the distribution group by name from the CSV $DistributionGroup = Get-DistributionGroup -Identity $DL.Alias -ResultSize Unlimited # Get members of the distribution group and filter for external users $Members = Get-DistributionGroupMember -Identity $DistributionGroup.Identity -ResultSize Unlimited | Where-Object { $_.RecipientType -eq 'MailContact' -or $_.RecipientType -eq 'MailUser' -or $_.ExternalEmailAddress } foreach ($Member in $Members) { $DLsWithExtUsers += [PSCustomObject]@{ GroupName = $DistributionGroup.DisplayName MemberName = $Member.DisplayName MemberType = $Member.RecipientType MemberEmail = $Member.PrimarySmtpAddress } } } # Export the results to a CSV file $DLsWithExtUsers | Export-Csv -Path "C:\output.csv" -NoTypeInformation Write-Host "Export completed. File saved to C:\output.csv"
For Exchange Online, you can use a similar approach. First, connect to Exchange Online using the Connect-ExchangeOnline cmdlet, and then run the script to get and export the distribution lists:
# Connect to Exchange Online $UserCredential = Get-Credential Connect-ExchangeOnline -UserPrincipalName $UserCredential.UserName -Password $UserCredential.Password # Fetch and export DLs with external users $DLs = Get-DistributionGroup -ResultSize Unlimited $DLsWithExternalUsers = @() $totalDLs = $DLs.Count $currentDL = 0 foreach ($DL in $DLs) { $currentDL++ Write-Progress -Activity "Processing Distribution Groups" -Status "$currentDL out of $totalDLs" -PercentComplete (($currentDL / $totalDLs) * 100) $Members = Get-DistributionGroupMember -Identity $DL.Identity -ResultSize Unlimited | Where-Object { $_.RecipientType -eq 'MailContact' -or $_.RecipientType -eq 'MailUser' -or $_.ExternalEmailAddress } foreach ($Member in $Members) { $DLsWithExternalUsers += [PSCustomObject]@{ GroupName = $DL.DisplayName MemberName = $Member.DisplayName MemberType = $Member.RecipientType MemberEmail = $Member.PrimarySmtpAddress } } } # Export the results to a CSV file $DLsWithExternalUsers | Export-Csv -Path "C:\DLsWithExternalUsers_ExchangeOnline.csv" -NoTypeInformation Write-Host "Export completed. File saved to C:\DLsWithExternalUsers_ExchangeOnline.csv"
These optimizations should help your script run more efficiently and give you a better understanding of its progress.
Please feel free to contact me for any updates. And if this helps, don't forget to mark it as an answer.
Best,
Jake Zhang
-
Roger Roger 6,691 Reputation points
2025-01-27T20:29:39.3666667+00:00 I am encountering the following error when executing this in Exchange Online. I am using an Exchange Hybrid environment with Azure AD Sync, meaning all my on-premises distribution lists (DLs) are visible in Exchange Online. If I execute this in Exchange Online, will it be sufficient, or do I need to execute it in Exchange On-Premises as well?
$ExchangeDLs = Import-Csv -Path "C:\temp\input.csv" $DLsWithExtUsers = @() $totalDLs = $ExchangeDLs.Count $currentDL = 0 foreach ($DL in $ExchangeDLs) { $currentDL++ Write-Progress -Activity "Processing Distribution Groups" -Status "$currentDL out of $totalDLs" -PercentComplete (($currentDL / $totalDLs) * 100) # Get the distribution group by name from the CSV $DistributionGroup = Get-DistributionGroup -Identity $ExchangeDLs.Alias -ResultSize Unlimited $Members = Get-DistributionGroupMember -Identity $DistributionGroup.Identity -ResultSize Unlimited | Where-Object { $_.RecipientType -eq 'MailContact' -or $_.RecipientType -eq 'MailUser' -or $_.ExternalEmailAddress } foreach ($Member in $Members) { $DLsWithExtUsers += [PSCustomObject]@{ GroupName = $DL.DisplayName MemberName = $Member.DisplayName MemberType = $Member.RecipientType MemberEmail = $Member.PrimarySmtpAddress } } } # Export the results to a CSV file $DLsWithExtUsers | Export-Csv -Path "C:\temp\output.csv" -NoTypeInformation Write-Host "Export completed. File saved to C:\temp\output.csv" =========================== Attempted to divide by zero. At line:9 char:5 + Write-Progress -Activity "Processing Distribution Groups" -Status ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], RuntimeException + FullyQualifiedErrorId : RuntimeException Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'. At line:19 char:9 + $DLsWithExternalUsers += [PSCustomObject]@{ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound