0

I ran into an issue recently when in an existing Console Application project we're forced to remove a reference to WSE 3.0. When I tried to remove it from references (because I could not find where it's used) it turned out there is only one place and it's using the SoapEnvelope class.

A little bit about the application: it's a console application that connects to an Exchange Server and listens to incoming emails, around 2-3k emails daily.

The SoapEnvelope class is used to read and parse the email body:

    /// <summary>
    /// Reads content of received HTTP request. 
    /// </summary>
    /// <param name="client">The specified client.</param>
    /// <returns>The watermark string if the read is successful; otherwise the last watermark.</returns>
    public string Read(TcpClient client)
    {
        try
        {
            _myReadBuffer = new byte[client.ReceiveBufferSize];

            using (var networkStream = client.GetStream())
            { 
                var httpRequest = new MailboxHttpRequest(networkStream);

                if (httpRequest.HasBody)
                {
                    var httpResponse = new MailboxHttpResponse(_mailbox);

                    httpResponse.ParseBody(httpRequest.Body);
                    httpResponse.Send(networkStream, httpRequest.Body);
                }

                return httpRequest.Watermark;
            }
        }
        catch (Exception ex)
        {
            Logger.WriteErrorLine("[EventsCollector] Error calling Read in MailboxNotificationManager", ex);

            return _mailbox.LastWatermark;
        }
        finally
        {
            _myReadBuffer = null;
        }
    }

And the ParseBody methods looks like this:

        /// <summary>
        /// Parses the XML body content of receive notification and initialized email processing, if new message was received.
        /// </summary>
        /// <param name="body">XML content of received notification.</param>
        public void ParseBody(string body)
        {
            var soapEnvelope = new SoapEnvelope() { InnerXml = body };

            var serializer = new XmlSerializer(typeof(SendNotificationResponseType));

            using (var reader = new XmlNodeReader(soapEnvelope.Body.FirstChild))
            {
                var notificationResponse = (SendNotificationResponseType)serializer.Deserialize(reader);

                if (notificationResponse.ResponseMessages != null)  // Process notification, if request contains response message
                {
                    _result = processNotification(notificationResponse);
                }
            }
        }

As you can see, it creates a SoapEnvelope class to access the body`s first child.

MailboxHttpRequest class

private class MailboxHttpRequest
        {
            private readonly Regex _httpRequestBodyLengthPattern = new Regex(@"Content-Length: (?<BodyLength>\d*)", RegexOptions.Compiled);
            private readonly Regex _httpRequestBodyPattern = new Regex(@"<\?xml .*", RegexOptions.Compiled);
            private readonly Regex _httpRequestWatermarkPattern = new Regex(@"<t:Watermark>(?<Watermark>.*?)<\/t:Watermark>", RegexOptions.Compiled);

            private const int _bufferSize = 8192;

            public bool HasBody
            {
                get { return !String.IsNullOrEmpty(Body); }
            }

            public string Body { get; private set; }

            public string Watermark { get; private set; }

            /// <summary>
            /// Initializes a new instance of the <see cref="MailboxHttpRequest"/> class and reads incoming messages
            /// </summary>
            /// <param name="networkStream">The network stream.</param>
            public MailboxHttpRequest(NetworkStream networkStream)
            {
                var completeRequest = new StringBuilder();
                var readBuffer = new byte[_bufferSize];

                do  // Read incoming message that might consist of many parts
                {
                    var newDataLength = networkStream.Read(readBuffer, 0, readBuffer.Length);
                    completeRequest.Append(Encoding.ASCII.GetString(readBuffer, 0, newDataLength));
                }
                while (networkStream.DataAvailable || !requestWasFullyReceived(completeRequest.ToString()));

                Body = _httpRequestBodyPattern.Match(completeRequest.ToString())
                                                                    .Value;
                Watermark = _httpRequestWatermarkPattern.Match(Body).Groups["Watermark"].Value;
            }
}

The downside is that I`m not able test this part of code since I cant listen to same mailbox so I cant check what and how does the passed string look like.

If anybody has any suggestion on how to replace the SoapEnvelope class, would be greatly appreciate it.

Cosmin

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Cosmin
  • 152
  • 3
  • 18

0 Answers0