Determine the Management Roles and Commands a user can run in Exchange PowerShell

Scenario –  You want to see what Management Roles and Commands a user can run from Exchange PowerShell

Scriptlet:

#Determine management role assignments for an account
    $1= Get-ManagementRoleAssignment -RoleAssignee <username>
    $1 | Select Role

#Determine what commands are associated with that account
#For a Single Role
Get-ManagementRole Monitoring | FL
    Get-ManagementRole Monitoring | Select -ExpandProperty RoleEntries | Select Name
    Get-ManagementRole Monitoring | Select -ExpandProperty RoleEntries |Sort Name | Select name

#For Multiple Roles from $1
$Roles = @()
    $1.role.name | %{
        $n = $_
        $temp = Get-managementrole $n | Select -ExpandProperty RoleEntries |Sort Name | Select -expandproperty name    

        $temp | %{
            $c = $_
            $ServerObj = New-Object PSObject
            $ServerObj | Add-Member NoteProperty -Name “ManagementRole” -value $n
            $ServerObj | Add-member NoteProperty -Name “Command” -Value $c
            $Roles += $ServerObj
        }

       $n = $null
        $c = $null
    }

#Display $roles
    $roles | Sort Command | Select Command, ManagementRole

 

Advanced PowerShell Select-Object Statements: Performing Get commands inside a Select-Object Statement (Tying the output from several commands by running one command)

Scenario: You want to pull in values/output from other commands into the output of a different command. In Exchange we know not all uniquely identifiable properties are attached to each exchange command:

Example: The Alias can be found in get-mailbox, but is not tied to the output of a get-mailboxstatistics command.

In the scriptlet below, we are going to tie together the following properties in a single one-liner using expressions within the Select-Object statement:

  • Displayname from  get-mailboxstastics
  • TotalItemSize & TotalDeletedItemSize from get-mailboxstatistics
  • HasActivesyncDevicePartnership from get-casmailbox
  • Alias from get-mailbox
  • MobileDevice Count from get-mobiledevice

 

Scriptlet:

Get-mailboxstatistics steve | Select Displayname,`
Total*Size,`
@{Name=”User_Email”;Expression={$u = $_.LegacyDN; (@(get-mailbox “$u”)).primarysmtpaddress}},`
@{Name=”Alias”;Expression={$u = $_.LegacyDN; (@(get-mailbox “$u”)).alias}}, `
@{Name=”HasActiveSyncDevicePartnership”;Expression={$u = $_.LegacyDN; (@(get-casmailbox “$u”)).HasActiveSyncDevicePartnership}}, `
@{Name=”MobileDeviceCount”;Expression={$u = $_.LegacyDN; (@(get-mobiledevice -mailbox “$u”)).count}}

Another example:  Pulling the Get-mailboxfolderpermission for the calendar, but including the primarysmtpaddress in the Select statement of the delegated user:

get-mailboxfolderpermission steve:calendar | Select FolderName,`
        User,`
        @{Name=”User_Email”;Expression={$u = $_.user; (@(get-mailbox “$u”)).primarysmtpaddress}},`
        AccessRights

 

 

 

 

EWS Script: Perform a RegEx search against all Items in a Mailbox and perform an action

Scenario:  Although RegEx searches are not supported within the Exchange toolset, here is an EWS Script that will perform two kinds of RegEx searches; Patterns AND exact matches (not case sensitive).

The script below is going to do the following:

  • If the mailbox item matches the RegEx, it will move the email item into a folder: BadFolder_Reg
  • If the mailbox item matches the Term, it will move the email item into a folder: BadFolder_Term
  • If any mailbox item has an attachment, it will download it into a directory

Scripts:

#Finding items With RegEx
#Variables
$cred = Get-credential  #credentials will fullaccess to access the mailbox
$mailboxname = “stevetest25@domain.com”  #The Mailbox you wish to perform the query and restore on
$EWS_DLL = “C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll”
$EWS_URL = “https://domain/ews/exchange.asmx&#8221;

#Configure connection to EWS
Import-Module -Name $EWS_DLL
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
$service.Url = new-object System.Uri($EWS_URL)
$service.UseDefaultCredentials = $false
$service.Credentials = $cred.GetNetworkCredential()

 

#Find all Mailbox folders
$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)

#Bind to BadFolders for RegEx and Terms
$BADfolder_Reg = $findFolderResults | Where displayname -like “BadFolder_Reg”
$BADfolder_Term = $findFolderResults | Where displayname -like “BadFolder_Term”

If($BadFolder_Reg -eq $null){
#Create a Folder called BAD on the Root
“Bad folder doesnt exist, creating it now”
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailboxname)
$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName = “BadFolder_reg”
$NewFolder.Save($Folder.id)

$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
#Find all folders in the mailbox
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)
$BADfolder_Reg = $findFolderResults | Where displayname -like “BadFolder_Reg”
}

If($BadFolder_Term -eq $null){
#Create a Folder called BAD on the Root
“Bad folder doesnt exist, creating it now”
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailboxname)
$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName = “BadFolder_Term”
$NewFolder.Save($Folder.id)

$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
#Find all folders in the mailbox
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)
$BADfolder_Term = $findFolderResults | Where displayname -like “BadFolder_Term”
}

#Create Variables for Search

$ItemPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$i = 0
$i_end = $findfolderResults.item.count
$reg = @()

$reg +=  “[1-9][0-9]{2}-[0-9]{2}-[0-9]{4}^d”

$reg += “(^|D)(d{3}-d{2}-d{4})(D|$)”

$DownloadDirectory = “\servershare$attachments”
$term = ” test123 “,” steve “,” batman “,” superman ”

#Loop each mail folder and perform the search
Do{
If(($findFolderResults.Folders[$i]).DisplayName -notlike “Badfolder*”){

“Checking Folder: $(($findFolderResults.Folders[$i]).DisplayName)”
$ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)

Do{
$AqsString = “System.Message.DateReceived:01/01/2000..12/31/2099”
$fiItems = $findFolderResults.Folders[$i].FindItems($AqsString,$ItemView)
$ItemView.offset += $fiItems.Items.Count
[Void]$service.LoadPropertiesForItems($fiItems , $ItemPropset)

foreach($Item in $fiItems.Items){
“Checking on $($Item.Subject)”
#Check for attachments#########################
If($item.Hasattachments -eq $true){
“Attachment Detected on $($Item.Subject)”
foreach($attach in $Item.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “” + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host “Downloaded Attachment : ” + (($downloadDirectory + “” + $attach.Name.ToString()))
}
}
#^Check for attachments#########################

#Check for Reg#########################
$reg_result = $false
$b_temp = $Item.body.text
#Loop regex
$reg | %{
$r = $b_temp -match “$_”
“Result: $r”
if($r -eq $true){“Setting $reg_result to $r”;$reg_result = $true}
}

#display
“$Reg_result – The MSG with Subject: $($Item.subject) ”

If($reg_result -eq $true){
“Moving $($Item.Subject) to BadFolder_reg”
[VOID]$Item.Move($BadFolder_reg.Id)}
#^Check for Reg##################################################

#Check for Terms#########################
$Term_result = $false
$b_temp = $Item.body.text
#Loop term
$term | %{

$rr = $b_temp -match $_
“Result: $rr”
if($rr -eq $true){“Setting $term_result to $rr”;$term_result = $true}
$term_temp = $null
}

#display
“$term_result – The MSG with Subject: $($Item.subject) ”

If($term_result -eq $true){
“Moving $($Item.Subject) to BadFolder_term”
[VOID]$Item.Move($BadFolder_term.Id)}
#^Check for Terms##################################################

#clean var
$r = $null
$b_temp = $null

}
}While($fiItems.moreavailable -eq $true)
}

$i++
“FolderID Counter $i”

}While ($i -le $i_end)

 

 

CMD: Determine the current Schema Versions before applying a Exchange CU

Scenario: You are going to install the latest CU for Exchange, but you want to check the AD Schema levels to see if they need to be upgraded before the CU install

Command Line:  Using CMD line, run the following: (Everything in bold needs to be edited to reflect your Exchange organization OR your domain)

dsquery * "cn=Enterprise Exchange,cn=Microsoft Exchange,cn=services,cn=configuration,dc=root,dc=domain,dc=com" -scope base -attr msExchProductID

dsquery * "cn=Enterprise Exchange,cn=Microsoft Exchange,cn=services,cn=configuration,dc=root,dc=domain,dc=com" -scope base -attr objectVersion

dsquery * "CN=Microsoft Exchange System Objects,DC=child,DC=root,DC=domain,DC=com" -scope base -attr objectVersion

dsquery * cn=ms-Exch-Schema-Version-Pt,cn=schema,cn=configuration,dc=root,dc=domain,dc=com -scope base -attr rangeUpper

QuotaExceededException – Error: Cannot save changes made to an item to store. –> MapiExceptionShutoffQuotaExceeded: Unable to save changes.

Scenario:  When performing a New-MailboxImportRequest, you receive the following error:

QuotaExceededException

Error: Cannot save changes made to an item to store. –> MapiExceptionShutoffQuotaExceeded: Unable to save changes.

Solution:  Increase the Quotas on the mailbox. It was the Recoverable quotas that were giving me an issue.

Set-Mailbox mailbox -RecoverableItemsWarningQuota 100GB -RecoverableItemsQuota 100GB -UseDatabaseQ
uotaDefaults $false -IssueWarningQuota unlimited -ProhibitSendQuota unlimited -ProhibitSendReceiveQuota unlimited

 

Mailbox attempts to automap to your Outlook after you have removed your full mailbox permissions

Scenario:  You have removed your full access permission (with automap) from a mailbox, but your Outlook still attempts to automap to it.

Solution:  Check the msexchdelegatelistlink property and clear it if your entry still exists:

Check the Property:   Get-aduser  steve -properties msexchdelegatelistlink

Clear the property:  Set-aduser steve -clear “msexchdelegatelistlink”

EWS Script: Record Mailbox Size per Year and Export into Multiple PSTs.

Scenario:  You want to use a EWS Script to perform two functions:

-Calculate the total size of the mailbox per year. This includes both the Mailbox and the Mailbox Dumpster.

-Export a PST for each year.  If the size of the yearly emails exceeds 10GB, adjust the dates within that year so each export for that year is under 10GB.

Script:

#Edit Variables############################
$mailboxname = “steve@domain.com”
$Export_Log = “C:tempMbx_Size_Years.csv”
$Export_PST = “\ExServerPSTFiles”
$PSTFilePath = $Export_PST
$Batchname = “Steve”
$Size_for_PST = [int]10240
$PST_Final = @()
$EWSServer = “https://mail.domain.com/EWS/Exchange.asmx&#8221;
##########################################

#Paste the Script#########################
Write-host “Starting $Mailboxname” -ForegroundColor Cyan
Import-Module -Name “C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll”
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
$service.Url = new-object System.Uri($EwsServer)

$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add(“System.DLL”) | Out-Null

$TASource=@’
namespace Local.ToolkitExtensions.Net.CertificatePolicy{
public class TrustAll : System.Net.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Net.ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Net.WebRequest req, int problem) {
return true;
}
}
}
‘@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance(“Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll”)
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll

#CAS URL Option 1 Autodiscover
$service.AutodiscoverUrl($MailboxName,{$true})
“Using CAS Server : ” + $Service.url
# Bind to the Inbox Folder
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)

#Define ItemView to retrive just 1000 Items
$ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$psPropset= new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::Size)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeCreated)
$ivItemView.PropertySet = $psPropset
$TotalSize = 0
$TotalItemCount = 0

#Define Function to convert String to FolderPath
function ConvertToString($ipInputString){
$Val1Text = “”
for ($clInt=0;$clInt -lt $ipInputString.length;$clInt++){
$Val1Text = $Val1Text + [Convert]::ToString([Convert]::ToChar([Convert]::ToInt32($ipInputString.Substring($clInt,2),16)))
$clInt++
}
return $Val1Text
}

#Define Extended properties
$PR_FOLDER_TYPE = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(13825,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
$folderidcnt = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$folderidcnt_r = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::RecoverableItemsRoot,$MailboxName)

#Define the FolderView used for Export should not be any larger then 1000 folders due to throttling
$fvFolderView =  New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)

#Deep Transval will ensure all folders in the search path are returned
$fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep;
$psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String);

#Add Properties to the  Property Set
$psPropertySet.Add($PR_Folder_Path);
$fvFolderView.PropertySet = $psPropertySet;

#The Search filter will exclude any Search Folders
$sfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($PR_FOLDER_TYPE,”1″)
$fiResult = $null
$rptHash = @{}
$minYear = (Get-Date).Year
$maxYear = (Get-Date).Year

#The Do loop will handle any paging that is required if there are more the 1000 folders in a mailbox
do {
$fiResult = $Service.FindFolders($folderidcnt,$sfSearchFilter,$fvFolderView)
$fiResult2 = $Service.FindFolders($folderidcnt_r,$sfSearchFilter,$fvFolderView)

$collection_folders = @()
$Collection_Folders = $firesult.folders
$Collection_Folders += $firesult2.folders

$firesult3 = @()
$firesult3 = $fiResult
$firesult3 += $fiResult2

foreach($ffFolder in $collection_Folders){
#foreach($ffFolder in $fiResult.Folders){
$foldpathval = $null
#Try to get the FolderPath Value and then covert it to a usable String
if ($ffFolder.TryGetProperty($PR_Folder_Path,[ref] $foldpathval))
{
$binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval)
$hexArr = $binarry | ForEach-Object { $_.ToString(“X2″) }
$hexString = $hexArr -join ”
$hexString = $hexString.Replace(“FEFF”, “5C00”)
$fpath = ConvertToString($hexString)
}
“FolderPath : ” + $fpath

#Define ItemView to retrive just 1000 Items
$ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$psPropset= new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::Size)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeCreated)
$ivItemView.PropertySet = $psPropset

$fiItems = $null
do{
$fiItems = $service.FindItems($ffFolder.Id,$ivItemView)
#[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
$dateVal = $null
if($Item.TryGetProperty([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[ref]$dateVal )-eq $false){
$dateVal = $Item.DateTimeCreated
}
if($rptHash.ContainsKey($dateVal.Year)){
$rptHash[$dateVal.Year].TotalNumber += 1
$rptHash[$dateVal.Year].TotalSize += [Int64]$Item.Size
}
else{
$rptObj = “” | Select TotalNumber,TotalSize
$rptObj.TotalNumber = 1
$rptObj.TotalSize = [Int64]$Item.Size
$rptHash.add($dateVal.Year,$rptObj)
if($dateVal.Year -lt $minYear){$minYear = $dateVal.Year}
}
}
$ivItemView.Offset += $fiItems.Items.Count
}while($fiItems.MoreAvailable -eq $true)
}
$fvFolderView.Offset += $collection_folders.Count
}while($fiResult3.MoreAvailable -eq $true)

$rptCollection = @()
$fnFinalreporttlt = “” | Select Name,TotalNumber,TotalSize, @{Name=”Mbx”;Expression={“$mailboxname”}}
$fnFinalreporttlt.Name = $MailboxName
$rptCollection += $fnFinalreporttlt
$fnFinalreport = “” | Select Name,TotalNumber,TotalSize,@{Name=”Mbx”;Expression={“$mailboxname”}}
$rptCollection += $fnFinalreport
$rptHash.GetEnumerator() | Sort-Object Name | ForEach-Object {
$fnFinalreport = “” | Select Name,TotalNumber,TotalSize,@{Name=”Mbx”;Expression={“$mailboxname”}}
$fnFinalreport.Name = $_.key
$fnFinalreport.TotalNumber = $rptHash[$_.key].TotalNumber
$fnFinalreport.TotalSize = [Math]::Round($rptHash[$_.key].TotalSize/1MB,2)
$fnFinalreporttlt.TotalNumber += $rptHash[$_.key].TotalNumber
$fnFinalreporttlt.TotalSize += [Math]::Round($rptHash[$_.key].TotalSize/1MB,2)
$rptCollection += $fnFinalreport
}

$rptCollection | Select Mbx,Name,TotalNumber,TotalSize

$rptCollection | Export-csv $export_log

############################

$tableStyle = @”
<style>
BODY{background-color:white;}
TABLE{border-width: 1px;
border-style: solid;
border-color: black;
border-collapse: collapse;
}
TH{border-width: 1px;
padding: 10px;
border-style: solid;
border-color: black;
background-color:#66CCCC
}
TD{border-width: 1px;
padding: 2px;
border-style: solid;
border-color: black;
background-color:white
}
</style>
“@

$body = @”
<p style=”font-size:25px;family:calibri;color:#ff9100″>
$TableHeader
</p>
“@

############################################

$PST_Size = $null

#Loop
$rptcollection | Where {($_.Name -ne “”) -and ($_.name -notlike “*@*”)} |  %{
#Declare Variables

$Size = [int]$_.TotalSize
$Name = $_.Mbx
$year = $_.Name
$Start = “1/1/$year”
$End = $Start;$End = [datetime]$End;$End = $end.AddYears(1);$End = $End.ToString(“M/d/yyyy”)

“`n`rStarting Loop for:  $Name – $Size – $Start <–> $End”

If((Test-Path $PSTFilePath$NAME) -eq $False){MD “$PSTFilePath$NAME”}
If($Size -lt $Size_For_PST){
$PSTName = $Name+”_”+$Start+”_”+$End
$PSTName = $PSTName -replace (“/”,”-“)
$F = “$PSTFilePath$Name$PstName.pst”
write-host “…..Size is less than $Size_for_PST” -foregroundcolor cyan
New-MailboxExportRequest -mailbox $Name -contentFilter {(Received -ge $start) -and (Received -le $end)} -name $PSTName -filepath $f -baditemlimit 1000000 -acceptlargedataloss -batchname $Batchname
}

If($Size -gt $Size_For_PST){
$R = [math]::Round($Size/$Size_For_PST)
If(($R -eq 0) -or ($R -eq 1)){$R = 2}
$Months = 12/$r
$count = 0
$LoopEnd = [datetime]$End
“Startin Loop  r = $R, months = $Months”

Do{
$Count++
write-host “Size is bigger than $Size_for_PST” -foregroundcolor green
$start = [datetime]$Start
If($start -ge (Get-date)){Break}
$end = $start.AddMonths($Months)
$start = $start.tostring(“M/d/yyyy”)
$end = $end.tostring(“M/d/yyyy”)
$PSTName = $Name+”_”+$Start+”_”+$End
$PSTName = $PSTName -replace (“/”,”-“)
$F = “$PSTFilePath$Name$PstName.pst”
“…..New Mailbox Export Request for $name for  $start –> $end”
$start = $End
$Loopstart = [datetime]$start
New-MailboxExportRequest -mailbox $Name -contentFilter {(Received -ge $start) -and (Received -le $end)} -name $PSTName -filepath $f -baditemlimit 1000000 -acceptlargedataloss -batchname $Batchname
}While($loopstart -ne $Loopend)
“End Loop”
}
}

 

Exchange PowerShell: Export a mailbox into multiple psts by size using native Exchange commands

Scenario:  Using native Exchange PowerShell commands, export a single mailbox into multiple 10GB PSTs (or another size). This is to mimic the eDiscovery tool in which it makes multiple PST’s that stay around 10GB each.

The script/commands below will perform a search mailbox until it hits the 10000 item limit.  When it hits the 10,000 item limit, it finds the previous  date where the search results is under the 10,000 item limit and records it.  Then the script will take all the dates it records and add the size until it hits around 10GB.  It records those dates in a array and then exports to a PST.

Script:

#Initialize Variables###########################################
$mbx = “Steve”
$stat = Get-mailboxstatistics $mbx | Select DisplayName,TotalDeletedItemSize, TotalItemSize,ItemCount
$TotalSize = [int]$stat.TotalItemSize.Value.ToMB() + [int]$stat.TotalDeletedItemSize.Value.ToMB()
$SizeforPST = [int]10240 ; “$MBX : Total Size $totalSize MB”
$CutThePST = “Yes”
$PSTFilePath =”\ExSvr1PSTFILES”
###############################################################

#If MBX totalsize is greater than $SizeforPST ###############################################################
If($TotalSize -gt $SizeforPST){

“Entering If Statement:  TotalSize ($TotalSize) is greater than $SizeForPST”

#Find Oldest Item in Mailbox to know when to stop searching
$OldestItem = Get-MailboxFolderStatistics $mbx -IncludeOldestAndNewestItems | Where OldestItemReceivedDate -ne $Null | Sort OldestItemReceivedDate | Select -ExpandProperty OldestItemReceivedDate -first 1
$oldestItem = $oldestItem.AddMonths(-1)  #Subtract a month to ensure that search goes before oldest item.
$OldestItem = $OldestItem.ToSTring((“M/d/yyyy”))
#Set Start and End Month 1 Month Apart
$end = get-date -Format “M/d/yyyy”
$start = [datetime]$end
$start= $start.AddMonths(-1)
$start = $start.ToString((“M/d/yyyy”))

#Initialize $results Variable and Final variable
$Results = Search-Mailbox $mbx -SearchDumpster -SearchQuery “Received:$start..$End” –estimateresultonly | Select ResultItemsCount,@{n=’Size’;e={([Microsoft.Exchange.Data.ByteQuantifiedSize]$_.ResultItemsSize).ToMb()}}
$final = @()

#Loop It –
Do{
If($results.ResultItemsCount -ge 10000){
Do{
$start= [datetime]$start
$start= $start.AddDays(5)
$start = $start.ToString((“M/d/yyyy”))
$Results = Search-Mailbox $mbx -SearchDumpster -SearchQuery “Received:$start..$End” –estimateresultonly | Select ResultItemsCount,@{n=’Size’;e={([Microsoft.Exchange.Data.ByteQuantifiedSize]$_.ResultItemsSize).ToMb()}}
“ResultCount: $results.ResultItemsCount between $start – $end”
}While($Results.ResultItemsCount -ge 10000)
}

If($Results.ResultItemsCount -lt 10000){
Do{
If([datetime]$Start -lt [datetime]$oldestitem){Break}
$start= [datetime]$start
$start= $start.AddMonths(-1)
$start = $start.ToString((“M/d/yyyy”))
$Results = Search-Mailbox $mbx -SearchDumpster -SearchQuery “Received:$start..$End” –estimateresultonly | Select ResultItemsCount,@{n=’Size’;e={([Microsoft.Exchange.Data.ByteQuantifiedSize]$_.ResultItemsSize).ToMb()}}
“ResultCount: $results.ResultItemsCount between $start – $end”
}While($Results.ResultItemsCount -lt 10000)

#Since ResultItemCount just became greater than or equal too 10000, subtract add a month to start.
$start= [datetime]$start
$start= $start.AddMonths(1)
$start = $start.ToString((“M/d/yyyy”))
$Results = Search-Mailbox $mbx -SearchDumpster -SearchQuery “Received:$start..$End” –estimateresultonly | Select ResultItemsCount,@{n=’Size’;e={([Microsoft.Exchange.Data.ByteQuantifiedSize]$_.ResultItemsSize).ToMb()}}

}

“Result Count: $($results.ResultItemsCount) Size $($results.size)”

#Build the Array
$ServerObj = New-Object PSObject
$ServerObj | Add-Member NoteProperty -Name “Alias” -Value $mbx
$ServerObj | Add-Member NoteProperty -Name “Start” -Value $start
$ServerObj | Add-Member NoteProperty -Name “End” -Value $end
$ServerObj | Add-Member NoteProperty -Name “ItemCount” -Value $results.ResultItemsCount
$ServerObj | Add-Member NoteProperty -Name “Size” -Value $results.Size
$Final += $ServerObj

#Recalibrate Variables
$end = $start
$start = [datetime]$end
$start= $start.AddMonths(-1)
$start = $start.ToString((“M/d/yyyy”))
$Results = Search-Mailbox $mbx -SearchDumpster -SearchQuery “Received:$start..$End” –estimateresultonly | Select ResultItemsCount,@{n=’Size’;e={([Microsoft.Exchange.Data.ByteQuantifiedSize]$_.ResultItemsSize).ToMb()}}

“While Start: $start > OldestItem: $oldestitem”
}While([datetime]$start -ge [datetime]$OldestItem)

$ServerObj = New-Object PSObject
$ServerObj | Add-Member NoteProperty -Name “Alias” -Value $mbx
$ServerObj | Add-Member NoteProperty -Name “Start” -Value $start
$ServerObj | Add-Member NoteProperty -Name “End” -Value $end
$ServerObj | Add-Member NoteProperty -Name “ItemCount” -Value $results.ResultItemsCount
$ServerObj | Add-Member NoteProperty -Name “Size” -Value $results.Size
$Final += $ServerObj
###########################################################################################################

#Create a PST Hash Table

$PST_Final = @()
$PSTSize = 999999

$Final | %{
“____________________________________”
“Starting Loop”

if($PSTSize -eq 999999){

$PSTSize = $_.Size
$PST_end = $_.End
$PST_Start = $_.Start
“1st Loop: $PST_Start — $PST_end — $PSTSize”

}else{

“Entering Else Loop”
$PST_Start_temp = $_.start
$PST_End_temp = $_.end

#When on second pass, add the two sizes together
$PSTSize_temp = $PSTSize + $_.Size
Write-host “PST Size = $PSTSize_Temp” -ForegroundColor Cyan

If($PSTSize_temp -lt $SizeForPST){
“..Less than $SizeForPST  ($PSTSize_Temp)”
$PSTSize = $PSTSize_Temp
$PST_Start = $PST_Start_Temp

“….New DateRange:  $PST_Start — $PST_END”

}

If($PSTSize_Temp -gt $SizeForPST){
“..Greater Than $SizeForPST ($PSTSize_temp)”
$ServerObj = New-Object PSObject
$ServerObj | Add-Member NoteProperty -Name “Alias” -Value $mbx
$ServerObj | Add-Member NoteProperty -Name “Start” -Value $PST_Start
$ServerObj | Add-Member NoteProperty -Name “End” -Value $PST_End
$ServerObj | Add-Member NoteProperty -Name “Size” -Value $PSTSize
$PST_Final += $ServerObj

$PST_END = $PST_Start
$PSTSize = [int]0

}

}

}

$ServerObj = New-Object PSObject
$ServerObj | Add-Member NoteProperty -Name “Alias” -Value $mbx
#$ServerObj | Add-Member NoteProperty -Name “Start” -Value $PST_Start
$ServerObj | Add-Member NoteProperty -Name “Start” -Value “1/1/1900”
$ServerObj | Add-Member NoteProperty -Name “End” -Value $PST_End
$ServerObj | Add-Member NoteProperty -Name “Size” -Value $PSTSize
$PST_Final += $ServerObj

$PST_FINAL

}

If($PST_Final -eq $null){
$ServerObj = New-Object PSObject
$ServerObj | Add-Member NoteProperty -Name “Alias” -Value $mbx
#$ServerObj | Add-Member NoteProperty -Name “Start” -Value $PST_Start
$ServerObj | Add-Member NoteProperty -Name “Start” -Value “1/1/1900”
$ServerObj | Add-Member NoteProperty -Name “End” -Value $(get-date -Format “M/d/yyyy”)
$ServerObj | Add-Member NoteProperty -Name “Size” -Value $TotalSize
$PST_Final += $ServerObj

}

#Export the PST for this user
If($CutThePST -eq “Yes”){

$PST_Final | %{
$N = $_.Alias
$S = $_.Start
$E = $_.End
$PSTName = $N+”_”+$S+”_”+$E
$PSTName = $PSTName -replace (“/”,”-“)
$F = “$PSTFilePath$PstName.pst”
New-mailboxExportRequest -mailbox $N -contentfilter {(Received -ge $s) -and (Received -le $e)} -name $PSTName -filepath $F -baditemlimit 1000000 -acceptlargedataloss
}
}

Use Search-Mailbox to perform a email item count based on specific words for multiple mailboxes

Scenario:  You are asked the question if you can provide a count of email items based on certain words per mailbox.

You sure can! I will give you a CLUE

We are going to look in each mailbox (the $mbx variable) for any email items that contain each word (in the $word variable).

Specifically, since I think it was Colonel Mustard, I will add his name as a AND statement in the KQL Search.  Because this game can be complex, I  will also include a NEAR statement to add a little of that complexity to the search-mailbox searchquery-KQL language.

Scriptlet:

#Variables
$mbx = “ProfessorPlum”, “MrsPeacock”, “MissScarlet”
$Word = “Candlestick”,  “Rope”,  “Wrench”
$word += “Ballroom NEAR(2) inside”, “Study NEAR(2) inside”, “Dining NEAR(2) Room”
$Result = @()

#Loop it
$mbx | %{
    $n = $_
    #Loop the Word
    $Word | %{
          $w = “$_”
          “Searching $n for word: $W”
          #Perform Serach
          $1 = (Search-Mailbox $n -SearchDumpster -SearchQuery “(Mustard) AND ($W)”  -EstimateResultOnly).ResultItemscount
         
          #Add to Table
          $returnobj = new-object psobject
          $returnobj |Add-Member -MemberType NoteProperty -Name “Name” -Value $n
          $returnobj |Add-Member -MemberType NoteProperty -Name “Word” -Value “(Mandava) AND ($W)” 
          $returnobj |Add-Member -MemberType NoteProperty -Name “EmailItemCount” -Value “$1” 
          $Result += $returnObj
         
          $w = $Null
          $1 = $null
          }
    $n = $null
    }

To view or Export:

$result

$result | Export-csv C:tempresult.csv -notypeinformation

Determine if a user has Elevated/Administrative Privileges in Exchange via PowerShell

Scenario: You want to clean up rights in Exchange, but you want to verify if a specific account has any elevated/administrative Exchange privilege.

Solution: Run the following command line via Exchange PowerShell:

get-managementroleassignment -roleassignee  steve

The results will give you all permissions via role in Exchange.  If its a standard mailbox with no elevated permissions, you will see a bunch of Default Roles for the RoleAssigneeName.  Any elevated privilege will also be listed as well.