Step-By-Step: Identifying Large Exchange Mailbox Folders Via PowerShell

Identifying users with large Exchange mailboxes is a task undertaken by most system administrators who are in need of freeing up space on their mail servers. While most search for mailboxes approaching a certain size, I wanted to take this a step further and identify the large folders within user mailboxes. An example of this would be to find all the users who have a large Deleted Items folder or Sent Items or Calendar that would be eligible to be cleaned out. It’s made to be run from a Remote Exchange Management Shell connection instead of by logging into an Exchange server via remote desktop and running such a shell manually.

Let’s get started by defining the function and parameters:

{

    [CmdletBinding()]

    param (

        [Parameter(Mandatory = $False)]

        [ValidateSet('All', 'Calendar', 'Contacts', 'ConversationHistory', 'DeletedItems', 'Drafts', 'Inbox', 'JunkEmail', 'Journal', 'LegacyArchiveJournals', 'ManagedCustomFolder', 'NonIpmRoot', 'Notes', 'Outbox', 'Personal', 'RecoverableItems', 'RssSubscriptions', 'SentItems', 'SyncIssues', 'Tasks')]

        [string]$FolderScope = 'All',

        [Parameter(Mandatory = $False)]

        [int]$Top = 1,

        [Parameter(Mandatory = $False,

                Position = 1,

        ValueFromPipeline = $True)]

        [string]$Identity = '*'

    )

}

This function is to be named Get-LargeFolder and takes three parameters.

  1. $FolderScope is used in the Get-MailboxFolderStatistics cmdlet and must belong to the set of values specified.
     
  2. $Top is an integer used to define how many results we’re going to return
     
  3. $Identity can be specified as an individual username to examine a specific mailbox, or left blank (defaulted to *) to examine the entire organization.

 

function Get-LargeFolder

{

    [CmdletBinding()]

    param (

        [Parameter(Mandatory = $False)]

        [ValidateSet('All', 'Calendar', 'Contacts', 'ConversationHistory', 'DeletedItems', 'Drafts', 'Inbox', 'JunkEmail', 'Journal', 'LegacyArchiveJournals', 'ManagedCustomFolder', 'NonIpmRoot', 'Notes', 'Outbox', 'Personal', 'RecoverableItems', 'RssSubscriptions', 'SentItems', 'SyncIssues', 'Tasks')]

        [string]$FolderScope = 'All',

        [Parameter(Mandatory = $False)]

        [int]$Top = 1,

        [Parameter(Mandatory = $False,

                Position = 1,

        ValueFromPipeline = $True)]

        [string]$Identity = '*'

    )

 

    Get-Mailbox -Identity $Identity -ResultSize Unlimited |

    Get-MailboxFolderStatistics -FolderScope $FolderScope

}

Next I’ve added a lines to retrieve all of my organizations mailboxes which I direct the data stream into a Get-MailboxFolderStatistics command with the FolderScope parameter set to the same value we passed to our function. Now we need to sort the results.

function Get-LargeFolder

{

    [CmdletBinding()]

    param (

        [Parameter(Mandatory = $False)]

        [ValidateSet('All', 'Calendar', 'Contacts', 'ConversationHistory', 'DeletedItems', 'Drafts', 'Inbox', 'JunkEmail', 'Journal', 'LegacyArchiveJournals', 'ManagedCustomFolder', 'NonIpmRoot', 'Notes', 'Outbox', 'Personal', 'RecoverableItems', 'RssSubscriptions', 'SentItems', 'SyncIssues', 'Tasks')]

        [string]$FolderScope = 'All',

        [Parameter(Mandatory = $False)]

        [int]$Top = 1,

        [Parameter(Mandatory = $False,

                Position = 1,

        ValueFromPipeline = $True)]

        [string]$Identity = '*'

    )

 

    Get-Mailbox -Identity $Identity -ResultSize Unlimited |

    Get-MailboxFolderStatistics -FolderScope $FolderScope |

    Sort-Object -Property @{

        e = {

            $_.FolderSize.split('(').split(' ')[-2].replace(',','') -as [double]

        }

    } -Descending

}

The FolderSize parameter returns with a Get-MailboxFolderStatistics cmdlet which is a string to be split up to provide only the value in bytes which I am casting to a double. Once the stats have been gathered and set in order, they need to be selected so they can be returned. 

The complete script is as follows:

function Get-LargeFolder

{

    [CmdletBinding()]

    param (

        [Parameter(Mandatory = $False)]

        [ValidateSet('All', 'Calendar', 'Contacts', 'ConversationHistory', 'DeletedItems', 'Drafts', 'Inbox', 'JunkEmail', 'Journal', 'LegacyArchiveJournals', 'ManagedCustomFolder', 'NonIpmRoot', 'Notes', 'Outbox', 'Personal', 'RecoverableItems', 'RssSubscriptions', 'SentItems', 'SyncIssues', 'Tasks')]

        [string]$FolderScope = 'All',

        [Parameter(Mandatory = $False)]

        [int]$Top = 1,

        [Parameter(Mandatory = $False,

                Position = 1,

        ValueFromPipeline = $True)]

        [string]$Identity = '*'

    )

 

    Get-Mailbox -Identity $Identity -ResultSize Unlimited |

    Get-MailboxFolderStatistics -FolderScope $FolderScope |

    Sort-Object -Property @{

        e = {

            $_.FolderSize.split('(').split(' ')[-2].replace(',','') -as [double]

        }

    } -Descending |

    Select-Object -Property @{

        l = 'NameFolder'

        e = {

            $_.Identity.Split('/')[-1]

        }

    },

    @{

        l = 'FolderSize'

        e = {

            $_.FolderSize.split('(').split(' ')[-2].replace(',', '') -as [double]

        }

    } -First $Top

}

This can now be accomplished once completed:

#Get 25 largest Deleted Items folders in your organization

Get-LargeFolder -FolderScope 'DeletedItems' -Top 25

 

#Get my largest 10 folders

Get-LargeFolder -Identity ThmsRynr -Top 10

 

#Get the top 25 largest Deleted Items folder for users in a specific group

$arrLargeDelFolders = @()

(Get-ADGroupMember 'GroupName' -Recursive).SamAccountName | ForEach-Object -Process {

    $arrLargeDelFolders += Get-LargeFolder -FolderScope 'DeletedItems' -Identity $_

}

$arrLargeDelFolders |

Sort-Object -Property FolderSize -Descending |

Select-Object -Property NameFolder, @{

    l = 'FolderSize (Deleted Items)'

    e = {

        '{0:N0}' -f $_.FolderSize

    }

} -First 25 |

Format-Table -AutoSize