# ================================ # Exchange Online Mailbox Manager (MSP Edition) # ================================ # Global Variables $global:Connected = $false $LogFile = "$PSScriptRoot\MailboxTool.log" # ================================ # Logging # ================================ function Write-Log { param ($Message) $time = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $entry = "$time - $Message" Write-Host $entry Add-Content -Path $LogFile -Value $entry } # ================================ # Connection # ================================ function Connect-EXO { try { Write-Host "Connecting to Exchange Online..." -ForegroundColor Cyan Connect-ExchangeOnline -ShowBanner:$false $global:Connected = $true Write-Log "Connected to Exchange Online" } catch { Write-Log "Connection failed: $_" } } function Disconnect-EXO { Disconnect-ExchangeOnline -Confirm:$false $global:Connected = $false Write-Log "Disconnected from Exchange Online" } function Ensure-Connection { if (-not $global:Connected) { Write-Host "Not connected. Connecting now..." -ForegroundColor Yellow Connect-EXO } } # ================================ # Helper: Convert Size to GB # ================================ function Convert-ToGB { param ($sizeString) if ($sizeString -match "([\d\.]+)\sGB") { return [math]::Round([double]$matches[1],2) } elseif ($sizeString -match "([\d\.]+)\sMB") { return [math]::Round(([double]$matches[1] / 1024),2) } else { return 0 } } # ================================ # Mailbox Listing # ================================ function Get-AllMailboxes { Ensure-Connection Get-Mailbox -ResultSize Unlimited | Select DisplayName, PrimarySmtpAddress } # ================================ # Archive Management # ================================ function Get-ArchiveEnabled { Ensure-Connection Get-Mailbox -ResultSize Unlimited | Where-Object {$_.ArchiveStatus -eq "Active"} | Select DisplayName, PrimarySmtpAddress, ArchiveStatus } function Get-ArchiveDisabled { Ensure-Connection Get-Mailbox -ResultSize Unlimited | Where-Object {$_.ArchiveStatus -ne "Active"} | Select DisplayName, PrimarySmtpAddress, ArchiveStatus } function Check-ArchiveSingle { Ensure-Connection $user = Read-Host "Enter email" $mb = Get-Mailbox -Identity $user Write-Host "`nArchive Status: $($mb.ArchiveStatus)" -ForegroundColor Green } function Enable-ArchiveSingle { Ensure-Connection $user = Read-Host "Enter email" Enable-Mailbox -Identity $user -Archive Write-Log "Archive enabled for $user" } function Disable-ArchiveSingle { Ensure-Connection $user = Read-Host "Enter email" Disable-Mailbox -Identity $user -Archive Write-Log "Archive disabled for $user" } # ================================ # Bulk Operations # ================================ function Bulk-Enable-Archive { Ensure-Connection $file = Read-Host "Enter CSV path (column: UserPrincipalName)" $users = Import-Csv $file foreach ($u in $users) { try { Enable-Mailbox -Identity $u.UserPrincipalName -Archive Write-Log "Enabled archive: $($u.UserPrincipalName)" } catch { Write-Log "Failed: $($u.UserPrincipalName) - $_" } } } # ================================ # Mailbox + Archive Size Report # ================================ function Get-MailboxFullSizeReport { Ensure-Connection Write-Host "Fetching mailbox + archive sizes..." -ForegroundColor Cyan $results = @() $mailboxes = Get-Mailbox -ResultSize Unlimited foreach ($mb in $mailboxes) { try { $primaryStats = Get-MailboxStatistics -Identity $mb.PrimarySmtpAddress $primarySizeGB = Convert-ToGB $primaryStats.TotalItemSize.ToString() $archiveSizeGB = 0 $archiveStatus = $mb.ArchiveStatus try { $archiveStats = Get-MailboxStatistics -Identity $mb.PrimarySmtpAddress -Archive -ErrorAction Stop $archiveSizeGB = Convert-ToGB $archiveStats.TotalItemSize.ToString() } catch { $archiveSizeGB = 0 } # Detect Issues $status = "OK" if ($primarySizeGB -gt 80 -and $archiveStatus -ne "Active") { $status = "⚠ No Archive + Large Mailbox" } elseif ($archiveStatus -eq "Active" -and $archiveSizeGB -lt 1) { $status = "⚠ Archive Enabled but Not Used" } $results += [PSCustomObject]@{ DisplayName = $mb.DisplayName Email = $mb.PrimarySmtpAddress PrimaryGB = $primarySizeGB ArchiveGB = $archiveSizeGB ArchiveStatus = $archiveStatus HealthStatus = $status } } catch { Write-Log "Failed: $($mb.PrimarySmtpAddress) - $_" } } return $results } # ================================ # Export Report # ================================ function Export-MailboxFullReport { $path = "$PSScriptRoot\MailboxFullReport.csv" Get-MailboxFullSizeReport | Export-Csv $path -NoTypeInformation Write-Host "Report exported to $path" -ForegroundColor Green } # ================================ # Menu System # ================================ function Show-MainMenu { Clear-Host Write-Host "========================================" -ForegroundColor Cyan Write-Host " Exchange Online Mailbox Tool (MSP)" Write-Host "========================================" Write-Host "1. Connect" Write-Host "2. List Mailboxes" Write-Host "3. Archive Management" Write-Host "4. Reports" Write-Host "5. Bulk Operations" Write-Host "6. Disconnect" Write-Host "0. Exit" } function Show-ArchiveMenu { Write-Host "`n--- Archive Management ---" Write-Host "1. List Enabled" Write-Host "2. List Disabled" Write-Host "3. Check User" Write-Host "4. Enable Archive" Write-Host "5. Disable Archive" Write-Host "0. Back" } function Show-ReportMenu { Write-Host "`n--- Reports ---" Write-Host "1. Mailbox + Archive Size Report" Write-Host "2. Export Full Report" Write-Host "0. Back" } function Show-BulkMenu { Write-Host "`n--- Bulk ---" Write-Host "1. Bulk Enable Archive" Write-Host "0. Back" } # ================================ # Main Loop # ================================ do { Show-MainMenu $choice = Read-Host "Select option" switch ($choice) { 1 { Connect-EXO } 2 { Get-AllMailboxes | Format-Table } 3 { do { Show-ArchiveMenu $a = Read-Host "Select option" switch ($a) { 1 { Get-ArchiveEnabled | Format-Table } 2 { Get-ArchiveDisabled | Format-Table } 3 { Check-ArchiveSingle } 4 { Enable-ArchiveSingle } 5 { Disable-ArchiveSingle } } } while ($a -ne 0) } 4 { do { Show-ReportMenu $r = Read-Host "Select option" switch ($r) { 1 { Get-MailboxFullSizeReport | Format-Table -AutoSize } 2 { Export-MailboxFullReport } } } while ($r -ne 0) } 5 { do { Show-BulkMenu $b = Read-Host "Select option" switch ($b) { 1 { Bulk-Enable-Archive } } } while ($b -ne 0) } 6 { Disconnect-EXO } } Pause } while ($choice -ne 0) Write-Host "Exiting..." -ForegroundColor Yellow