Managing user mailboxes to specific quotas with retention policies

Managing user mailboxes to specific quotas with retention policies

A little while ago, some of the Exchange MVPs were discussing a company’s desire to have size-based archiving rather than the age-based archiving that retention policies are designed to accomplish. As you might recall, you can define a retention policy that includes tags that use the “Move to Archive” action to instruct the Managed Folder Assistant (MFA) to move items that come under the scope of the policy to an archive mailbox after the retention period elapses.

It’s a scheme that works very well when you want to operate policies like “archive everything that’s more than 2 years old”, but it’s not so good when you encounter a requirement that archiving should occur on a phased basis to help users keep within their assigned mailbox quota. Another way of putting the requirement is to say that MFA should become more aggressive about moving items from the primary mailbox to the archive the larger a mailbox grows.

The initial reaction was that Exchange’s retention policies are not designed to cope with such a requirement. That is, until MVP Jeff Guillet came up with the brilliant insight that it is possible to construct a scheme where mailboxes are monitored for their size and retention policies are switched based on that size. As a mailbox gets bigger, a more aggressive policy is stamped on the mailbox to force MFA to archive items faster. The policy reduces the mailbox size and once a threshold is reached a different policy takes over to allow items to be retained in the mailbox for longer. It’s a simple and effective scheme that is easy to implement.

As it turns out, Jeff and I had a “blog clash” as both of us have written up the concept. Jeff’s take on it is available on his site. He tested his code against Exchange on-premises and hybrid deployments and includes some useful guidance on how to run a scheduled task to keep tabs on mailboxes.

The basic idea is illustrated as follows. Let’s assume that we want users to keep within a 2 GB mailbox quota. To achieve the goal, we deploy three retention policies.

  • Retention Policy 1 allows items to be retained in the mailbox for 90 days. It is applied when the mailbox is 1.65 GB or below.
  • Retention Policy 2 allows items to be retained for 60 days and is applied when the mailbox reaches 1.65 GB.
  • Retention Policy 3 reduces the retention period to 30 days and is applied once the mailbox reaches 1.8 GB.

The thresholds for the different levels are up to you and the values used here are just to illustrate the concept.

Each retention policy contains a default archive retention tag with the desired retention period. This tag will be stamped on any item in the mailbox that is not under the control of either a folder tag (for the default folders, such as the Inbox) or a personal tag (for non-default folders or specific items).

Although a retention policy usually contains a mixture of between six and fifteen default, folder, and personal tags, a policy is valid if it has just one tag. For example, the middle 60-day archive policy could be created with the following PowerShell commands:

New-RetentionPolicyTag –Name ‘Default -60 days to archive’ –RetentionEnabled $True –RetentionAction MoveToArchive –Type All –MessageClass * -AgeLimitForRetention 60
New-RetentionPolicy –Name ‘Retention Policy 2’ – RetentionPolicyTagLinks ‘Default - 60 days to archive’

Naturally, you can create retention tags and policies through the Exchange Administration Center (EAC) console if you prefer. The screen shot below shows the retention policy created with the two PowerShell commands.

Applying retention policies to mailboxes is easily done by running the Set-Mailbox cmdlet. However, we need some intelligence to control the policies. Jeff’s solution was to write a PowerShell script that can be run periodically to check mailbox sizes and assign policies based on those results. I’ve taken the script and made a couple of modifications. The core processing is performed by collecting a set of mailboxes that we want to control. To speed things up, mailboxes such as room mailboxes, discovery mailboxes, or shared mailboxes are excluded and one of the custom attributes is used to mark the user mailboxes to process.

Once we collect a set of mailboxes, a loop is used to check the current size of each mailbox using the Get-MailboxStatistics cmdlet. We set the retention policy based on the mailbox size and capture what we’ve done in a variable that is written to a different custom attribute for the mailbox. The information is also kept so that it can be later included in a report.

# Find the mailboxes who come under the control of dynamic retention
$Mbx = Get-Mailbox -ResultSize UnLimited –Filter {RecipientTypeDetails –eq 'UserMailbox' –and CustomAttribute10 –eq 'AA'}
# Process each mailbox, check their current mailbox size and stamp the appropriate policy. Also capture details in the mailbox and to a report file
ForEach ($M in $Mbx) {
  $Alias = $M.Alias
  $MbxSize = [math]::Round(((Get-MailboxStatistics -Identity $Alias).TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1GB),2)
  $OutMessage = "Mailbox Size " + $MbxSize +"GB" + " on " + (Get-Date)
  If ( $MbxSize -gt "1.8" ) {
   $RP = $RP1
  elseif ( $MbxSize -gt "1.65" ) {
  $RP = $RP2
  else {
  $RP = $RP3
  Set-Mailbox $Alias -RetentionPolicy $RP -CustomAttribute11 $OutMessage -ErrorAction SilentlyContinue
  $ReportRow = New-Object -Type PSObject -Property @{
         Name = $M.DisplayName 
         Policy = $RP
         Info = $OutMessage}
  $Report += $ReportRow

The somewhat obscure formatting of the $MbxSize variable is to put the mailbox size data returned by Get-MailboxStatistics into a format that can be used in the comparison. For whatever reason, Exchange likes to return its own type of data, especially for this cmdlet.

The HTML report that is generated by the script is just a bit of fancy output to demonstrate once again how easy it is to find some PowerShell code on the web and repurpose it to meet a need. 

Retention policies can be configured in this manner for Exchange 2010, Exchange 2013 (and Exchange 2016), and Exchange Online.

Once again, I am impressed at just how flexible Exchange really is, especially when PowerShell is involved. You can download a copy of the full script from the TechNet Gallery.

Follow Tony @12Knocksinna

TAGS: Office 365
Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.