Hello Max,
thanks for the info, indeed i was looking and seems more complex, due the Exchange version too, i think i will try to create a filter by MAPI property and looking what’s the property by MFCMAPI.
however i’ve noticed now another issue, i’ve adapted a bit your code with mine, basically the operation it’s the same however i look for the folder based on a CSV file, the issue i’ve found is that he don’t do the Loop of DO, he only perform the move of the number of items i use for the view as is he’s not getting the MoreItems property
try {
# Bind your Folder & Create your filter
$folderID = new-object Microsoft.Exchange.WebServices.Data.FolderId 'Inbox', $EmailAccount
$folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($EWS, $folderID)
$MailItems = $folder.FindItems($EWSItems)
$FilterSender = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $True)
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView($EWSItems)
# Offset
$size = 0
$view.Offset = 0
$req = 0
# Loop items
do {
$req++
$MailItems = $folder.FindItems($FilterSender, $view)
if ($view.Offset -eq 0) {
Write-Verbose ('Messages Total: {0}' -f $MailItems.TotalCount)
}
$view.Offset += $MailItems.Items.Count
foreach ($item in $MailItems.Items) {
if ($Item.Categories -ne "") {
[int]$msgsize = $item.Size / 1MB
$ItemSize = "{0:N0}" -f $msgsize
$size += $ItemSize
if ($EWSLoad -eq $True) {
$Item.Load()
}
$msg = $item | Select-object DateTimeReceived,Categories,@{Name="MsgFromAddress";Expression={$_.From.Address}},
@{Name="MsgFromUser";Expression={$_.From.Name}}, @{Name="Domain";Expression={$_.From.Address.Split("@")[1]}},
Subject, displayTo, DisplayCC, isread, Flag, IsFromMe, Size, InternetMessageId
# Split categories for cases where two or more categories are assigned
# Array | [string[]]$EmailCat = $msg.Categories.split(",")
# Whole Array | [String]$EmailCat = $msg.Categories
[string[]]$EmailCat = $msg.Categories.split(",")
[String]$MailSender = $Msg.MsgFromUser
[String]$MailAddressSender = $Msg.MsgFromAddress
[String]$MailCategory = $EmailCat[0]
[String]$MailSubject = $Msg.Subject
[String]$MailReceivedTime = $Msg.DateTimeReceived
[String]$MailDomain = $Msg.Domain
$UnRead = $Msg.isread
[String]$InetMsgID = $Msg.InternetMessageId
[String]$FromMe = $msg.IsFromMe
# Checking Category against CSV file
$TargetMbxFolder = $FolderStructure | Where-Object { $_.Mailbox -eq $Mailbox -and $_.MailCategory -eq $MailCategory }
# Get Folder ID
# Find and Bind to Folder based on Path
# Define the path to search should be seperated with \ Bind to the MSGFolder Root
[String]$FolderPath = ("\inbox\{0}\{1}" -f $CurrentMonthFolder, $TargetMbxFolder.Folder)
Write-Debug ("Target Message | Category {0} | TargetFolder: {1} | QueryFolder: {4} | Sender: {2} | IsRead: {3}" -f $MailCategory, $TargetMbxFolder.Folder, $MailSender, $UnRead, $FolderPath)
Try {
$Movefolderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$EmailAccount)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($EWS,$Movefolderid)
$fldArray = $FolderPath.Split("\")
#Loop through the Split Array and do a Search for each level of folder
for ($lint = 1; $lint -lt $fldArray.Length; $lint++) {
#Perform search based on the displayname of each folder level
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint])
$findFolderResults = $EWS.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
Write-Verbose "Error Folder Not Found"
$tfTargetFolder = $null
$Remark = "Folder not found"
}
}
if($tfTargetFolder -ne $null){
$TargetFolder = $tfTargetFolder
[Bool]$FolderFound = $True
}
}
Catch {
$ErrorMessage = $_.Exception.Message
Write-Host "EWS FindFolder: " -NoNewline ; Write-Host "Folder $($TargetMbxFolder.Folder) not found | $ErrorMessage" -ForegroundColor red
$Remark = "Folder not found"
}
# Move Item to TargetFolder ID
if ($FolderFound -eq $True -and $TestMove -eq $False) {
$item.Move($TargetFolder.ID) | Out-Null
Write-Verbose ("Message: Moved | Category: {0} | From: {1} | Folder: {2}" -f $MailCategory, $MailSender, $TargetFolder.DisplayName)
}
elseif ($TestMove -eq $True) {
Write-Verbose ("Message: TEST-Moved | Category: {0} | From: {1} | Folder: {2}" -f $MailCategory, $MailSender, $TargetMbxFolder.Folder)
}
$MoveMailsCollection += [PSCustomObject]@{
Mailbox = $Mailbox
DateOfMove = $(Get-Date -Format dd/MM/yyyy)
TimeOfMove = $(get-date -Format HH:mm:ss)
ExecutedBy = $ENV:USERNAME
MsgID = $InetMsgID
SenderName = $MailSender
ReceivedTime = $MailReceivedTime
Category = $MailCategory
Folder = $TargetMbxFolder.Folder
SenderEmail = $MailAddressSender
MailSubject = $MailSubject
Remark = $Remark
}
}
}
} while ($MailItems.MoreAvailable)
$MoveMailsCollection
$EDate = (get-date)
$LapsedTime = $EDate - $SDate
$LapsedMessage = "{0:00}:{1:00}:{2:00}" -f $LapsedTime.Hours, $LapsedTime.Minutes, $LapsedTime.Seconds
Write-Host ('{0}: Finished | Messages: {1} | Size: {2} mb | Batches: {3} | Time: {4}' -f $OperationMode, $MoveMailsCollection.Count, $size, $req, $LapsedTime)
}
since sometimes the number of items can be high is not very convenient just modify the number of items for the view, i try to debug the issue and i think it’s related to the code of the Search the subfolders:
# Get Folder ID
# Find and Bind to Folder based on Path
# Define the path to search should be seperated with \ Bind to the MSGFolder
[String]$FolderPath = ("\inbox\{0}\{1}" -f $CurrentMonthFolder, $TargetMbxFolder.Folder)
Write-Debug ("Target Message | Category {0} | TargetFolder: {1} | QueryFolder: {4} | Sender: {2} | IsRead: {3}" -f $MailCategory, $TargetMbxFolder.Folder, $MailSender, $UnRead, $FolderPath)
Try {
$Movefolderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$EmailAccount)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($EWS,$Movefolderid)
$fldArray = $FolderPath.Split("\")
#Loop through the Split Array and do a Search for each level of folder
for ($lint = 1; $lint -lt $fldArray.Length; $lint++) {
#Perform search based on the displayname of each folder level
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint])
$findFolderResults = $EWS.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
Write-Verbose "Error Folder Not Found"
$tfTargetFolder = $null
$Remark = "Folder not found"
}
}
if($tfTargetFolder -ne $null){
$TargetFolder = $tfTargetFolder
[Bool]$FolderFound = $True
}
thanks in advance for your feedback!