We’ve recently had a few cases where some SOAP headers were missing from the request when performing specific operations and targeting specific Exchange versions. This resulted in incorrect data being returned.

For example, if you Target Exchange2010 or higher and wish to reply to or forward an EmailMessage, the TimeZone information specified when creating the Exchange service will not be added as a SOAP header to the request. For this reason, the Sent time returned in the reply body will be the UTC (Universal Coordinated Time) instead the local time or the time as per the TimeZone specified.

Note: You will not experience this issue if you target Exchange2007_SP1.

For example, if the TimeZone specified is FLE Standard Time (Standard: UTC+2 / Daylight: UTC+3) and the message was sent at 18:44 on the 17th April 2014, the Sent time in the reply body will be 15:44.

Original message

TimeZoneHeader1

Text displayed in the reply body

TimeZoneHeader2

When comparing the SOAP requests generated when targeting Exchange2007_SP1 and Exchange2010, we notice that the TimeZoneDefinition SOAP header is missing from the Exchange2010 request:

      <t:TimeZoneContext>

        <t:TimeZoneDefinition Id="FLE Standard Time" />

      </t:TimeZoneContext>

The workaround:

To allow adding missing or just custom SOAP headers, a new event was added to the ExchangeService class implemented by the EWS Managed API. The event is called OnSerializeCustomSoapHeaders and represents the event that is called to enable applications to emit custom SOAP headers in requests that are sent to Microsoft Exchange Server.

Here is an example on how to use it:

public void DoSomething()
{
    ExchangeService m_Service = new ExchangeService(ExchangeVersion.Exchange2010, TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));
    m_Service.OnSerializeCustomSoapHeaders += m_Service_OnSerializeCustomSoapHeaders;
    //
    // Your code here
    //
    m_Service.OnSerializeCustomSoapHeaders -= new Microsoft.Exchange.WebServices.Data.CustomXmlSerializationDelegate(m_Service_OnSerializeCustomSoapHeaders);
    }

public void m_Service_OnSerializeCustomSoapHeaders(XmlWriter writer)
{
    writer.WriteRaw(Environment.NewLine + "    <t:TimeZoneContext><t:TimeZoneDefinition Id=\"" + m_Service.TimeZone.StandardName + "\"/></t:TimeZoneContext>" + Environment.NewLine);
}

Note: You can use the OnSerializeCustomSoapHeaders to add any SOAP headers.