List of All Emails in Archive Folder

Copper Contributor

Hello everyone!

 

Is there a script that would provide me a list of all emails with the Archive Folder for all Employees in the tabular format below? 

 

Employee Name  |   Folder Name (which would be Archive) | Last Accessed  | Department Name

9 Replies

@lpmdvip Updated columns:

 

Employee Name  |   Folder Name (which would be Archive) |  Email Subject | Last Accessed  | Department Name

 

@Erick A. Moreno R. Think you could help with this one?

Did you try Get-MailboxFolderStatistics with the -Archive switch?

@lpmdvip Hi, just to clarify, you want to know who has the archive mailbox enabled or you want to know which emails are contained in the archive folder? as per your second post, you are adding a header Email Subject.


@Erick A. Moreno R. Hi Erick, I would like to know what emails are in the Archive Folder.

 

For example, the script would output something like:

 

Parker, John | Archive | 2/17 Meeting Notes | 2/1/20 2:30 PM | IT

Parker, John | Archive | IT Quarterly Report  | 12/31/19 5:40 PM | IT

@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

 

@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

 

 

 

@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

@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