Skip to content

Instantly share code, notes, and snippets.

@Crosse
Last active July 21, 2016 16:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Crosse/d9378e97a0d56869b929ab49d71fe21f to your computer and use it in GitHub Desktop.
Save Crosse/d9378e97a0d56869b929ab49d71fe21f to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
Removes messages matching a search query from all mailboxes in Exchange.
.DESCRIPTION
Removes messages matching a search query from all mailboxes in Exchange. This script is simply a wrapper
around Search-Mailbox adding the ability to break up mailbox searches into smaller batches. In fact,
it can be argued that unless you really want progress reports throughout the process, you should probably
just use Search-Mailbox instead.
.EXAMPLE
Remove messages from all mailboxes received after 6/3/2016 with the subject line "New Notification Regarding Your Payroll":
Remove-MaliciousMessages.ps1 -TargetMailbox spam@contoso.com -TargetFolder "SearchLog" -SearchQuery 'Received:>=6/3/2016 AND Subject:(New Notification Regarding Your Payroll)'
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]
# The TargetMailbox parameter specifies the identiy of the destination mailbox where search results are copied.
$TargetMailbox,
[Parameter(Mandatory=$true)]
[string]
# The TargetFolder parameter specifies a folder name in which search results are saved in the target mailbox.
$TargetFolder,
[Parameter(Mandatory=$true)]
[string]
# The SearchQuery parameter specifies a search string or a query formatted using
# Advanced Query Syntax (2010) or Keyword Query Syntax (2016).
# See https://technet.microsoft.com/en-us/library/dd298173.aspx for examples.
$SearchQuery,
[Parameter(Mandatory=$false)]
[switch]
# The DeleteContent switch specifies that the messages returned by the search be permanently deleted from the source mailbox.
# Deleted messages are copied to the target mailbox and removed from the source mailbox.
# Before you use the Delete Content switch, we recommend that you test search parameters.
$DeleteContent = $false,
[Parameter(Mandatory=$false)]
[int]
# The number of mailboxes to search at a time. The default is 100.
$BatchSize = 100
)
$mboxes = Get-Mailbox -ResultSize Unlimited | Select-Object -ExpandProperty SamAccountName
# Use queues to process mailboxes in batches of 100. Not necessarily needed
# and probably over-thought; this simply breaks the mailbox search up into
# smaller chunks.
$q = New-Object System.Collections.Queue
foreach ($mbox in $mboxes) { $q.Enqueue($mbox) }
$r = New-Object System.Collections.Queue
while ($q.Count -gt 0) {
# Take the next $BatchSize mailboxes and search them.
while ($r.Count -lt $BatchSize -and $q.Count -gt 0) { $r.Enqueue($q.Dequeue()) }
if ($DeleteContent -eq $true) {
# If the user specified -DeleteContent, do as they say.
$r | Search-Mailbox -TargetMailbox $targetMailbox -TargetFolder $targetFolder -LogLevel Full `
-SearchQuery $searchQuery -DeleteContent #-Force
} else {
# The user didn't specify -DeleteContent, so just log what we would have done.
$r | Search-Mailbox -TargetMailbox $targetMailbox -TargetFolder $targetFolder -LogLevel Full `
-SearchQuery $searchQuery -LogOnly
}
$r.Clear()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment