Reputation: 336
High fellow coders.
I'm using the raw exchange web service, referenced in my SSIS script task.
My issue is that when I enumerate items in a mailbox or folder, Not only am I interested in only those items that have not been read, but I want to ignore all the system type messages. so I only want items, specifically messages, who's "itemclass" is "IPM.Note" nothing else.
Here is a definitive list of Item Types and Message classes https://msdn.microsoft.com/en-us/library/office/ff861573.aspx
my code which works successfully for unread items in the inbox
'declare my find criteria, return only the IDs, from the inbox, for unread items
Dim reqFindUnreadMailInInbox As FindItemType = New FindItemType With _
{.Traversal = ItemQueryTraversalType.Shallow _
, .ItemShape = New ItemResponseShapeType With {.BaseShape = DefaultShapeNamesType.IdOnly} _
, .ParentFolderIds = New DistinguishedFolderIdType(0) {New DistinguishedFolderIdType With {.Id = DistinguishedFolderIdNameType.inbox}} _
, .Restriction = New RestrictionType With _
{.Item = New IsEqualToType With _
{.Item = New PathToUnindexedFieldType With {.FieldURI = UnindexedFieldURIType.messageIsRead} _
, .FieldURIOrConstant = New FieldURIOrConstantType With {.Item = New ConstantValueType With {.Value = "0"}} _
} _
} _
}
'go fetch the response from exchange
Dim resFindItemResponse As FindItemResponseType = esb.FindItem(reqFindUnreadMailInInbox)
Dim resFindFolderMessages As FindItemResponseMessageType = resFindItemResponse.ResponseMessages.Items(0)
Dim resFolderItems As ArrayOfRealItemsType = Nothing '= New ArrayOfRealItemsType
The problem I have is I want to add a restriction on the itemClass that is returned. But cannot figure out how to add a second Restriction to the request. This is what the restriction would look like if I changed my search to pull all items from the inbox regardless of read state but restricting only to itemClass IPM.Note (note the addition of the paged result)
Dim reqFindUnreadMailInInbox As FindItemType = New FindItemType With _
{.Item = New IndexedPageViewType With {.MaxEntriesReturnedSpecified = True, .MaxEntriesReturned = "100", .BasePoint = IndexBasePointType.Beginning, .Offset = 0} _
, .Traversal = ItemQueryTraversalType.Shallow _
, .ItemShape = New ItemResponseShapeType With {.BaseShape = DefaultShapeNamesType.IdOnly} _
, .ParentFolderIds = New DistinguishedFolderIdType(0) {New DistinguishedFolderIdType With {.Id = DistinguishedFolderIdNameType.inbox}} _
, .Restriction = New RestrictionType With _
{.Item = New IsEqualToType With _
{.Item = New PathToUnindexedFieldType With {.FieldURI = UnindexedFieldURIType.itemItemClass} _
, .FieldURIOrConstant = New FieldURIOrConstantType With {.Item = New ConstantValueType With {.Value = "IPM.Note"}} _
} _
} _
}
The next chunk of code checks for an error, and proceeds to enumerate the IDs and fetch the items in one call. If I debug the resGetitem after the response has returned, I can drill down and look at each items class by looking in the immediate window with this query
?directcast(directcast(resGetItem.ResponseMessages.Items(0),ItemInfoResponseMessageType).Items.Items(0),MessageType)
and I can see "REPORTS.IPM.Note.NDR". The question is how can I filter the initial call to restrict to only "IPM.Note"
'if there was an error bur out and report
If resFindFolderMessages.ResponseClass = ResponseClassType.[Error] Then
Throw New Exception(resFindFolderMessages.MessageText)
Else
TraceLog.AppendLine("Inbox found, ID pulled back")
If Not IsNothing(DirectCast(resFindFolderMessages.RootFolder.Item, ArrayOfRealItemsType).Items) Then
resFolderItems = resFindFolderMessages.RootFolder.Item
TraceLog.AppendLine(String.Format("found {0} unread mail - start processing", resFolderItems.Items.Count))
'So we have the array of ids for the emails, now fetch the emails themselves
Dim resItemIDs As ItemIdType() = Nothing
'collect the ids up
For x As Integer = 0 To resFolderItems.Items.Count - 1
If IsNothing(resItemIDs) Then ReDim resItemIDs(0) Else ReDim Preserve resItemIDs(resItemIDs.Length)
resItemIDs(x) = resFolderItems.Items(x).ItemId
Next
'go get the email messages
Dim resGetItem As GetItemResponseType = esb.GetItem(New GetItemType With { _
.ItemShape = New ItemResponseShapeType With {.BaseShape = DefaultShapeNamesType.AllProperties _
, .BodyType = BodyTypeResponseType.Text _
, .BodyTypeSpecified = True} _
, .ItemIds = resItemIDs})
'declare and fill up the message array that we are going to return
Dim resItemMessage As ItemType() = Nothing
For x As Integer = 0 To resGetItem.ResponseMessages.Items.Length - 1
If IsNothing(resItemMessage) Then ReDim resItemMessage(0) Else ReDim Preserve resItemMessage(resItemMessage.Length)
resItemMessage(x) = DirectCast(resGetItem.ResponseMessages.Items(x), ItemInfoResponseMessageType).Items.Items(0)
Next
'pass back the emails
Return resItemMessage
Else
TraceLog.AppendLine("no unread mail found closing out")
Return Nothing
End If
End If
========== UPDATE ============
With a nudge in the right direction from Glen Scales we have Success! EWS is a mine field of types and derived types.
'create the finditemtype and load the restrictions
'first only the unread messages
'secondly, only of type "IPM.Note" ie just emails
Dim reqFindUnreadMailInInbox As FindItemType = New FindItemType With _
{.Traversal = ItemQueryTraversalType.Shallow _
, .ItemShape = New ItemResponseShapeType With {.BaseShape = DefaultShapeNamesType.IdOnly} _
, .ParentFolderIds = New DistinguishedFolderIdType(0) {New DistinguishedFolderIdType With {.Id = DistinguishedFolderIdNameType.inbox}} _
, .Restriction = New RestrictionType With {.Item = New AndType With { _
.Items = New IsEqualToType() { _
New IsEqualToType With {.Item = New PathToUnindexedFieldType With { _
.FieldURI = UnindexedFieldURIType.messageIsRead} _
, .FieldURIOrConstant = New FieldURIOrConstantType With {.Item = New ConstantValueType With {.Value = "0"}} _
} _
, New IsEqualToType With {.Item = New PathToUnindexedFieldType With { _
.FieldURI = UnindexedFieldURIType.itemItemClass} _
, .FieldURIOrConstant = New FieldURIOrConstantType With {.Item = New ConstantValueType With {.Value = "IPM.Note"}} _
} _
}}}}
Thanks goes to Glen Scales!
Upvotes: 0
Views: 260
Reputation: 22032
You need to use the AndType https://msdn.microsoft.com/en-us/library/office/exchangewebservices.andtype(v=exchg.150).aspx
Then define and add two isEqual Restrictions to that eg
RestrictionType restriction = new RestrictionType();
AndType andType = new AndType();
andType.Items = new SearchExpressionType[] { IsEqual1,IsEqual2 };
restriction.Item = andType;
Cheers Glen
Upvotes: 1