Add users to Security and Compliance Retention Policy with Powershell

To preserve your Office 365 content you can use Retention Policy that you can create in the Security and Compliance Center. An important step is to add users to the policy. This can easily be done with PowerShell. This way we can also automatically add new users to an existing retention policy by running a script once a day or week.

Before we are going to add the retention policy, we first want to find all users that don’t have one yet. So we will get a list of all the users through Exchange and apply a policy to them.

By using PowerShell we can get a list of all your Exchange mailboxes and get a list of all the currently added Exchange locations (users) in the retention policy. Those two compared will result in a list of missing mailboxes which we can be added to the retention policy with Powershell.

Import note: First connect to Exchange Online and then to the Security and Compliance Center. Otherwise, you will get a different result from the get-recipient command.

Connecting to the Office 365 Exchange Online

Connect to Exchange Online with the code below or this connector script on my Microsoft Technet Gallery

$cred = get-credential $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $cred -Authentication Basic -AllowRedirection Import-PSSession $ExchSession

Connecting to the Office 365 Security & Compliance Center using remote PowerShell

You can connect to the Security and Compliance Center with the following command or this script

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $cred -Authentication Basic -AllowRedirection

Import-PSSession $Session

Getting a list of all your users with a mailbox

So first we start with creating a list of all the mailboxes that we want to preserve. With Get-Recipient we get all the existing recipient objects in your organization. To compare the list, we only need the PrimarySmtpAddress. By using the select cmd we can limit the results and select only the fields that we need.

Make sure you sort the results, so we can compare it later.

$ExchUsers = Get-Recipient -ResultSize Unlimited -RecipientType UserMailbox | select PrimarySmtpAddress | sort-object PrimarySmtpAddress

If you are using SharePoint or OneDrive in your organization you probably have some external users listed in Office 365. (Check it in the Office 365 Admin Center > Guest Users). You want to exclude those users from the results. We can do this based on the Alias and filter all the results that don’t contain the EXT mark: $_.Alias -notlike '#EXT#'.

I had also some address that didn’t need to be added, exclude them with $_.primarySmtpAddress -notlike '*'

With both where clauses in it you get the following command:

$ExchUsers = Get-Recipient -ResultSize Unlimited -RecipientType UserMailbox | where {( $_.Alias -notlike '#EXT#' ) -and ( $_.primarySmtpAddress -notlike '*' )} | select PrimarySmtpAddress | sort-object PrimarySmtpAddress

Get all the current mailboxes in the retention policy

To get all the users there are currently in the retention policy, we will first have to look up the name or GUID of the policy. Run the following command to get the policies with the names and GUID. The GUID isn’t necessary, but it might be easier to use the GUID than the name in the script.

Get-RetentionCompliancePolicy | select name,guid

This will return a table with all the Retention Policies in your Office 365 tenant.

Get-RetentionCompliancePolicy -Identity <policy-name or guid> -DistributionDetail | Select -ExpandProperty ExchangeLocation

To get all the mailboxes that already have a retention policy assigned to it, we need to expand the ExchangeLocation. This will give us a list of all objects with there names, email address, recourse type etc. To compare the lists we are going to sort the results on the name which is actually the email address:

$SecUsers = Get-RetentionCompliancePolicy -Identity <policy-name or guid> -DistributionDetail | Select -ExpandProperty ExchangeLocation | foreach {$_.Name} | sort-object $_.Name

Comparing the two and add the missing ones

All is left to compare to two arrays and add the missing users to the retention policy:

$notInSec = $exchUsers.primarySmtpAddress | Where {$secUsers -NotContains $_} foreach ($user in $notInSec){ Set-RetentionCompliancePolicy -Identity "<PolicyName>" -AddExchangeLocation $user }

8 thoughts on “Add users to Security and Compliance Retention Policy with Powershell”

  1. Thanks for the script Rudd, as you know retention policy can only contain 1000 users, how can we create a new policy and assign users to it when the existing policy reaches 1000 users. this would be really nice to have.

    • One option is to use the default policy instead of creating a custom one. Or create multiple policies and slit the user between based on the first letter of there name, for example:
      |? { $_.samaccountname -match '^[A-N]' }

  2. Great Article. I am a little unclear on the differences between an exchange MRM policy and the Office 365 retention policy. i understand them conceptually, but how does one tell if an email messages, or user mailbox, for instance has the office 365 retention policy applied or the exchange MRM policy applied?



  3. I am not able to get the list of User Accounts that have the Retention policy in Compliance using the following:

    Get-RetentionCompliancePolicy -Identity ” | Select-Object -ExpandProperty ExchangeLocation | foreach {$_.Name} | sort-object $_.Name

    I’m trying a simpler cmdlet:

    Get-RetentionCompliancePolicy -Identity ‘Exchange Retention Policy’ -ExpandProperty ExchangeLocation

    However it craps out stating that Parameter cannot be found that matches name ‘Expand Property’

  4. To get a list of current Exchange mailboxes in a policy, I had to use the following:
    $Mailboxes = (Get-RetentionCompliancePolicy -Identity “Policy” -DistributionDetail | Select -ExpandProperty ExchangeLocation)

    $(Foreach ($policyLocation in $Mailboxes) {
    New-Object PSObject -Property @{
    DisplayName = $policyLocation.DisplayName
    UPN = $
    } ) | select-object -Property DisplayName, UPN | Export-Csv -Path “PolicyUsers.csv” -NoTypeInformation

Leave a Comment