none
Using EWS to work with mail items from a range derived from Get-Date RRS feed

  • Question

  • I am attempting to write a powershell script that uses EWS to move items from the prior month and create a folder named after that month to hold those items. 

    I am finding that the search filter only likes the format if you use .NET system.DateTime and not Get-Date.

    However it's strange, for testing I configured my variable to be the exact same format as the .NET format but it rejects it. 

    The error i receive is: 

    Exception calling "FindItems" with "2" argument(s): "The specified value is
    invalid for property."
    At line:1 char:1
    + $frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ServiceResponseException


    For example, if i set $startdate and $enddate like this  $startdate=(([system.DateTime]::Today.AddDays(-60)))


    $startdate returns Monday, January 20, 2014 12:00:00 AM, and the search filter works fine.

    but if i set $startdate using this: $startdate = (Get-Date).AddMonths(-1).ToString("dddd, MMMM 01, 12:00:00 AM")

    It gets rejected event though the output is exactly the same.

    i.e. Friday, February 01, 2014 12:00:00 AM

    Any help would be appreciated. 

    Thank You. 

    #Set the mailbox that this script will run against
    
    $MailboxName = "mymailbox@mydomain.com"
    
    # Set up the API dll path, AutoDiscover URL and AD account used to access the mailbox
    
    Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
    $service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::"Exchange2010_SP2")
    $windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
    $aceuser = [ADSI]$sidbind
    $service.AutodiscoverUrl($aceuser.mail.ToString())
    
    # Determine if the script is running in January in order to set the year used in the search filter
    
    if ((Get-Date).Month -eq 1) {
    
    $searchyear = (Get-Date).Year - 1
    }
       Else{
       $searchyear = (Get-Date).Year
       }
          
    # Set variables for the search filter to move items from the prior month to a folder
    
    $startdate = (Get-Date).AddMonths(-1).ToString("dddd, MMMM 01,")
    $startdatetime= "$startdate $searchyear 12:00:00 AM"
    $enddate = [System.DateTime]::DaysInMonth($(Get-date).Year, $(Get-date).Month -1)
    $priormonth = (Get-Date).AddMonths(-1).ToString("dddd, MMMM")
    $enddatetime = "$priormonth $enddate, $searchyear 11:59:59 PM"
    
    
    # Set up folder path locations for the search filter
    
    $folderid = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
    $MailboxRoot = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
    $InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
    
    
    # Create the search filter
    
    $Sfgt = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThan([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $startdatetime)
    $Sflt = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThan([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $enddatetime)
    $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
    $sfCollection.add($Sfgt)
    $sfCollection.add($Sflt)
    
    # Perform the search
    
    $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(5000)
    $frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
    
    # define the destination folder name, check if the destination folder exists
    
    
    $foldermonth = (Get-Date).AddMonths(-1).ToString("MM")
    $newFolderName = "$foldermonth$searchear" 
    $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(10)
    $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$newFolderName)
    $findFolderResults = $service.FindFolders($MailboxRoot,$SfSearchFilter,$fvFolderView)
    
    # Create the destination folder if necessary
    
    if ($findFolderResults.TotalCount -eq 0){
    		$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
    		$NewFolder.DisplayName = $newFolderName
    		$NewFolder.Save($MailboxRoot.Id.UniqueId)
    }
    	else{
    		# Folder Already Exists - Do Nothing
    	}
    
    # Move the items in to the destination folder
    
    foreach ($miMailItems in $frFolderResult.Items){
       "Moving" + $miMailItems.Subject.ToString()
       [VOID]$miMailItems.Move($NewFolder.Id.UniqueId)
    }


    • Edited by MikeN401 Friday, March 21, 2014 7:49 PM
    Friday, March 21, 2014 7:47 PM

All replies

  • The Managed API is expecting you to pass a Typed Value not a String so if you just use

    $startdatetime= [System.DateTime]::Parse("$startdate $searchyear 12:00:00 AM")

    That should work okay, the Managed API itself will then covert it to and from UTC and then submit the query eg

            <m:Restriction>
              <t:IsLessThan>
                <t:FieldURI FieldURI="item:DateTimeReceived" />
                <t:FieldURIOrConstant>
                  <t:Constant Value="2014-02-24T03:26:34.889Z" />
                </t:FieldURIOrConstant>
              </t:IsLessThan>
            </m:Restriction>

    Which you can see yourself if you enable tracing eg

    $service.TraceEnabled = $true

    Cheers
    Glen

    Monday, March 24, 2014 3:36 AM
  • Thanks Glen.

    that didn't work exactly, it was throwing an error where it did not like the format of the day of week.

    However i tweaked that section of the code to the following format and now it works fine.

    $startdate = (Get-Date).AddMonths(-1).ToString("MM-01")
    $startdatetime= [System.DateTime]::Parse("$startdate-$searchyear 12:00:00 AM")
    $enddate = [System.DateTime]::DaysInMonth($(Get-date).Year, $(Get-date).Month -1)
    $priormonth = (Get-Date).AddMonths(-1).ToString("MM")
    $enddatetime = [System.DateTime]::Parse("$priormonth-$enddate-$searchyear 11:59:59 PM")

    Monday, March 24, 2014 8:44 PM