Description
I’ve had several client ask me lately how to set retention periods on mailboxes, and, equally important, how to make sure that all newly created mailboxes have the policy applied. Some organizations will have more than one admin who creates mailbox enabled user accounts, and leaving it up to the admins to manually set the account for a retention policy is just prone to mistakes.
I won’t go into a lot of detail talking about what MRM is and what can be done. It’s already been covered many times on other sites, including this short but informative video from the Exchange product group. This article assumes that you have a working policy already in place. What I’ll cover here is how to use PowerShell to be consistent in applying an MRM policy to all users. For the most part, we’ll “set it and forget it”.
We can use PowerShell to apply an MRM policy using the ManagedFolderMailboxPolicy parameter of the Set-Mailbox cmdlet. This script basically looks for all users who are not resource accounts, not disabled, and don’t already have a policy applied (since we don’t generally want to override that). We do that with this line:
$MBXArray = @(Get-Mailbox | Where-Object {($_.RecipientType -eq 'UserMailbox') -and ($_.UserAccountControl -notmatch 'AccountDisabled') -and ($_.ManagedFolderMailboxPolicy -eq $null)})
$MBXArray is thus a list of mailboxes that pass the query. We then cycle through the array with ForEach and apply a policy to each mailbox using Set-Mailbox, like this:
Set-Mailbox -identity $Mailbox.SAMAccountName -ManagedFolderMailboxPolicy $strPolicyName -ManagedFolderMailboxPolicyAllowed
I use the -ManagedFolderMailboxPolicyAllowed parameter to get past confirmation prompts, since we’ll run the PowerShell script has a Windows scheduled task. $strPolicyName is a variable that holds the name of the policy we’d like to apply.
That’s simple enough, really. But it’s generally a good idea to have some sort of record that a policy was applied. PowerShell gives us a couple of ways to record the event, and we’ll use both.
First, when the script first starts, we’ll write an event to the application event log noting that the script is starting. First, set some variables and create a new object with
$strWhoAmI = $MyInvocation.MyCommand.Name
$evt.Source=$strWhoAmI
$evt=new-object System.Diagnostics.EventLog("Application")
$infoevent=[System.Diagnostics.EventLogEntryType]::Information
The first line actually creates a variable, $strWhoAmI, and assigns it the name of the PowerShell script. The second line sets that same info to be the source of the event log entry we’re about to write.
We use the two lines below to set the text for the event log, and write it.
$strEventLogText = "Beginning processing."
$evt.WriteEntry($strEventLogText,$infoevent,70)
When the script is finished, we also write another event log entry to say we’re done, along with a count of how many mailboxes were processed.
Next is where we build some flexibility into the script. At the beginning of the script, we define another variable, $strLogEachUser (and set it to $false) to disable writing an event log entry for EACH user we apply a policy to. In larger environments, it’s not a good idea to have that set to $true when the script runs the first time, as it can result in a LOT of event log entries. But, after that, it might provide some valuable information. The log entry will look something like
Messaging Records Management policy ‘MyManagedFolderPolicy’ applied to Claudia Richard
The next logging option we have is to stamp the actual AD account when we apply the policy to it. We do this by using one of the Custom Attributes available on Active Directory objects. For a user account, there are 15 Custom Attributes, and they can be viewed by opening a recipient in Exchange Management Console, and clicking on the Custom Attributes button near the bottom of the General tab. We’ll use Custom Attribute 13 for this example. This is easily accomplished by using the -CustomAttribute13 parameter of the Set-Mailbox cmdlet.We assign the text we’ll use with the $strMRM variable near the top of the script:
$strMRM = "MRM policy applied by " + $strWhoAmI + " " + $strToday
This allows for the script name, policy name, and a time stamp, and looks like this:
MRM policy applied by AutoApplyMRMPolicy.ps1 05/16/2009 12:16:38
The last feature built in is a status indicator while the script is running. This probably won’t be very valuable unless you plan to only ever manually run the script. The status indicator is disabled by default, but can be enabled by changing
$strShowStatus = $false
to
$strShowStatus = $true
it’s the same status indicator you see when doing many tasks at one time, such as moving or export mailboxes.
Here’s the finished script. Save it as AutoApplyMRMPolicy.ps1 in your \scripts folder on your Exchange server. Edit the three variables under the header block to suit your needs.
###############################################################################
# AutoApplyMRMPolicy.ps1 by Pat Richard, MVP
# https://www.ucunleashed.com/85
#
# Automatically apply a Messaging Records Management policy to
# all users who are:
# a) not resource accounts
# b) not disabled
# c) don't already have a policy applied
#
# This script is designed to be run as a Windows Scheduled task on an Exchange
# server.
#
# UPDATES
# =======
# v1.3 05/22/2009 Updated array per Nick's additional suggestions
# v1.2 05/19/2009 Updated array per Nick's suggestions
# v1.1 05/15/2009 Added status indicator;
# cleaned up/added event log entries
# added variables for enabling/disabling each
# v1.0 04/30/2009 Initial version
#
# Simply edit the settings below to fit your needs
###############################################################################
$strPolicyName = 'MyManagedFolderPolicy'
$strLogEachUser = $false
$strShowStatus = $false
############ DO NOT EDIT ANYTHING BELOW THIS LINE ############
$strToday = Get-Date
$strWhoAmI = $MyInvocation.MyCommand.Name
$strMRM = "MRM policy applied by " + $strWhoAmI + " " + $strToday
$evt=new-object System.Diagnostics.EventLog("Application")
$evt.Source=$strWhoAmI
$infoevent=[System.Diagnostics.EventLogEntryType]::Information
$strEventLogText = "Beginning processing."
$evt.WriteEntry($strEventLogText,$infoevent,70)
$MBXArray = @(Get-Mailbox | ? {($_.RecipientType -eq 'UserMailbox') -and ($_.UserAccountControl -notmatch 'AccountDisabled') -and ($_.ManagedFolderMailboxPolicy -eq $null)})
ForEach ($Mailbox in $MBXArray) {
$x=$x+1
if($strShowStatus){
Write-Progress -id 1 -activity "Applying Messaging Records Management policy '$strPolicyName'" -status $Mailbox.SAMAccountName -percentComplete (100/$MBXArray.count*$x) -CurrentOperation '' -SecondsRemaining ($MBXArray.count-$x)
}
Set-Mailbox -identity $Mailbox.SAMAccountName –ManagedFolderMailboxPolicy $strPolicyName -ManagedFolderMailboxPolicyAllowed -CustomAttribute13 $strMRM
if($strLogEachUser){
$strEventLogText = "Messaging Records Management policy '$strPolicyName' applied to "+$mailbox.DisplayName
$evt.WriteEntry($strEventLogText,$infoevent,70)
}
}
############ Blank line after next line is intentional for cleaner event log entry ############
$strEventLogText = "Finished processing "+$MBXArray.count+" accounts.
For more information on Messaging Records Management, see http://technet.microsoft.com/en-us/library/bb310756.aspx."
$evt.WriteEntry($strEventLogText,$infoevent,70)
Create a scheduled task
The last piece of this is a scheduled task. This is quite easy. Go to Scheduled Tasks on the server (Control Panel–> Scheduled Tasks). Right click and choose New>Scheduled Task. Call the task what ever you like, such as AutoApplyMRMPolicy. Right click the task and choose Properties. For the RUN field, paste this:
c:\windows\system32\windowspowershell\v1.0\powershell.exe -psconsolefile "c:\Program Files\Microsoft\Exchange Server\bin\exshell.psc1" -Command "AutoApplyMRMPolicy.ps1"
but change the -psconsole parameter to point to your \bin folder. The default path is shown. For the START IN field, enter the path to your \scripts folder, such as the default:
"c:\program files\microsoft\exchange server\scripts"
Set RUN AS to an administrator account. Click the Schedule tab and configure the task to run at least once a day. Be careful to ensure that it runs outside of your backup and maintenance windows. Click Ok. That’s all there is to it.
Some things to note:
The script will apply a policy to ALL users who are not disabled, resource accounts, or already configured for a policy. If you need it to be more restrictive, alter the line that starts with “$MBXArray =”
There is no error checking in the script. If there is enough call for that, I’ll work that into the script.
Feel free to make suggestions as to how to improve the script.
UPDATED 5/22/09: Cleaned up the array stuff a little per more Nick’s suggestions. Thanks, Nick!
Installation
Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.
Donations
I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.
Follow Me