Forum Discussion
List of All Emails in Archive Folder
lpmdvip Ok, that is different. The only way that I know to accomplish that is by using discovery. This is the script that I would use for this. It may take a while due that searches depend on the number of items in each folder. Be aware that you will need additional permissions to run the Search cmdlets.
<#
.SYNOPSIS
Get MBXs Stats, User Attribute(s), Gets Subject Emails in Archive Folder (Only if the user has a department assigned)
.DESCRIPTION
Requires you to be a member of groups: eDiscoveryManager and Compliance Administrator to be able to use the Compliance cmdlets properly.
.NOTES
Author: Erick A. Moreno
Email: emoreno@request-script.com
Date: 17 Jan 2020
PowerShell: v3
.References
#requested: https://techcommunity.microsoft.com/t5/windows-powershell/list-of-all-emails-in-archive-folder/m-p/1178048#M1045
#>
$CredentialsFolder = "$home\Documents\"
$WorkingDir = "$home\Documents"
$ScriptTime = Get-Date -UFormat "%m%d%Y-%H%M"
#region Functions
Function _Get-Sessions
{
Param(
[Parameter(Mandatory=$true)]$CredentialsFolder,
[Parameter(Mandatory=$true)]$CredentialsFileName,
[Parameter(Mandatory=$false)]$InlcudeSecSession,
[Parameter(Mandatory=$false)]$InlcudeExoSession
)
#region Check for Credentials File
$TargetCredPath = $CredentialsFolder #Credential XML File Location
$TargetCredName = $TargetCredPath + $CredentialsFileName
#Write-Host $TargetCredName
If(Test-Path $TargetCredName)
{
$TargetCred = Import-Clixml $TargetCredName
}
Else
{
$Cred = Get-Credential
$Cred | Export-CliXml -Path $(Join-Path -path $TargetCredPath -ChildPath RemotePS.HCH.cred)
$TargetCred = Import-Clixml $TargetCredName
}
#endregion
#region connections
If($InlcudeExoSession -eq $true)
{
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic -AllowRedirection
$NoOutput = Import-PSSession $Session -AllowClobber -Prefix O365 -CommandName "*Mailbox*","*User*"
}
If($InlcudeSecSession -eq $true)
{
$Session2 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic –AllowRedirection
$NoOutput2 = Import-PSSession $Session2 -Prefix 365Sec -CommandName "*Compliance*" -AllowClobber
}
#endregion
Return $Session,$Session2
}
#endregion
#region Open PS Sessions
Get-PSSession | Remove-PSSession
$TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true
#endregion
$MBXs = Get-O365Mailbox -ResultSize Unlimited #| where{$_.DisplayName -eq "Erick A. Moreno"} #| where{$_.ArchiveStatus -eq "Active"}
$Counter = @($MBXs).count
$Results = @()
$NoDepartment = @()
$Counter
Foreach($MBX in $MBXs)
{
#Start-Sleep -Milliseconds 300
$PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State
$PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State
If($($Counter/100) -match '^[0-9]+$' -or $PsExOSessionState -ne "Opened" -or $PsSecSessionState -ne "Opened")
{
Remove-PSSession $TenantSession[0].Id -Confirm:$false
Remove-PSSession $TenantSession[1].Id -Confirm:$false
Write-Host "Opening a new Session Each 100 iterations" -ForegroundColor Yellow
$TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true
}
Write-Host "($Counter) Working On MBX: $($MBX.PrimarySmtpAddress)" -ForegroundColor Cyan
$Stats = $null
$UserData = $null
$FolderItems = $null
$UserData = Get-O365User $MBX.PrimarySmtpAddress
$LastLogon = $null
If(![string]::IsNullOrEmpty($($UserData.Department)))
{
$FolderInfo = Get-O365MailboxFolderStatistics -Identity $MBX.PrimarySmtpAddress | Where {$_.Name -eq “Archive”} | Select Name,ItemsInFolder,FolderID #Add Folders as needed
$FolderID = $Folder.FolderId
#region decoding From: https://docs.microsoft.com/en-us/microsoft-365/compliance/use-content-search-for-targeted-collections#step-1-run-the-script-to-get-a-list-of-folders-for-a-mailbox-or-site
$encoding = [System.Text.Encoding]::GetEncoding("us-ascii")
$nibbler = $encoding.GetBytes("0123456789ABCDEF");
$folderIdBytes = [Convert]::FromBase64String($FolderID)
$indexIdBytes = New-Object byte[] 48
$indexIdIdx = 0
$folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
$folderQueryeDiscovery = "folderid:$($encoding.GetString($indexIdBytes))"
#endregion
$SearchName = "($Counter) Search Archive ($($MBX.DisplayName))"
$Search = New-365SecComplianceSearch -Name $SearchName -ContentMatchQuery $folderQueryeDiscovery -ExchangeLocation All
Start-365SecComplianceSearch -Identity $SearchName
Do
{
$SearchStatus = Get-365SecComplianceSearch $Search.Name
Write-Progress -Status $($SearchStatus.Status) -Activity "Search For MBX: $($MBX.DisplayName)" -PercentComplete $($SearchStatus.JobProgress)
}While($SearchStatus.Status -ne "Completed")
$Action = New-365SecComplianceSearchAction -SearchName $SearchName -Preview
$PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State
$PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State
If($PsSecSessionState -ne "Opened")
{
Remove-PSSession $TenantSession[0].Id -Confirm:$false
Remove-PSSession $TenantSession[1].Id -Confirm:$false
Write-Host "Opening a new Session" -ForegroundColor Yellow
$TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true
}
Do
{
$ActionStatus = Get-365SecComplianceSearchAction -Identity $Action.Name
Write-Progress -Status $($ActionStatus.Status) -Activity "Search Action Review For MBX: $($MBX.DisplayName)" -PercentComplete $($ActionStatus.JobProgress)
}While($ActionStatus.Status -ne "Completed")
$PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State
$PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State
If($PsSecSessionState -ne "Opened")
{
Remove-PSSession $TenantSession[0].Id -Confirm:$false
Remove-PSSession $TenantSession[1].Id -Confirm:$false
Write-Host "Opening a new Session" -ForegroundColor Yellow
$TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true
}
$Subjects = $($ActionStatus.Results -split ';' | where{$_ -like "*subject*"}).replace("Subject:",'') -join ';'
Remove-365SecComplianceSearch -Identity $SearchName -Confirm:$false
If(![string]::IsNullOrEmpty($Stats.LastLogonTime))
{
$LastLogon = $Stats.LastLogonTime.ToString()
}
$Properties = [Ordered]@{
DisplayName = $MBX.DisplayName
EmailSubjectsInArchiveFolder = $Subjects
Department = $UserData.Department
ArchiveItems = $($FolderItems | where{$_.Name -eq "Archive"}).ItemsInFolder
LastLogon = $LastLogon
lastuseractiontime = $Stats.lastuseractiontime
UserPrincipalName = $MBX.UserPrincipalName
FolderIdQuery = $folderQueryeDiscovery
}
$Results += New-Object PSObject -Property $Properties
}
Else
{
Write-Host "Department Field is Empty Skipping MBX: $($MBX.PrimarySmtpAddress)"
$Properties2 = [Ordered]@{
DisplayName = $MBX.DisplayName
UserPrincipalName = $MBX.UserPrincipalName
}
$NoDepartment += New-Object PSObject -Property $Properties2
}
$Counter--
}
Remove-PSSession $TenantSession[0].Id -Confirm:$false
Remove-PSSession $TenantSession[1].Id -Confirm:$false
$Results | Export-Csv -Path "$WorkingDir\ReportMBXsStats_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force
$NoDepartment | Export-Csv -Path "$WorkingDir\NoDepartmentField_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force
Write-Host "Report Saved To: $WorkingDir\ReportMBXsStats_$ScriptTime.csv" -ForegroundColor Cyan
Write-Host "Report Saved To: $WorkingDir\NoDepartmentField_$ScriptTime.csv" -ForegroundColor Cyan
Erick A. Moreno R. Is there anything that should be done to modify the line of code with your name in it?
$MBXs = Get-O365Mailbox -ResultSize Unlimited #| where{$_.DisplayName -eq "Erick A. Moreno"} #| where{$_.ArchiveStatus -eq "Active"}
And I've received these errors:
The operation couldn't be performed because '(2495) Search Archive (****,***)' couldn't be found.
+ CategoryInfo : WriteError: (:) [Remove-ComplianceSearch], ManagementObjectNotFoundException
You cannot call a method on a null-valued expression.
At line:147 char:18
+ ... ubjects = $($ActionStatus.Results -split ';' | where{$_ -like "*subje ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Write-Progress : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Status'. Specified method is not supported.
At line:133 char:30
+ Write-Progress -Status $($ActionStatus.Status) -Activity "Searc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Progress], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteProgressCommand
Write-Progress : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Status'. Specified method is not supported.
At line:114 char:30
+ Write-Progress -Status $($SearchStatus.Status) -Activity "Searc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Progress], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.WriteProgressCommand
A parameter cannot be found that matches parameter name 'Preview'.
+ CategoryInfo : InvalidArgument: (:) [New-ComplianceSearchAction], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,New-ComplianceSearchAction
+ PSComputerName : ----.ps.compliance.protection.outlook.com
- Erick A. Moreno R.Feb 19, 2020Iron Contributor
lpmdvip Sorry I forgot to remove that, It does not affect you as it is commented.
I've removed that and added an error catch to deal with those that are throwing errors, the error that you got seems to be due to the way the Display Name is formed, I've changed the naming for the searches to use PrimarysmtpAddress as base hopefully this should fix it in your side.
<# .SYNOPSIS Get MBXs Stats, User Attribute(s), Gets Subject Emails in Archive Folder (Only if the user has a department assigned) .DESCRIPTION Requires you to be a member of groups: eDiscoveryManager and Compliance Administrator to be able to use the Compliance cmdlets properly. .NOTES Author: Erick A. Moreno Email: emoreno@request-script.com Date: 17 Jan 2020 PowerShell: v3 .References #requested: https://techcommunity.microsoft.com/t5/windows-powershell/list-of-all-emails-in-archive-folder/m-p/1178048#M1045 #> $CredentialsFolder = "$home\Documents\" $WorkingDir = "$home\Documents" $ScriptTime = Get-Date -UFormat "%m%d%Y-%H%M" #region Functions Function _Get-Sessions { Param( [Parameter(Mandatory=$true)]$CredentialsFolder, [Parameter(Mandatory=$true)]$CredentialsFileName, [Parameter(Mandatory=$false)]$InlcudeSecSession, [Parameter(Mandatory=$false)]$InlcudeExoSession ) #region Check for Credentials File $TargetCredPath = $CredentialsFolder #Credential XML File Location $TargetCredName = $TargetCredPath + $CredentialsFileName #Write-Host $TargetCredName If(Test-Path $TargetCredName) { $TargetCred = Import-Clixml $TargetCredName } Else { $Cred = Get-Credential $Cred | Export-CliXml -Path $(Join-Path -path $TargetCredPath -ChildPath RemotePS.HCH.cred) $TargetCred = Import-Clixml $TargetCredName } #endregion #region connections If($InlcudeExoSession -eq $true) { $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic -AllowRedirection $NoOutput = Import-PSSession $Session -AllowClobber -Prefix O365 -CommandName "*Mailbox*","*User*" } If($InlcudeSecSession -eq $true) { $Session2 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic –AllowRedirection $NoOutput2 = Import-PSSession $Session2 -Prefix 365Sec -CommandName "*Compliance*" -AllowClobber } #endregion Return $Session,$Session2 } #endregion #region Open PS Sessions Get-PSSession | Remove-PSSession $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true #endregion $MBXs = Get-O365Mailbox -ResultSize Unlimited $Counter = @($MBXs).count $Results = @() $NoDepartment = @() $Errors = @() $Counter Foreach($MBX in $MBXs) { #Start-Sleep -Milliseconds 300 $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($($Counter/100) -match '^[0-9]+$' -or $PsExOSessionState -ne "Opened" -or $PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session Each 100 iterations" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } Write-Host "($Counter) Working On MBX: $($MBX.PrimarySmtpAddress)" -ForegroundColor Cyan $Stats = $null $UserData = $null $FolderItems = $null $UserData = Get-O365User $MBX.PrimarySmtpAddress $LastLogon = $null If(![string]::IsNullOrEmpty($($UserData.Department))) { Try { $FolderInfo = Get-O365MailboxFolderStatistics -Identity $MBX.PrimarySmtpAddress -ErrorAction Stop | Where {$_.Name -eq “Archive”} | Select Name,ItemsInFolder,FolderID #Add Folders as needed $FolderID = $Folder.FolderId #region decoding From: https://docs.microsoft.com/en-us/microsoft-365/compliance/use-content-search-for-targeted-collections#step-1-run-the-script-to-get-a-list-of-folders-for-a-mailbox-or-site $encoding = [System.Text.Encoding]::GetEncoding("us-ascii") $nibbler = $encoding.GetBytes("0123456789ABCDEF"); $folderIdBytes = [Convert]::FromBase64String($FolderID) $indexIdBytes = New-Object byte[] 48 $indexIdIdx = 0 $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]} $folderQueryeDiscovery = "folderid:$($encoding.GetString($indexIdBytes))" #endregion $Split = $null $Split = $MBX.PrimarySmtpAddress -split "@" $SearchName = "($Counter) Search Archive ($($Split[0]))" $Search = New-365SecComplianceSearch -Name $SearchName -ContentMatchQuery $folderQueryeDiscovery -ExchangeLocation All -ErrorAction Stop Start-365SecComplianceSearch -Identity $SearchName -ErrorAction Stop Do { $SearchStatus = Get-365SecComplianceSearch $Search.Name -ErrorAction Stop Write-Progress -Status $($SearchStatus.Status) -Activity "Search For MBX: $($MBX.DisplayName)" -PercentComplete $($SearchStatus.JobProgress) }While($SearchStatus.Status -ne "Completed") $Action = New-365SecComplianceSearchAction -SearchName $SearchName -Preview -ErrorAction Stop $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } Do { $ActionStatus = Get-365SecComplianceSearchAction -Identity $Action.Name -ErrorAction Stop Write-Progress -Status $($ActionStatus.Status) -Activity "Search Action Review For MBX: $($MBX.DisplayName)" -PercentComplete $($ActionStatus.JobProgress) }While($ActionStatus.Status -ne "Completed") $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } $Subjects = $($ActionStatus.Results -split ';' | where{$_ -like "*subject*"}).replace("Subject:",'') -join ';' Remove-365SecComplianceSearch -Identity $SearchName -Confirm:$false -ErrorAction Stop If(![string]::IsNullOrEmpty($Stats.LastLogonTime)) { $LastLogon = $Stats.LastLogonTime.ToString() } $Properties = [Ordered]@{ DisplayName = $MBX.DisplayName EmailSubjectsInArchiveFolder = $Subjects Department = $UserData.Department ArchiveItems = $($FolderItems | where{$_.Name -eq "Archive"}).ItemsInFolder LastLogon = $LastLogon lastuseractiontime = $Stats.lastuseractiontime UserPrincipalName = $MBX.UserPrincipalName FolderIdQuery = $folderQueryeDiscovery } $Results += New-Object PSObject -Property $Properties } Catch { Write-Host "Error Found During MBX Search: $($MBX.PrimarySmtpAddress)" -ForegroundColor Red $Properties3 = [Ordered]@{ PrimarySmtpAddress = $MBX.PrimarySmtpAddress Error = $Errors[0] } $Error += New-Object PSObject -Property $Properties3 } } Else { Write-Host "Department Field is Empty Skipping MBX: $($MBX.PrimarySmtpAddress)" $Properties2 = [Ordered]@{ PrimarySmtpAddress = $MBX.PrimarySmtpAddress } $NoDepartment += New-Object PSObject -Property $Properties2 } $Counter-- } Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false $Results | Export-Csv -Path "$WorkingDir\ReportMBXsStats_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force $NoDepartment | Export-Csv -Path "$WorkingDir\NoDepartmentField_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force $Errors | Export-Csv -Path "$WorkingDir\Errors_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force Write-Host "Report Saved To: $WorkingDir\ReportMBXsStats_$ScriptTime.csv" -ForegroundColor Cyan Write-Host "Report Saved To: $WorkingDir\NoDepartmentField_$ScriptTime.csv" -ForegroundColor Cyan Write-Host "Report Saved To: $WorkingDir\Errors_$ScriptTime.csv" -ForegroundColor Cyan
- lpmdvipFeb 19, 2020Copper Contributor
Erick A. Moreno R. When I run the script, here's the results for all of the users:
Cannot overwrite variable Error because it is read-only or constant.
At line:181 char:8
+ $Error += New-Object PSObject -Property $Properties3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (Error:String) [], SessionStateUnauthorizedAccessException
+ FullyQualifiedErrorId : VariableNotWritable- Erick A. Moreno R.Feb 19, 2020Iron Contributor
lpmdvip Try again please, I've added more error controls and fixed a couple of variables names that I miss in the last pass. Editing in my phone can be har as I don't have an editor with coloring help xD.
<# .SYNOPSIS Get MBXs Stats, User Attribute(s), Gets Subject Emails in Archive Folder (Only if the user has a department assigned) .DESCRIPTION Requires you to be a member of groups: eDiscoveryManager and Compliance Administrator to be able to use the Compliance cmdlets properly. .NOTES Author: Erick A. Moreno Email: emoreno@request-script.com Date: 17 Jan 2020 PowerShell: v3 .References #requested: https://techcommunity.microsoft.com/t5/windows-powershell/list-of-all-emails-in-archive-folder/m-p/1178048#M1045 #> $CredentialsFolder = "$home\Documents\" $WorkingDir = "$home\Documents" $ScriptTime = Get-Date -UFormat "%m%d%Y-%H%M" #region Functions Function _Get-Sessions { Param( [Parameter(Mandatory=$true)]$CredentialsFolder, [Parameter(Mandatory=$true)]$CredentialsFileName, [Parameter(Mandatory=$false)]$InlcudeSecSession, [Parameter(Mandatory=$false)]$InlcudeExoSession ) #region Check for Credentials File $TargetCredPath = $CredentialsFolder #Credential XML File Location $TargetCredName = $TargetCredPath + $CredentialsFileName #Write-Host $TargetCredName If(Test-Path $TargetCredName) { $TargetCred = Import-Clixml $TargetCredName } Else { $Cred = Get-Credential $Cred | Export-CliXml -Path $(Join-Path -path $TargetCredPath -ChildPath RemotePS.HCH.cred) $TargetCred = Import-Clixml $TargetCredName } #endregion #region connections If($InlcudeExoSession -eq $true) { $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic -AllowRedirection $NoOutput = Import-PSSession $Session -AllowClobber -Prefix O365 -CommandName "*Mailbox*","*User*" } If($InlcudeSecSession -eq $true) { $Session2 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $TargetCred -Authentication Basic –AllowRedirection $NoOutput2 = Import-PSSession $Session2 -Prefix 365Sec -CommandName "*Compliance*" -AllowClobber } #endregion Return $Session,$Session2 } #endregion #region Open PS Sessions Get-PSSession | Remove-PSSession $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true #endregion $MBXs = Get-O365Mailbox -ResultSize Unlimited $Counter = @($MBXs).count $Results = @() $NoDepartment = @() $ErrorsLog = @() $Counter Foreach($MBX in $MBXs) { #Start-Sleep -Milliseconds 300 $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($($Counter/100) -match '^[0-9]+$' -or $PsExOSessionState -ne "Opened" -or $PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session Each 100 iterations" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } Write-Host "($Counter) Working On MBX: $($MBX.PrimarySmtpAddress)" -ForegroundColor Cyan $Stats = $null $UserData = $null $FolderItems = $null $UserData = Get-O365User $MBX.PrimarySmtpAddress $LastLogon = $null If(![string]::IsNullOrEmpty($($UserData.Department))) { Try { $FolderID = $null $FolderInfo = Get-O365MailboxFolderStatistics -Identity $MBX.PrimarySmtpAddress -ErrorAction Stop | Where {$_.Name -eq “Archive”} | Select Name,ItemsInFolder,FolderID #Add Folders as needed $FolderID = $FolderInfo.FolderId If(![string]::IsNullOrEmpty($FolderID)) { #region decoding From: https://docs.microsoft.com/en-us/microsoft-365/compliance/use-content-search-for-targeted-collections#step-1-run-the-script-to-get-a-list-of-folders-for-a-mailbox-or-site $encoding = [System.Text.Encoding]::GetEncoding("us-ascii") $nibbler = $encoding.GetBytes("0123456789ABCDEF"); $folderIdBytes = [Convert]::FromBase64String($FolderID) $indexIdBytes = New-Object byte[] 48 $indexIdIdx = 0 $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]} $folderQueryeDiscovery = "folderid:$($encoding.GetString($indexIdBytes))" #endregion $Split = $null $Split = $MBX.PrimarySmtpAddress -split "@" $SearchName = "($Counter) Search Archive ($($Split[0]))" $Search = New-365SecComplianceSearch -Name $SearchName -ContentMatchQuery $folderQueryeDiscovery -ExchangeLocation All -ErrorAction Stop Start-365SecComplianceSearch -Identity $SearchName -ErrorAction Stop Do { $SearchStatus = Get-365SecComplianceSearch $Search.Name -ErrorAction Stop Write-Progress -Status $($SearchStatus.Status) -Activity "Search For MBX: $($MBX.DisplayName)" -PercentComplete $($SearchStatus.JobProgress) }While($SearchStatus.Status -ne "Completed") $Action = New-365SecComplianceSearchAction -SearchName $SearchName -Preview -ErrorAction Stop $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } Do { $ActionStatus = Get-365SecComplianceSearchAction -Identity $Action.Name -ErrorAction Stop Write-Progress -Status $($ActionStatus.Status) -Activity "Search Action Review For MBX: $($MBX.DisplayName)" -PercentComplete $($ActionStatus.JobProgress) }While($ActionStatus.Status -ne "Completed") $PsExOSessionState = $(Get-PsSession $TenantSession[0].Id).State $PsSecSessionState = $(Get-PsSession $TenantSession[1].Id).State If($PsSecSessionState -ne "Opened") { Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false Write-Host "Opening a new Session" -ForegroundColor Yellow $TenantSession = _Get-Sessions -CredentialsFolder $CredentialsFolder -CredentialsFileName RemotePS.HCH.cred -InlcudeSecSession $true -InlcudeExoSession $true } $Subjects = $($ActionStatus.Results -split ';' | where{$_ -like "*subject*"}).replace("Subject:",'') -join ';' Remove-365SecComplianceSearch -Identity $SearchName -Confirm:$false -ErrorAction Stop If(![string]::IsNullOrEmpty($Stats.LastLogonTime)) { $LastLogon = $Stats.LastLogonTime.ToString() } $Properties = [Ordered]@{ DisplayName = $MBX.DisplayName EmailSubjectsInArchiveFolder = $Subjects Department = $UserData.Department ArchiveItems = $($FolderItems | where{$_.Name -eq "Archive"}).ItemsInFolder LastLogon = $LastLogon lastuseractiontime = $Stats.lastuseractiontime UserPrincipalName = $MBX.UserPrincipalName FolderIdQuery = $folderQueryeDiscovery } $Results += New-Object PSObject -Property $Properties }#Folder ID Exist? Else { Write-Host "Archive Folder Does not Exists for MBX: $($MBX.PrimarySmtpAddress)" -ForegroundColor Yellow Throw "Archive Folder Does not Exists for MBX: $($MBX.PrimarySmtpAddress)" } } Catch { Write-Host "Error Found During MBX Search: $($MBX.PrimarySmtpAddress): $($Error[0])" -ForegroundColor Red $Properties3 = [Ordered]@{ PrimarySmtpAddress = $MBX.PrimarySmtpAddress Error = $Error[0] } $ErrorsLog += New-Object PSObject -Property $Properties3 } } Else { Write-Host "Department Field is Empty Skipping MBX: $($MBX.PrimarySmtpAddress)" $Properties2 = [Ordered]@{ PrimarySmtpAddress = $MBX.PrimarySmtpAddress } $NoDepartment += New-Object PSObject -Property $Properties2 } $Counter-- } Remove-PSSession $TenantSession[0].Id -Confirm:$false Remove-PSSession $TenantSession[1].Id -Confirm:$false $Results | Export-Csv -Path "$WorkingDir\ReportMBXsStats_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force $NoDepartment | Export-Csv -Path "$WorkingDir\NoDepartmentField_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force $ErrorsLog | Export-Csv -Path "$WorkingDir\Errors_$ScriptTime.csv" -NoTypeInformation -Encoding UTF8 -Force Write-Host "Report Saved To: $WorkingDir\ReportMBXsStats_$ScriptTime.csv" -ForegroundColor Cyan Write-Host "No Department Field Saved To: $WorkingDir\NoDepartmentField_$ScriptTime.csv" -ForegroundColor Cyan Write-Host "Errors Saved To: $WorkingDir\Errors_$ScriptTime.csv" -ForegroundColor Cyan