Public/Invoke-ModernMailHybridReport.ps1
function Invoke-ModernMailHybridReport { <# .SYNOPSIS ModernMail Hybrid Report / Exchange Hybrid Report / Microsoft365 Hybrid Report .DESCRIPTION Generates a comprehensive Exchange Hybrid report for Microsoft 365 environments. The report includes user statistics, shared mailbox details, directory sync status, and license information. Outputs a styled HTML file with interactive charts and summary statistics. .PARAMETER OutPath The output path for the generated HTML report. Can be a directory (FileName: 'ExchangeHybridReport.html') or a full file path. .EXAMPLE Invoke-ModernMailHybridReport -OutPath "C:\Reports" Invoke-ModernMailHybridReport -OutPath "C:\Reports\ExchangeHybridReport.html" .LINK https://exchangepermissions.alweys.ch/modernmailtools/Invoke-ModernMailHybridReport .INPUTS None .OUTPUTS .NOTES #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$OutPath ) # Connect-ExchangeServer.ps1 # Connect-Exchange Online $session = Get-ConnectionInformation If (!$session) { Connect-ExchangeOnline -ShowBanner:$false $session = Get-ConnectionInformation } Write-Debug $session.UserPrincipalName $userPrincipalName = $session.UserPrincipalName ## Organization | $organisationName Write-Debug $session.TenantID $tenantID = $session.TenantID $users = Get-User #$usersGrouped = $users | Group RecipientType $usersGrouped = $users | Group-Object RecipientTypeDetails #$usersGrouped[0].Name #$usersGrouped[0].Count #Total Users $usersCount = $users.Count #$users | Group IsDirSynced $isDirSyncedCount = ($users | Where-Object {$_.IsDirSynced}).count $sharedMailboxes = $users | Where-Object {$_.RecipientTypeDetails -eq "SharedMailbox"} $sharedMailboxCount = $sharedMailboxes.count # ToBeQuestioned $sharedMailboxEnabled = $sharedMailboxes | Where-Object {$_.AccountDisabled -eq $false} $sharedMailboxEnabledCount = $sharedMailboxEnabled.count #$users | Group AccountDisabled $sharedMailboxDisabled = $sharedMailboxes | Where-Object {$_.AccountDisabled -eq $true} $sharedMailboxDisabledCount = $sharedMailboxDisabled.count # ToBeQuestioned (Litigation Hold Enabled?) #$users | Group SKUAssigned $sharedMailboxLicensed = ($sharedMailboxes | Where-Object {$_.SKUAssigned -ne $true}) $sharedMailboxLicensedCount = $sharedMailboxLicensed.count #$users | select -First 1 *hold* function Build-HybridReport { param( [Parameter(Mandatory=$false)] [string]$OutputPath ) # Path to the HTML template $templatePath = "$PSScriptRoot\..\Private\HybridReportTemplate.html" # Read the HTML template $htmlTemplate = Get-Content -Path $templatePath -Raw # Generate dynamic rows for grouped data $dynamicRows = "" $chartLabels = @() $chartData = @() foreach ($group in $usersGrouped) { $dynamicRows += @" <tr class="border-b border-gray-300"> <td class="px-4 py-2 border-b border-r">$($group.Name)</td> <td class="px-4 py-2 border-b">$($group.Count)</td> </tr> "@ $chartLabels += "'$($group.Name)'" $chartData += $group.Count } # Convert arrays to JavaScript-compatible strings $chartLabelsString = "[" + ($chartLabels -join ", ") + "]" $chartDataString = "[" + ($chartData -join ", ") + "]" # Generate header details $reportName = "Exchange Hybrid Report" $date = Get-Date #$organizationName = "Your Organization Name" # Replace with actual organization name $headerContent = @" <div class="header bg-orange-500 text-white p-6 rounded-lg shadow-md"> <h1 class="text-3xl font-bold">$reportName</h1> <!--<p class="text-lg">Organization: $organizationName</p>--> <p class="text-lg mt-4">Tenant ID: $tenantID</p> <p class="text-lg">Generated by: $userPrincipalName</p> <p class="text-lg">Generated on: $date</p> <div class="mt-4"> <a href="https://alweys.ch" target="_blank" class="bg-blue-500 hover:bg-blue-700 text-white text-xs font-semibold py-1 px-2 rounded"> Website (alweys.ch) </a> <a href="https://www.linkedin.com/in/stefanwey" target="_blank" class="bg-blue-500 hover:bg-blue-700 text-white text-xs font-semibold py-1 px-2 rounded ml-2"> LinkedIn (Stefan Wey) </a> </div> </div> <div class="stats-container grid grid-cols-2 gap-4 mt-4"> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Total Users</h3> <p class="text-2xl font-bold text-orange-500">$usersCount</p> </div> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Shared Mailboxes</h3> <p class="text-2xl font-bold text-orange-500">$sharedMailboxCount</p> </div> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Directory Synced Users</h3> <p class="text-2xl font-bold text-orange-500">$isDirSyncedCount</p> </div> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Enabled Shared Mailboxes</h3> <p class="text-2xl font-bold text-orange-500">$sharedMailboxEnabledCount</p> </div> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Disabled Shared Mailboxes</h3> <p class="text-2xl font-bold text-orange-500">$sharedMailboxDisabledCount</p> </div> <div class="stat-box bg-white p-4 rounded-lg shadow-md"> <h3 class="text-lg font-semibold">Licensed Shared Mailboxes</h3> <p class="text-2xl font-bold text-orange-500">$sharedMailboxLicensedCount</p> </div> </div> "@ # Replace placeholders in the template $htmlContent = $htmlTemplate -replace "{{HeaderContent}}", $headerContent $htmlContent = $htmlContent -replace "{{DynamicRows}}", $dynamicRows $htmlContent = $htmlContent -replace "{{ChartLabels}}", $chartLabelsString $htmlContent = $htmlContent -replace "{{ChartData}}", $chartDataString # Generate the Path if (Test-Path $OutPath -PathType Container) { # If $OutPath is a directory, append the default file name $OutputPath = Join-Path -Path $OutPath -ChildPath "ExchangeHybridReport.html" } else { # If $OutPath is a file, use it directly $OutputPath = $OutPath } # Output HTML report #$html | Out-File -FilePath $OutputPath -Encoding UTF8 $htmlContent | Out-File -FilePath $OutputPath -Encoding UTF8 Write-output "HTML report generated at $OutputPath" # Open the report in the default browser Start-Process $OutputPath } Build-HybridReport -OutputPath $OutPath } |