← Archive

How to run a (targeted) compliance search for specific Exchange inboxes or OneDrive+SharePoint sites with PowerShell - Part 1

Archived post · originally published · may be out of date

Microsoft 365 · #Microsoft #Microsoft365 #PowerShell


Intro

I recently had to perform a compliance search that required me to target a particular department that included their users, SharePoint sites, and any other mailboxes or content associated with this department (including Shared Mailboxes). If you have previously used the Compliance Search web GUI, it becomes quickly apparent that using the web GUI is an arduous experience as it is slow to use and even more time consuming when selecting individual mailboxes and SharePoint sites especially in a large organization that has hundreds to thousands of such items. Like all good System Administrators, I turned to PowerShell to help streamline my search.

If you are like me you found the following guide and script from Microsoft (Use Content Search to search the mailbox and OneDrive site for a list of users) and unfortunately, also like me, you found that the provided script from Microsoft does not work due to authentication errors caused by MFA being enabled on your account[1]. Instead of reworking Microsoft's script to work with MFA access, I have decided to make a new script that utilizes the PnP PowerShell module instead of the SharePoint Online Management Shell. Secondly, there are issues with the New-ComplianceSearch cmdlet itself.

The Secret

The New-ComplianceSearch documentation provides incorrect information specifically in regard to the -ExchangeLocation and -SharePointLocation parameters with this comment being the source of the problem:

You can enter multiple values separated by commas. If the values contain spaces or otherwise require quotation marks, use the following syntax: `"Value1","Value2",..."ValueN"`.

The correct way to provide multiple mailboxes to the -ExchangeLocation parameter and multiple OneDrive or SharePoint sites to the -SharePointLocation is to use an array, and not to use multiple values all separated by commas as stated by Microsoft. So create an array, populate it with the content you wish to search, and then provide that variable to the New-ComplianceSearch cmdlet either under the -ExchangeLocation or -SharePointLocation parameters depending on what you are searching.

For example, let's say you have 100 specific mailboxes you would like to search then your array variable in PowerShell would look like this:

# Import CSV file
$Mailboxes = Import-Csv .\Mailboxes.csv

#Initialize the array
$ExchangeLocations = @()

#Loop through each item in the CSV to populate the array
foreach ($Mailbox in $Mailboxes) {

$ExchangeLocations += $Mailbox.User

}

The results of $ExchangeLocations will produce the following output below:

User1@owltec.ca 
user2@owltec.ca
User3@owltec.ca
.
.
User99@owltec.ca
User100@owltec.ca

After you have confirmed that your array has a proper list of all your required information then provide it to the New-ComplianceSearch cmdlet. For the example we previously used, the final result to create a search would be New-ComplianceSearch -ExchangeLocation $ExchangeLocations.

However, if you do follow Microsoft's guidance and your variable expresses its multiple values as separated by commas (or you just paste in a list of your values separated by commas) then it will not work as the search itself will either contain only one entry or will be blank altogether in the Purview Portal GUI.

User1@owltec.ca,User2@owltec.ca,User3@owltec.ca,..User99@owltec.ca,User100@owltec.ca

The Script

My script was originally designed to create three different compliance searches based on each location (Exchange, OneDrive, and SharePoint) with each portion shared below. Based on my requirements, my script is three separate and self-contained parts that I manually select, tweak and run based on my search requirements; feel free to combine all three parts together to make a more complete script that creates one compliance search.

Prerequisites

User
user1@owltec.ca
user2@owltec.ca
user3@owltec.ca
URL
https://[yourtenant].onmicrosoft.com/sites/Site1
https://[yourtenant].onmicrosoft.com/sites/Site2
https://[yourtenant].onmicrosoft.com/sites/Site3

Exchange

<#
Exchange Search
#>

$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]

# Connect to Microsoft Purview
Connect-IPPSSession

# Import CSV file
$Mailboxes = Import-Csv -path [PATHTOYOURCSVFILE]

#Initialize the array
$ExchangeLocations = @()

#Loop through each item in the CSV to populate the array
foreach ($Mailbox in $Mailboxes) {
	$ExchangeLocations += $Mailbox.User
}

#Create a new compliance search with the specific users 
New-ComplianceSearch -Name ($SearchName + "-Exchange") -ExchangeLocation $ExchangeLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch

OneDrive

OneDrive searches are the only searches that take more effort. Most people have a user's email/UPN that they will need to search and not the associated PersonalURL that is connected to that user's OneDrive. What we will do is use the user's email to find a PersonalURL, create a variable, and then use that variable with our search.

<#
OneDrive Search
#>

$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]

# Connect to Microsoft Purview and SharePoint
$Url = "https://[YOURTENANTNAME]-admin.sharepoint.com"
Connect-IPPSSession
Connect-PnPOnline -Url $Url -Interactive -ClientId [YOURCLIENTID]

# Import CSV file
$Mailboxes = Import-Csv -path [PATHTOYOURCSVFILE]

# Initialize the array
$ODLocations = @()
 
#Loop through each item in the CSV to populate the arrays
foreach ($Mailbox in $Mailboxes) {
	$PnPUser = Get-PnPUserProfileProperty -Account $Mailbox.User
	$ODLocations += $PnPUser.PersonalUrl
}

#Create a new compliance search with specific user OneDrives
New-ComplianceSearch -Name ($SearchName + "-OneDrive") -SharePointLocation $ODLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch

SharePoint

<#
SharePoint Search
#>

$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]

# Connect to Microsoft Purview
Connect-IPPSSession

# Import CSV file
$SPSites = Import-Csv -path [PATHTOYOURCSVFILE]

#Initialize the array
$SPLocations = @()

#Loop through each item in the CSV to populate the array
foreach ($SPSite in $SPSites) {
	$SPLocations += $SPSite.URL
}

#Create a new compliance search with the specific SharePoint sites
New-ComplianceSearch -Name ($SearchName + "-SharePoint") -SharePointLocation $SPLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch

  1. This error is related to MFA access requirements. Turning off MFA for an account is not a practical option nowadays but I did try that at one point but that did not work. Another solution I heard is that one could bypass this by using an app password but this an not an option for me as well (and I also have not tried it on my end). Microsoft's script uses the SharePoint Online Management Shell module then uses the SharePoint assemblies from that module to authenticate via auth cookies but generates the following error when run: "Exception calling "GetAuthenticationCookie" with "1" argument(s): "The sign-in name or password does not match one in the Microsoft account system." ↩︎