Gathering emails powershell by MAPI / EWS

This topic contains 3 replies, has 2 voices, and was last updated by Profile photo of Max Kozlov Max Kozlov 2 weeks, 5 days ago.

  • Author
    Posts
  • #65890
    Profile photo of pepe
    pepe
    Participant

    Hello All,

    i've done a function to perform few automated task from Outlook, like create folders, scan mails per categories or move them to assigned folders based on a csv file. Unfortunally i'm having some issues while gathering the emails in order to move them to the folders

    mailboxes are mapped as shared mailbox and the service account have full access (they're as Online not cache)
    Emails have a category and on base of this category he will lookup on the CSV to create the path and then invoke the expression, this works fine in one of the mailbox where the amount of emails it's not high, less than 300, however there is other mailbox where the amount of messages it's higher aprox 600 message UnRead from 1000aprox in whole inbox.

    the main issue i've found it's that he's not able to gather all message information such as Categories, SenderName... which it's important to let the tool know where to move them. I run the code below :

    		$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
    		$OlClass = "Microsoft.Office.Interop.Outlook.OlObjectClass" -as [type]
    		$OlSaveAs = "Microsoft.Office.Interop.Outlook.OlSaveAsType" -as [type]
    		$OlBodyFormat = "Microsoft.Office.Interop.Outlook.OlBodyFormat" -as [type]
    
    			$mapi = $outlook.GetNameSpace("Mapi")
    			$Accounts = $outlook.Session.Stores | Select-Object displayname, ExchangeStoreType, FilePath
    			$Source = $Mapi.Folders[$Mailbox].Folders.Item("Inbox")
    			$NotRead = $Source.Items | Where-Object { $_.Unread -eq $False -and $_.FlagIcon -eq "0" }
    

    If i run that he will gather aprox the 50% of the messages and the others are blank. Any idea what could be the reason or possible workarounds?

    I was trying to "migrate" the tool to EWS but it's a bit more complex and i'm not very skilled with it at the moment...

  • #65917
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    here is excerpt from my EWS script for similar task (message move by subject)

    $address = 'test@test.ru'
    $TargetFolderName = 'Target Folder'
    $Subject = 'TestSubject'
    
    Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" 
    $EWS = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService 'Exchange2013',([timezoneinfo]::Utc)
    
    $EWS.AutodiscoverUrl($address)
    
    $folderID = new-object Microsoft.Exchange.WebServices.Data.FolderId 'Inbox', $address
    $folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($EWS, $folderID)
    Write-Host "found $($folder.DisplayName) folder"
    
    $folderview = New-Object Microsoft.Exchange.WebServices.Data.FolderView 100
    $targetFolder = $null
    foreach ($f in $folder.FindFolders($folderview)) {
    	if ($f.DisplayName -eq $TargetFolderName) {
    		$targetFolder = $f
    		break;
    	}
    }
    if ($targetFolder) {
    	Write-Host "found $($targetFolder.DisplayName) folder"
    }
    else {
    	$targetFolder = New-Object Microsoft.Exchange.WebServices.Data.Folder $EWS
    	$targetFolder.DisplayName = $TargetFolderName
    	Write-Host "Create $($targetFolder.DisplayName) folder"
    	$targetFolder.Save($folderID)
    }
    
    $filter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject, $Subject)
    $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView 100
    # Так как найденное сообщение мы первым делом двигаем, то всё что берём - всё равно теряется, поэтому просим только ID
    $view.PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet
    # А это уже нам понадобится после перемещения
    $mailProperties = New-Object Microsoft.Exchange.WebServices.Data.PropertySet (
    						[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::TextBody,
    						[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject,
    						[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Sender
    					)
    
    $size = 0; $view.Offset = 0; $req = 0;
    do {
    	$req++
    	$MailItems = $folder.FindItems($filter, $view)
    	if ($view.Offset -eq 0) { Write-Host ('Messages Total: {0}' -f $MailItems.TotalCount) }
    	$view.Offset += $MailItems.Items.Count
    	foreach ($item in $MailItems.Items) {
    		$size += $item.Size
    		$item2 = $item.Move($targetFolder.Id)
    		$item2.Load($mailProperties)
    		# [...]
    	}
    } while ($MailItems.MoreAvailable)
    Write-Host ('Size: {0}, Requests: {1}' -f $size, $req)
    
    
  • #65956
    Profile photo of pepe
    pepe
    Participant

    Thanks for your reply and script example, really appreciated.

    While i was doing test with EWS i found i cannot gather more than 1000 items then i saw the loop (do-while) but i don't get if doing that he will do the operation for the total amount of items. Maybe this can be done as well for the MAPI? i know EWS it's faster than mapi but in both cases i know there is the limitation from IIS / Exchange of 1000 items per batch.

  • #65968
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    My example definitely work with folders which contain more than 1000 items (because of using $view.Offset), but can say nothing about MAPI, sorry

You must be logged in to reply to this topic.