powershell-scripts/Find Inactive Distribution Lists/FindInactiveDistributionLists.ps1
2024-07-09 17:42:41 +05:30

193 lines
7.7 KiB
PowerShell

<#
=============================================================================================
Name: Find Inactive Distribution Lists Using PowerShell
Version: 1.0
Website: o365reports.com
~~~~~~~~~~~~~~~~~
Script Highlights:
~~~~~~~~~~~~~~~~~
1. The script automatically verifies and installs the Exchange PowerShell module (if not installed already) upon your confirmation.
2. Exports inactive days of distribution lists in Microsoft 365.
3. Retrieves the last email received date.
4. Exports report results to CSV.
5. The script is schedular-friendly.
6. It can be executed with certificate-based authentication (CBA) too.
For detailed script execution: https:https://o365reports.com/2024/07/09/find-inactive-distribution-lists-using-powershell/
=============================================================================================
#>
param(
[string] $CertificateThumbPrint,
[string] $ClientId,
[string] $Organization,
[string] $UserName,
[string] $Password,
[String]$HistoricalMessageTraceReportPath
)
if($HistoricalMessageTraceReportpath)
{
if (-not (Test-Path $HistoricalMessageTraceReportPath -PathType Leaf))
{
Write-Host "`nError: The specified CSV file does not exist or is not accessible." -ForegroundColor Red
Exit
}
}
else
{
Write-Host "`nInput file path is required" -ForegroundColor Red
Exit
}
Function ConnectEXO
{
#check for EXO installation
$Module=Get-Module ExchangeOnlineManagement -ListAvailable
if($Module.count -eq 0)
{
Write-Host Exchange online powershell is not available -ForegroundColor Yellow
$Confirm = Read-Host Are you sure want to install module? [Y] Yes [N] No
if($Confirm -match "[yY]")
{
Write-Host Installing Exchange Online Powershell module
Install-Module -Name ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force -scope CurrentUser
Write-Host ExchangeOnlineManagement installed successfully...
}
else
{
Write-Host EXO module is required to connect Exchange Online.Please Install-module ExchangeOnlineManagement.
Exit
}
}
Write-Host "`nConnecting to Exchange Online..."
try{
#connect to Exchange Online
if(($Organization -ne "") -and ($ClientId -ne "") -and ($CertificateThumbPrint -ne ""))
{
#Connect Exchange online using Certificate based Authentication
Connect-ExchangeOnline -CertificateThumbprint $CertificateThumbPrint -AppId $ClientId -Organization $Organization -ErrorAction stop -ShowBanner:$false
}
elseif(($UserName -ne "") -and ($Password -ne ""))
{
#Connect Exchange online using username and password
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential $UserName, $SecuredPassword
Connect-ExchangeOnline -Credential $Credential -ErrorAction stop -ShowBanner:$false
}
else
{
Connect-ExchangeOnline -ErrorAction stop -ShowBanner:$false
}
}
catch
{
Write-Host "Error occurred: $($_.Exception.Message )" -ForegroundColor Red
Exit
}
Write-Host "`nExchangeonline connected successfully" -ForegroundColor Green
}
Function GettingDistributionLists{
Get-DistributionGroup -ResultSize unlimited | Where-Object{$_.RecipientTypeDetails -eq "MailUniversalDistributionGroup"} | ForEach-Object{
ForEach($Email in $_.EmailAddresses){
$Mail = (($Email).split(":") | Select -Index 1)
$global:DistributionLists[$Mail] = $_.PrimarySmtpAddress
}
}
}
Function FindDifference{
param(
$DateTime
)
$DayDifference = (New-TimeSpan -Start $DateTime -End (Get-Date)).Days
$DayDifference = "$DayDifference" + " Days"
return $DayDifference
}
Function GettingInactiveDistributionLists
{
# Read the original CSV file content
$originalContent = Get-Content -Path $HistoricalMessageTraceReportPath
# Remove non-printable characters (if any)
$sanitizedContent = $originalContent -replace '[^\P{C}]', ''
Set-Content -Path $HistoricalMessageTraceReportPath -Value $sanitizedContent
Import-CSV -path $HistoricalMessageTraceReportPath | Foreach-Object {
$RecipientAddresses = $_.'recipient_status' -Split ';'
ForEach($RecipientAddress in $RecipientAddresses){
$Recipient = $RecipientAddress -Split "##" | select -Index(0)
$DL = $global:DistributionLists.$Recipient
if($DL)
{
$LastEmail = Get-Date -Date $($_.'origin_timestamp_utc')
$LastEmailReceived = $LastEmail.ToString("dd-MM-yyyy HH:mm:ss")
$Difference = FindDifference -DateTime $LastEmail
if($global:InactiveDistributionLists.$DL)
{
$Last = $global:InactiveDistributionLists.$DL[0]
if($Last -lt $LastEmailReceived)
{
$global:InactiveDistributionLists.$DL[0] = $LastEmailReceived
$global:InactiveDistributionLists.$DL[1] = $Difference
}
}
else
{
$global:InactiveDistributionLists[$DL] = @($LastEmailReceived,$Difference)
}
}
}
}
}
#To connect exchangeonline
ConnectEXO
#Hashmap to store distribution lists
$global:DistributionLists = @{}
write-Host "`nGetting inactive distribution lists. This may take some time to process based on the input given..."
#To Get all the distribution lists including alias
GettingDistributionLists
#To store the Inactive DistributionLists
$global:InactiveDistributionLists = @{}
GettingInactiveDistributionLists
$global:CSVFile = "InactiveDistributionLists_" + ((Get-Date -format "MMM-dd hh-mm-ss tt").ToString()) + ".csv"
ForEach($DistributionList in $global:DistributionLists.GetEnumerator()){
$DL = $($DistributionList.Name)
if($DL -eq $($DistributionList.Value)){
if($global:InactiveDistributionLists.$DL)
{
$LastEmailReceivedDate = $global:InactiveDistributionLists.$DL[0]
$InactiveDays = $global:InactiveDistributionLists.$DL[1]
}
else
{
$LastEmailReceivedDate = "No data available"
$InactiveDays = "Inactive for longer than the selected time range."
}
$ExportResult = @{'Group Name' =$DL; 'Last Email Received Date' = $LastEmailReceivedDate; 'Inactive Days' = $InactiveDays }
$ExportResults = New-Object PSObject -Property $ExportResult
$ExportResults | Select-object 'Group Name', 'Last Email Received Date', 'Inactive Days' | Export-csv -path $global:CSVFile -NoType -Append -Force
}
}
$Location = Get-Location
if (((Test-Path -Path $global:CSVFile) -eq "True")) {
Write-Host "`nThe output file " -NoNewline -ForegroundColor yellow; Write-Host $global:CSVFile -NoNewline -ForegroundColor Cyan; Write-Host " is available in the directory $Location " -ForegroundColor Yellow
$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 "$global:CSVFile"
}
}
Disconnect-ExchangeOnline -Confirm:$false
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