none
Exchange web services not working as aspected (FindItems)?

    Question

  • Hello,

    I'm using some scripts from Glen Scales and one of them is to delete some messages from an inbox folder but am running into something strange.

    I’m trying to remove email from an inbox folder based on the following AQSString ($AQSString = "System.Subject:" + "Mail Delivery System"). When I run the script 250 emails (from 3000) are deleted. We’re using Exchange 2013 and fors some reason the search results are limited to 250 items. All works well for the 250 emails and they’re deleted. However, when I run the script again 0 items are deleted while there are plenty more available. Only when I adjust the $AQSString by removing e.g. one character the script will run again and delete 250 emails. The value of $AQSString can only be used ones, even when I succesfully run the script again with the adjused string. Here's the code I'm using, what am I missing?

    #region prerequisites 
    ## check where the API is installed
    If (Test-Path -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"){
          Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"}
    Else{
          Add-Type -Path "E:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"}
    
          
          
    ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates  
      
    ## Code From http://poshcode.org/624
    ## Create a compilation environment
    $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
    
    
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList ([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
    
    
    $uri=[system.URI] "https://[exchange server fqdn]/EWS/Exchange.asmx"    
    $service.Url = $uri  
    
    #Credentials Option 1 using UPN for the windows Account    
    $creds = New-Object System.Net.NetworkCredential("[account]","[password]")     
    $service.Credentials = $creds 
    
    #endregion prerequisites
    
    cls
    
    #region Script
    
          $MailboxName = "[mailbox]" 
          Write-Host "$MailboxName wordt nu doorzocht..."
          
          #Bind to Inbox
          $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)     
          $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
    
          $AQSString = ""
          $AQSString = "System.Subject:" + "Mail Delivery System"
            
          #Define ItemView to retrieve just 1000 Items    
          $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)    
          $fiItems = $null
    
          [INT]$Rcount = 0  
          
          do{    
              $fiItems = $service.FindItems($Inbox.Id,$AQSString,$ivItemView)    
              #[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)  
              foreach($Item in $fiItems.Items){      
                      $Rcount++
                      $Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
              }    
              $ivItemView.Offset += $fiItems.Items.Count    
          }while($fiItems.MoreAvailable -eq $true) 
    
    $Rcount
    
    #endregion Script
    

    Thnx Remco

    Tuesday, February 24, 2015 6:21 PM

Answers

  •  That is a bug in Exchange 2013 (first appeared in RU5 SP1) what rollup are you running on your server ? They have fixed in Office365 but only in the Mailbox store so its still an active bug in Archive stores. As a work around you can use a SearchFilter instead of an AQS String eg

    $SubjecttoSearch = "Blah Blah"
    $sfItemSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $SubjecttoSearch) 

    Then change

    $fiItems = $service.FindItems($Inbox.Id,$sfItemSearchFilter,$ivItemView)   

    I would make sure you test it first before enabling the line that delete items you may also want to test the Item Subject as a secondary check before you do the delete. These restrictions are all substring so they can produce false positives so i would always recommend a secondary check before a delete.

    Cheers
    Glen

    • Marked as answer by Remco Tiel Thursday, February 26, 2015 8:39 AM
    Wednesday, February 25, 2015 12:17 AM