OfficeDev / ews-managed-api

Other
583 stars 317 forks source link

Entries from Microsoft Bookings appear in EWS response and lead to NullReferenceException (using Exchange Online) #295

Open alex3683 opened 1 year ago

alex3683 commented 1 year ago

First a short note: I know that EWS for Exchange Online is discontinued and that MS Graph API should be used. We are going to switch to that, but it will take us some time. In the mean time we still have to support EWS for our customers. And I think the fix / Workaround could be quite simple, alas it can only implemented within the EWS managed API and not client code.

We observed the following symptom: Calling ExchangeService.SyncFolderItems failed for some users with the following exception and stack trace:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.Exchange.WebServices.Data.SyncResponse`2.ReadElementsFromXml(EwsServiceXmlReader reader)
   at Microsoft.Exchange.WebServices.Data.ServiceResponse.LoadFromXml(EwsServiceXmlReader reader, String xmlElementName)
   at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.ParseResponse(EwsServiceXmlReader reader)
   at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ParseResponse(EwsServiceXmlReader reader, WebHeaderCollection responseHeaders)
   at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ReadResponse(EwsServiceXmlReader ewsXmlReader, WebHeaderCollection responseHeaders)
   at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.ReadResponseXml(Stream responseStream, WebHeaderCollection responseHeaders)
   at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.ReadResponse(IEwsHttpWebResponse response)
   at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.InternalExecute()
   at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
   at Microsoft.Exchange.WebServices.Data.ExchangeService.SyncFolderItems(FolderId syncFolderId, PropertySet propertySet, IEnumerable`1 ignoredItemIds, Int32 maxChangesReturned, Int32 numberOfDays, SyncFolderItemsScope syncScope, String syncState)
   at Microsoft.Exchange.WebServices.Data.ExchangeService.SyncFolderItems(FolderId syncFolderId, PropertySet propertySet, IEnumerable`1 ignoredItemIds, Int32 maxChangesReturned, SyncFolderItemsScope syncScope, String syncState)

I then asked the customer to provide an EWS Trace. This contained a lot of the well known <t:CalendarItem> elements, but far at the end an <t:Booking>, which seems to come from Microsoft Bookings . In parallel I had a look at the source of the EWS managed API and looked for a spot, where the NRE could occur. This then fell into my eye: https://github.com/OfficeDev/ews-managed-api/blob/25a393dbc68b420d25999bdf0a03c23d86412f57/Core/Responses/SyncResponse.cs#L153-L155

So in case EwsUtilities.CreateEwsObjectFromXmlElementName<TServiceObject> cannot provide an instance for the element it returns default (https://github.com/OfficeDev/ews-managed-api/blob/25a393dbc68b420d25999bdf0a03c23d86412f57/Core/EwsUtilities.cs#L309), so in practice null and https://github.com/OfficeDev/ews-managed-api/blob/25a393dbc68b420d25999bdf0a03c23d86412f57/Core/Responses/SyncResponse.cs#L157 will throw the NRE. And in fact no element t:booking is registered here https://github.com/OfficeDev/ews-managed-api/blob/25a393dbc68b420d25999bdf0a03c23d86412f57/Core/ServiceObjects/ServiceObjectInfo.cs#L66

It seems that this library had the same issue: https://github.com/ecederstrand/exchangelib/issues/877

So my question is: What can we do, until we switch to Graph, to mitigate this? Is there any workaround we can implement on our side? Disabling Microsoft Bookings is no option. Honestly I fear there is no local workaround.

So would it be possible to provide a EWS managed API version that is more lenient in that regard and (maybe optionally) ignores new, unknown element types? The implementation would be quite simple. For me this just seems like a breaking change from Microsoft. We're quite stuck here ...

EDIT: This is what the Booking looks like, apart from the stuff after organizer much like a calendar item (XXXX where sensitive data was):

 <t:Booking>
                  <t:ItemId Id="XXXX" ChangeKey="XXXX" />
                  <t:Subject>XXXX</t:Subject>
                  <t:Sensitivity>Normal</t:Sensitivity>
                  <t:Importance>Normal</t:Importance>
                  <t:ExtendedProperty>
                    <t:ExtendedFieldURI DistinguishedPropertySetId="Meeting" PropertyId="35" PropertyType="Binary" />
                    <t:Value>XXXX</t:Value>
                  </t:ExtendedProperty>
                  <t:LastModifiedTime>2023-03-02T06:56:34Z</t:LastModifiedTime>
                  <t:Start>2023-03-02T07:10:00Z</t:Start>
                  <t:End>2023-03-02T07:40:00Z</t:End>
                  <t:IsAllDayEvent>false</t:IsAllDayEvent>
                  <t:LegacyFreeBusyStatus>Busy</t:LegacyFreeBusyStatus>
                  <t:Location />
                  <t:IsMeeting>true</t:IsMeeting>
                  <t:IsCancelled>false</t:IsCancelled>
                  <t:CalendarItemType>Single</t:CalendarItemType>
                  <t:MyResponseType>Organizer</t:MyResponseType>
                  <t:Organizer>
                    <t:Mailbox>
                      <t:Name>XXXX</t:Name>
                      <t:EmailAddress>XXXX@XXXX</t:EmailAddress>
                      <t:RoutingType>SMTP</t:RoutingType>
                      <t:MailboxType>Mailbox</t:MailboxType>
                    </t:Mailbox>
                  </t:Organizer>
                  <t:PreBuffer>0</t:PreBuffer>
                  <t:PostBuffer>0</t:PostBuffer>
                  <t:PricingType>Undefined</t:PricingType>
                  <t:Price>0</t:Price>
                  <t:BookingFee>0</t:BookingFee>
                  <t:BookingTax>0</t:BookingTax>
                  <t:SelfServiceId>00000000-0000-0000-0000-000000000000</t:SelfServiceId>
                </t:Booking>
SchultzAndreas commented 1 year ago

I fixed the bug. You are welcome to clone my fork, the only change is adding the booking element.

jbennink commented 2 months ago

@SchultzAndreas Thanks for this. I ran into this as well, apparently when Booking is enabled on the account you can get this, did not see this before. I am running on a fork by @sherlock1982 so I added your fix to my own fork of that fork :-|