script runs for hours without any output

Roger Roger 6,691 Reputation points
2025-01-24T12:51:10.99+00:00

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"
Exchange Server
Exchange Server
A family of Microsoft client/server messaging and collaboration software.
1,422 questions
Microsoft Exchange Online Management
Microsoft Exchange Online Management
Microsoft Exchange Online: A Microsoft email and calendaring hosted service.Management: The act or process of organizing, handling, directing or controlling something.
4,702 questions
Exchange Server Management
Exchange Server Management
Exchange Server: A family of Microsoft client/server messaging and collaboration software.Management: The act or process of organizing, handling, directing or controlling something.
7,775 questions
Microsoft Exchange
Microsoft Exchange
Microsoft messaging and collaboration software.
650 questions
Microsoft Exchange Hybrid Management
Microsoft Exchange Hybrid Management
Microsoft Exchange: Microsoft messaging and collaboration software.Hybrid Management: Organizing, handling, directing or controlling hybrid deployments.
2,210 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Andy David - MVP 151.6K Reputation points MVP
    2025-01-24T12:58:25.88+00:00

    A RecipientType -eq 'MailUser is not an external user. Thats a remote mailbox that represents the mailbox in Exchange Online for your internal users.

    0 comments No comments

  2. 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"
    
    
    0 comments No comments

  3. 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:

    1. 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.
    2. 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.
    3. 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

    0 comments No comments

  4. 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
     
     
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.