2025-03-13 16:02:00 +05:30

284 lines
9.5 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<#
=============================================================================================
Name: Get distribution groups report
Version: 1.0
Website: o365reports.com
Script Highlights:
~~~~~~~~~~~~~~~~~
1. Exports distribution groups with allowed / blocked external senders.
2. Helps to identify empty distribution groups.
3. Allows to filter results based on group members count.
4. Bulk import specific DLs and get the report on those specific DLs.
5. The script automatically verifies and installs the Exchange Online PowerShell module (if not installed already) upon your confirmation.
6. The script can be executed with MFA enabled account too.
7. It can be executed with Certificate-based Authentication (CBA) too.
8. Exports DLs members count based on Member Type such as user mailbox, group mailbox, etc.
9. The script is scheduler friendly and exports the report result to CSV format.
10. This script exports output in 2 CSV files. One with DL details and another with membership details.
For detailed script execution: https://o365reports.com/2025/03/04/export-distribution-groups-report-in-microsoft-365/
============================================================================================
#>
Param
(
[Parameter(Mandatory = $false)]
[string]$GroupNamesFile,
[switch]$IsEmpty,
[int]$MinGroupMembersCount,
[Nullable[boolean]]$ExternalSendersBlocked = $null,
[string]$UserName,
[string]$Password,
[string]$Organization,
[string]$ClientId,
[string]$CertificateThumbprint
)
Function Get_members
{
$DisplayName=$_.DisplayName
Write-Progress -Activity "`n Processed Group count: $Count "`n" Getting members of: $DisplayName"
$Alias=$_.Alias
$EmailAddress=$_.PrimarySmtpAddress
$GroupType=$_.GroupType
$ManagedBy=$_.ManagedBy
$ExternalSendersAllowed=$_.RequireSenderAuthenticationEnabled
if(($ExternalSendersBlocked -ne $null) -and ($ExternalSendersBlocked -ne $ExternalSendersAllowed))
{
$Print=0
}
#Get Distribution Group Authorized Senders
$AcceptMessagesOnlyFrom=$_.AcceptMessagesOnlyFromSendersOrMembers
$AuthorizedSenders=""
if($AcceptMessagesOnlyFrom.Count -gt 0)
{
foreach($item in $AcceptMessagesOnlyFrom)
{
$AuthorizedSenders=$AuthorizedSenders+$item
if($AcceptMessagesOnlyFrom.indexof($item) -lt (($AcceptMessagesOnlyFrom.count)-1))
{
$AuthorizedSenders=$AuthorizedSenders+","
}
}
}
elseif($ExternalSendersAllowed -eq "True")
{
$AuthorizedSenders="Only Senders in Your Organization"
}
else
{
$AuthorizedSenders="Senders inside & Outside of Your Organization"
}
$Manager = @()
if($_.ManagedBy.Count -gt 0)
{
foreach($ManageBy in $ManagedBy)
{ #Verify if manager property returned as ID and convert it to user-identifiable name
if($ManageBy -match '(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$')
{
if($ManagerHash.ContainsKey($ManageBy))
{
$ManagerName=$ManagerHash[$ManageBy]
}
# Retrieve the display name for the ID
else
{
$ManagerName=(Get-EXORecipient -Identity $ManageBy).DisplayName
$ManagerHash[$ManageBy]=$ManagerName
}
$ManageBy=$ManagerName
}
$Manager+=$ManageBy
}
$Manager= $Manager -join ","
}
$Recipient=""
$RecipientHash=@{}
for($KeyIndex = 0; $KeyIndex -lt $RecipientTypeArray.Length; $KeyIndex += 2)
{
$key=$RecipientTypeArray[$KeyIndex]
$Value=$RecipientTypeArray[$KeyIndex+1]
$RecipientHash.Add($key,$Value)
}
$Members=Get-DistributionGroupMember -ResultSize Unlimited -Identity $EmailAddress
$MembersCount=($Members.name).Count
#GroupSize Filter
if(([int]$MinGroupMembersCount -ne "") -and ($MembersCount -lt [int]$MinGroupMembersCount))
{
$Print=0
}
#Check for Empty Group
elseif($MembersCount -eq 0)
{
$Member="No Members"
$MemberEmail="-"
$RecipientTypeDetail="-"
Print_Output
}
#Loop through each member in a group
else
{
foreach($Member in $Members)
{
if($IsEmpty.IsPresent)
{
$Print=0
break
}
$RecipientTypeDetail=$Member.RecipientTypeDetails
$MemberEmail=$Member.PrimarySMTPAddress
$MemberName=$Member.DisplayName
if($MemberEmail -eq "")
{
$MemberEmail="-"
}
#Get Counts by RecipientTypeDetail
foreach($key in [object[]]$Recipienthash.Keys)
{
if(($RecipientTypeDetail -eq $key) -eq "true")
{
[int]$RecipientHash[$key]+=1
}
}
Print_Output
}
}
#Print Summary report
if($Print -eq 1)
{
#Order RecipientTypeDetail based on count
$Hash=@{}
$Hash=$RecipientHash.GetEnumerator() | Sort-Object -Property value -Descending |foreach{
if([int]$($_.Value) -gt 0 )
{
if($Recipient -ne "")
{ $Recipient+=";"}
$Recipient+=@("$($_.Key) - $($_.Value)")
}
if($Recipient -eq "")
{$Recipient="-"}
}
$Result=@{'DisplayName'=$DisplayName;'PrimarySmtpAddress'=$EmailAddress;'Alias'=$Alias;'GroupType'=$GroupType;'Manager'=$Manager;'GroupMembersCount'=$MembersCount;'MembersCountByType'=$Recipient;'AuthorizedSenders'=$AuthorizedSenders;'ExternalSendersBlocked'=$ExternalSendersAllowed;'HiddenFromAddressList'=$_.HiddenFromAddressListsEnabled;
'Description'=$_.Description;'CreationTime'=$_.WhenCreated;'DirSyncEnabled'=$_.IsDirSynced;'JoinGroupWithoutApproval'=$_.MemberJoinRestriction;'LeaveGroupWithoutApproval'=$_.MemberDepartRestriction} #Uncomment to print additional attributes in output
$Results= New-Object PSObject -Property $Result
$Results | Select-Object DisplayName,PrimarySmtpAddress,Alias,GroupType,Manager,GroupMembersCount,AuthorizedSenders,ExternalSendersBlocked,MembersCountByType,HiddenFromAddressList,Description,CreationTime,DirSyncEnabled,JoinGroupWithoutApproval,LeaveGroupWithoutApproval | Export-Csv -Path $ExportSummaryCSV -Notype -Append
}
}
#Print Detailed Output
Function Print_Output
{
if($Print -eq 1)
{
$Result=@{'DisplayName'=$DisplayName;'PrimarySmtpAddress'=$EmailAddress;'Alias'=$Alias;'Members'=$MemberName;'MemberEmail'=$MemberEmail;'MemberType'=$RecipientTypeDetail}
$Results= New-Object PSObject -Property $Result
$Results | Select-Object DisplayName,PrimarySmtpAddress,Alias,Members,MemberEmail,MemberType | Export-Csv -Path $ExportCSV -Notype -Append
}
}
Function main()
{
#Check for EXO module inatallation
$Module = Get-Module ExchangeOnlineManagement -ListAvailable
if($Module.count -eq 0)
{
Write-Host Exchange Online PowerShell module is not available -ForegroundColor yellow
$Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No
if($Confirm -match "[yY]")
{
Write-host "Installing Exchange Online PowerShell module"
Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
}
else
{
Write-Host EXO module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet.
Exit
}
}
Write-Host Connecting to Exchange Online...
#Storing credential in script for scheduling purpose/ Passing credential as parameter - Authentication using non-MFA account
if(($UserName -ne "") -and ($Password -ne ""))
{
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword
Connect-ExchangeOnline -Credential $Credential -ShowBanner:$false
}
elseif($Organization -ne "" -and $ClientId -ne "" -and $CertificateThumbprint -ne "")
{
Connect-ExchangeOnline -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -Organization $Organization -ShowBanner:$false
}
else
{
Connect-ExchangeOnline -ShowBanner:$false
}
#Set output file
$ExportCSV=".\DistributionGroup-MembershipReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv" #Detailed report
$ExportSummaryCSV=".\DistributionGroup-Report_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv" #Summary report
#Get a list of RecipientTypeDetail
$RecipientTypeArray=Get-Content -Path .\RecipientTypeDetails.txt -ErrorAction Stop
$Result=""
$Results=@()
$ManagerHash = @{}
#Check for input file
if([string]$GroupNamesFile -ne "")
{
#We have an input file, read it into memory
$DG=@()
$DG=Import-Csv -Header "DisplayName" $GroupNamesFile
foreach($item in $DG)
{
Get-DistributionGroup -Identity $item.displayname | Foreach{
$Print=1
Get_Members}
$Count++
}
}
else
{
#Get all distribution group
Get-DistributionGroup -ResultSize Unlimited | Foreach{
$Print=1
Get_Members
$Count++}
}
#Open output file after execution
Write-Host `nScript executed successfully
if((Test-Path -Path $ExportCSV) -eq "True")
{
Write-Host `n" Detailed report available in:" -NoNewline -ForegroundColor Yellow
Write-Host $ExportCSV `n
Write-host " Summary report available in:" -NoNewline -ForegroundColor Yellow
Write-Host $ExportSummaryCSV
Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green
Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; Write-Host " to get access to 1800+ Microsoft 365 reports. ~~" -ForegroundColor Green `n`n
$Prompt = New-Object -ComObject wscript.shell
$UserInput = $Prompt.popup("Do you want to open output file?",`
0,"Open Output File",4)
If ($UserInput -eq 6)
{
Invoke-Item "$ExportCSV"
Invoke-Item "$ExportSummaryCSV"
}
}
Else
{
Write-Host No DistributionGroup found
}
#Disconnect Exchange Online session
Disconnect-ExchangeOnline -Confirm:$false -InformationAction Ignore -ErrorAction SilentlyContinue
}
. main