Large distribution groups can lead to some unfortunate incidents in an Exchange organization, such as the one that occurred at Reuters recently when a person was able to send to 33,000 recipients, causing a server-crushing increase in email traffic as hundreds of those recipients proceeded to “reply all”.

One of the precautionary measures you can take is restricting who can send to your largest distribution groups. Of course this means you must first identify those groups, which is quite simple to do with PowerShell.

The Exchange management shell includes a Get-DistributionGroupMember cmdlet that can output the members of a distribution group. This cmdlet has one flaw in that it does not perform a recursive search. For example, this “All Staff” distribution group has two smaller groups nested in it as members, which then contain the several hundred individual recipients. If we use Get-DistributionGroupMember it tells us that there are two members, which is true in one sense, but quite useless for our objective here.

[PS] C:Scripts>(Get-DistributionGroupMember "All Staff").Count
2

Sure, we could build a script with a recursive function that expands the membership of any groups contained within other groups, and that would do the job. But that’s a bunch of code that isn’t necessary, because fortunately an Active Directory PowerShell cmdlet comes to the rescue. Get-ADGroupMember has a -Recursive switch to handle this for us.

[PS] C:Scripts>(Get-ADGroupMember -Recursive "All Staff").Count
389

So let’s say that we want to produce a report of all distribution groups that contains their names, member counts, and managers as well (in case we need to discuss any restrictions on the group with the owner/manager). I’ve written a simple PowerShell script to do just that.

Download Get-DGMemberCounts.ps1 from Github

Here’s an example of the script running.

[PS] C:Scripts>.Get-DGMemberCounts.ps1

Payroll Team has 3 members
Public Folder Owners has 2 members
Head Office Staff has 386 members
All Staff has 389 members
Regional Office Staff has 4 members
All Office Meeting Rooms has 3 members
Deny Outgoing External Email has 1 members
ZTestExternal2 has 1 members
Security Team has 0 members
Social Club has 3 members
App_Tier2_ABCDEF has 1 members
DL_Alannah.Shaw has 2 members
DL_Mike.Ryan has 2 members
DL_ex2010test has 1 members

And the resulting CSV file.

dg-member-counts

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. SD

    Hi

    Could you please provide an script to extract/report with all distribution groups (static and dynamic) with the following columns.

    Displayname, Members Count, AcceptMessagesOnlyFrom, ModerationEnabled, ModeratedBy

    1. Avatar photo
      Tony Redmond

      I certainly could provide such a script, but you’ll find that it will take you a little time to write the script and at the end of the experience, you’ll feel much better that you did it rather than me.

  2. Bhargav

    Hi Paul,

    Thanks for the script.
    when i am using below lines, its not counting the members in child groups. can you please help on it.

    #Get distribution groups
    $distgroups = @(Get-ADObject -LDAPFilter โ€œ(&(objectclass=group)(mail=*))โ€ -Properties name, distinguishedName, managedby, mail)

    #Process each distribution group
    foreach ($dg in $distgroups)
    {
    $count = @(Get-ADGroup $dg.distinguishedname -Properties member |Select-Object -ExpandProperty member|Get-ADObject -Properties Samaccountname,DistinguishedName |select Samaccountname,DistinguishedName,ObjectClass).Count

  3. Seifer Almasy

    For O365 users just use this :

    (Get-DistributionGroupMember -Identity “Name of your group”).count

    1. Avatar photo
      Tony Redmond

      That’s the count of objects in the DL. It doesn’t expand nested DLs into their members.

  4. Gino

    Hi , Is there a way to use the script if i dont have exchange on Prem? We use o #65 Exchange and we synch AD to Azure .

  5. Barry

    Hi,

    Great script. I to had to import-module activedirectory in PS to retrieve member count. Also as per the earlier post I had to remove .name from this line:
    $reportObj | Add-Member NoteProperty -Name โ€œManagerโ€ -Value $dg.managedby.Name
    for the Manager field to populate any data.

    However the data which populates the Manager column is as follows – am I missing something

    “Microsoft.Exchange.Data.Directory.ADMultiValuedProperty`1[Microsoft.Exchange.Data.Directory.ADObjectId]”

    Many Thanks

  6. Hari Prasad

    Hi Everyone,

    The script is really good, while i tweaked the script at few places. The ManagedBy property is not getting into csv. Please let me know if any PS module needs to be loaded or please share the script those who have already tried and working.

  7. David

    Any updates to this script?

  8. Samad

    Paul,
    Any chance you got this to work with 365? This script is extremely helpful.
    Thanks
    -Samad

  9. Alex

    I got it working by commenting out if/else for the RemoteExchange, and loaded the $LiveCred and Import-PSSession however, i got an error for the Set-ADServerSettings, and it says all my groups have 0 member count.

    GROUP has 0 members
    Get-ADGroupMember : Cannot find an object with identity:

    1. Alex

      Not sure but think somehow its not connecting to AD properly even tho it spits out the information for group names, and DN names. Just always showing 0 counts. Im on O365 and not exchange physical tho

  10. Alex

    How do I get this working for O365 ?

  11. Vinod

    Hey Paul,

    How do i achieve this using Exchange online? I need to export the DL members/Nested or recursive Members and Null Members

  12. Tiago Rocha

    Hi,

    I have a distribution group in Exchange 2013 on premise called grupoempresas@meudominio.com.br, and this group has the amount of more than 850 members. And to enter the group name created in the recipient field (Outlook / Webmail) the error appears below:

    You are not allowed to send: grupoempresas@meudominio.com.br

    gruposempresas @ mydomain contains about 901 recipients.

    The following documentation (https://technet.microsoft.com/pt-br/library/exchange-online-limits.aspx#DistributionGroupLimits), reports that the limit is 100,000 and sending up to 5,000.

    Any tips to release shipments for this group?

    Sorry translation, do not understand much English.

    Grateful!

    Thiago Rocha!

  13. John

    How can I change the scope to be distribution lists which start with a specific word?

    1. Avatar photo
      Paul Cunningham

      Edit the script so this line only returns the groups you’re interested in.

      #Get distribution groups
      $distgroups = @(Get-DistributionGroup -ResultSize Unlimited)

      1. Anish George

        Hi

        Could you please help me to get list of authored (authOrig) users to send the mail to DLs.

        DL name Members authored user list

  14. Tony

    The script works great with 2 exceptions.

    I had to remove .name from this line:
    $reportObj | Add-Member NoteProperty -Name “Manager” -Value $dg.managedby.Name

    I have some groups that are over the 5,000 limit placed on what I believe is ADWS. I get this error:
    Get-ADGroupMember : The size limit for this request was exceeded
    FullyQualifiedErrorId : The size limit for this request was exceeded,Microsoft.ActiveDirectory.Commands.GetADGroupMember

    1. Tom

      Yes the program canโ€™t count over 5000.
      Why?
      The Get-ADGroupMember commandlet has a restriction on the domain controller limiting it to 5000 results by default. The restriction is on the under MaxGroupOrMemberEntries attribute in the Microsoft.ActiveDirectory.WebServices.exe.config file, under C:\WindowsADWS directory.

      1. Dilip Sasikumar

        any workaround for this restriction of 5000?

        1. Dilip Sasikumar

          Thought This might help people who has more than 5000 member’s groups

          #Get distribution groups
          $distgroups = @(Get-ADObject -LDAPFilter “(&(objectclass=group)(mail=*))” -Properties name, distinguishedName, managedby, mail)

          #Process each distribution group
          foreach ($dg in $distgroups)
          {
          $count = @(Get-ADGroup $dg.distinguishedname -Properties member |Select-Object -ExpandProperty member|Get-ADObject -Properties Samaccountname,DistinguishedName |select Samaccountname,DistinguishedName,ObjectClass).Count

  15. PR

    I am running the script on Exchange 2010 Server and I get all zero for all groups. What should I do?

  16. Erik B

    If you are getting Zero for all groups you don’t have the AD snapin on powershell – add that and run and you are GTG

    1. Alex

      Not sure if thats the case. I am using ‘Import-Module ActiveDirectory’, and I still get 0 counts. I think it has do with Set-ADServerSettings command as I get an error there but. but I also had to remove the RemoteExchange part

  17. Shimi

    Hi,
    Downloaded and run the script but it shows zero 0 for all group, do I need to change something in the script?

  18. Mirit

    Hi Paul,
    Thanks for this great script, I used it and managed to get full list of all our distribution groups member count.
    however,
    the Dynamic distribution groups were not included on the report.
    what should I add in order to see the dynamic distribution groups on the report?
    Many Thanks.

  19. Pablo

    I can filter by OU the search? example: $distgroups = @(Get-DistributionGroup -ResultSize Unlimited | where {$_.identity -like “Ou../pais/groups/*”})

    Thank You.

  20. Vladislav Artukov

    It doesn’t work without Active DIrectory module.

  21. jconsumer

    Paul in my environment we have 3 child domains containing the users, while the Exchange servers are members of only one of the child domains. When I run the script in the domain containing the servers it does not correctly count the members if they are in one of the other child domains.

    For example group “All Staff” has members from all 3 child domains but the script only counts the members of the domain the script was run from leaving out the members of the other 2 domains.

    Any suggestions to span multiple domains? Other scripts I have written required 3 domaincontroller variables but not sure how I would add that in this script.

  22. Turbomcp

    awesome
    Thanks

  23. Roy

    Hi Paul

    I was going to use this to clean up empty distributiongroups. But then I saw some groups was displayed as “0” members from your script. But I knew there were members in them .

    Example: http://i.imgur.com/yYE0E4D.png
    This is mail contacts for external users/customers.

    I guess I’m using my old script for this ๐Ÿ™‚

    1. Avatar photo
      Paul Cunningham

      So the group contains only mail-enabled contacts? I will have to test that out, I have no groups like that in my lab right now ๐Ÿ™‚

      1. Patrick

        I have noticed the same – the Get-ADGroupMember cmdlet will return neither Mail Contacts nor PublicFolders that might be part of a distribution group.
        I don’t know if there’s any way around that, unfortunately, I came here while looking for a solution myself.

        1. Avatar photo
          Paul Cunningham

          The solution is to write a recursive function, which I was hoping to avoid in this case, but with this revelation that some objects aren’t returned by the AD cmdlet I’ll dig up one of my old samples and update this post and script soon ๐Ÿ™‚

          1. ac

            I know this is an old thread, but did you find your script that would detect mail contacts in distribution groups and count them?

  24. NavZ

    Hi Paul

    great script. when I am trying to run it I am getting this error thou.

    The ‘<' operator is reserved for future use.
    At C:usersagentnavzDesktopGet-DGMemberCounts.ps1:50 char:11
    + <!– < <<< –>
    + CategoryInfo : ParserError: (<:OperatorToken) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

    1. Avatar photo
      Paul Cunningham

      What version of Powershell? And have you modified the script at all?

      1. NavZ

        PSVersion 2.0

        and nope…I downloaded the script as is.

        1. Avatar photo
          Paul Cunningham

          If you open the script in the PowerShell ISE my guess is you’ll see a bunch of HTML code that doesn’t belong there. Click on the script instead so you can see the actual PowerShell code.

  25. Jason Meyer

    Awesome post as usual. Any thoughts on a report for when an Exchange Distribution Group was last used? Guessing that eventually Microsoft will add this as a tracked attribute as the only way that I can think of is tracking EXAND events in message tracking.

    Any thoughts?

    1. Avatar photo
      Paul Cunningham

      Message tracking is the only way I know of to get this info right now.

Leave a Reply