Introduction to Mailbox Quotas in Exchange 2016

Mailbox quotas play a vital role in managing storage resources within Exchange 2016. They serve as limitations imposed on the amount of data that users can store in their mailboxes. By defining these quotas, organizations can effectively monitor and control the consumption of storage resources, ensuring that users do not exceed their allocated limits. Mailbox quotas prevent performance degradation that can occur when mailboxes reach their maximum capacity, which can adversely affect user experience and system reliability.

In Exchange 2016, there are primarily two types of mailbox quotas: default and custom quotas. Default quotas are set by the system and apply universally across user mailboxes, providing a baseline level of storage for users. Custom quotas, on the other hand, are tailored to the specific needs of individual users or groups. Organizations may choose to implement custom quotas for various reasons, such as accommodating users with higher storage needs due to their role or ensuring compliance with specific regulatory requirements.

The necessity to update mailbox quotas arises from the dynamic nature of organizational needs. As businesses grow and evolve, the volume of email and other data stored by users can increase significantly. It is crucial for administrators to regularly assess and adjust these quotas to maintain a balance between resource availability and performance. This includes updating quotas to prevent interruptions in service delivery and ensuring users can access their emails without constraints. Maintaining compliance with storage policies is equally important, as adherence to these regulations helps avoid potential legal ramifications and ensures efficient use of resources.

Using PowerShell to Update Mailbox Quotas

I put together a script for a friend who needed to update over 5000 mailbox quotas but not affect users who have customer quotas set that were over 10GB and also not update any system mailboxes.

Here is the script, you can add one mailbox to test with before running it against every mailbox:

 

# Load Exchange Management Shell
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn -ErrorAction SilentlyContinue

# Get all user mailboxes (excluding system mailboxes)
$mailboxes = Get-Mailbox -ResultSize Unlimited | Where-Object {
    # Exclude system mailboxes
    if ($_.RecipientTypeDetails -match "DiscoveryMailbox|Arbitration|AuditLog|PublicFolder|SystemMailbox") {
        Write-Host "Skipping system mailbox: $($_.Identity)"
        return $false
    }

    # Get mailbox statistics
    $mailboxStats = Get-MailboxStatistics $_.Identity
    $mailboxSizeGB = 0  # Default for mailboxes that have never logged in

    if ($mailboxStats.TotalItemSize -ne $null) {
        # Extract numeric size (handles MB and GB properly)
        $sizeMatch = [regex]::Match($mailboxStats.TotalItemSize.Value, "(\d+(\.\d+)?)\s*(MB|GB)")
        if ($sizeMatch.Success) {
            $sizeValue = [double]$sizeMatch.Groups[1].Value
            $unit = $sizeMatch.Groups[3].Value
            $mailboxSizeGB = if ($unit -eq "MB") { $sizeValue / 1024 } else { $sizeValue }
        }
    }

    # Get current quota settings
    $mailbox = Get-Mailbox $_.Identity
    if ($mailbox.UseDatabaseQuotaDefaults -eq $false -and $mailbox.ProhibitSendQuota -ne "Unlimited") {
        # Handle ProhibitSendQuota that is not Unlimited
        $currentQuota = $mailbox.ProhibitSendQuota
        if ($currentQuota -eq "Unlimited") {
            Write-Host "Skipping $($_.Identity) (Quota is set to Unlimited)"
            return $false  # Skip mailbox with unlimited quota
        }

        # Convert the quota size to GB for comparison
        $currentQuotaGB = [double]$currentQuota.Value.ToGB()
        if ($currentQuotaGB -ge 10) {
            Write-Host "Skipping $($_.Identity) (Quota is already set to $($mailbox.ProhibitSendQuota) - greater than or equal to 10GB)"
            return $false  # Skip this mailbox
        }
        elseif ($currentQuotaGB -lt 10) {
            Write-Host "Mailbox $($_.Identity) has a custom quota set ($currentQuotaGB GB), updating quota..."
            return $true  # Proceed to update quota for this mailbox
        }
    }

    Write-Host "Mailbox: $($_.Identity) - Size: $mailboxSizeGB GB (Login: $($mailboxStats.LastLogonTime))"

    # Include mailboxes with size ≤ 10GB or that have never logged on
    return ($mailboxSizeGB -le 10 -or $mailboxStats.LastLogonTime -eq $null)
}

# If no mailboxes match, exit early
if ($mailboxes.Count -eq 0) {
    Write-Host "No matching mailboxes found. Exiting..."
    exit
}

# Apply quota and enable features
foreach ($mailbox in $mailboxes) {
    Write-Host "Processing mailbox: $($mailbox.Identity)"

    try {
        # Ensure quotas are applied even if using database defaults
        Set-Mailbox -Identity $mailbox.Identity -UseDatabaseQuotaDefaults $false -ProhibitSendQuota 10GB -ProhibitSendReceiveQuota 10GB -IssueWarningQuota 9GB -ErrorAction Stop
        Write-Host "✔ Quota updated for $($mailbox.Identity)"
    }
    catch {
        Write-Host "❌ Failed to set quota for $($mailbox.Identity): $_"
    }

    try {
        # Enable MAPI, ActiveSync, and OWA (forcing change)
        Set-CASMailbox -Identity $mailbox.Identity -MAPIEnabled $true -ActiveSyncEnabled $true -OWAEnabled $true -ErrorAction Stop
        Write-Host "✔ Features enabled for $($mailbox.Identity)"
    }
    catch {
        Write-Host "❌ Failed to enable features for $($mailbox.Identity): $_"
    }
}

# Confirm changes
Write-Host "`n📌 Final mailbox quota settings:"
$mailboxes | ForEach-Object {
    Get-Mailbox $_.Identity | Format-List DisplayName,UseDatabaseQuotaDefaults,ProhibitSendQuota,ProhibitSendReceiveQuota,IssueWarningQuota
    Get-CASMailbox $_.Identity | Format-List DisplayName,MAPIEnabled,ActiveSyncEnabled,OWAEnabled
}

Write-Host "`n✅ Script completed successfully!"

Here are some snippets from my lab:

Updating mailbox quotas in exchange 2016 with powershell: excluding custom quotas over 10gb
Updating mailbox quotas in exchange 2016 with powershell: excluding custom quotas over 10gb
Updating mailbox quotas in exchange 2016 with powershell: excluding custom quotas over 10gb
Updating mailbox quotas in exchange 2016 with powershell: excluding custom quotas over 10gb

Discover more from Everything-PowerShell

Subscribe now to keep reading and get access to the full archive.

Continue reading