/// <summary> /// Start loading the current requested message. /// </summary> /// <param name="message">The message object that will contain the message data.</param> private void LoadEmail(Message message) { NumberGenerator randomNumber = new NumberGenerator(); UpperCaseGenerator randomUpper = new UpperCaseGenerator(); _prefixNumber = randomUpper.Random(1) + randomNumber.Random(3); // If only message header data is required. if (_headersOnly) { if (_headerLineCount > 0) { // Send a command to the server indicating that // only body data is required. Send the message // position and the number of the body header, // '1' indicates only body text.. SendCommand(_prefixNumber + " FETCH " + _inboxPosition + ":" + _inboxPosition + " BODY[" + _headerLineCount + "]"); } else { // Send a command to the server indicating that // only header data is required. Send the message // position and the number of message lines to return. SendCommand(_prefixNumber + " FETCH " + _inboxPosition + ":" + _inboxPosition + " BODY[HEADER]"); } } else { // Send a command to return the entire // message. Send the message position. SendCommand(_prefixNumber + " FETCH " + _inboxPosition + ":" + _inboxPosition + " BODY[]"); } // Start the receive process // at this point, and return the state // object that contains the email message // built from the string builder. Imap4StateAdapter state = StartReceive(); // Return the complete raw email message only if (_rawEmailMessageOnly) { // Assign the complete email message. message.RawEmailMessage = state.EmailMessage.ToString(); } else { // Parse the email message for header processing // of the line within the email message. ParseEmail(state.EmailMessage.ToString().Split(new char[] { '\r' })); } }
/// <summary> /// Start receiving the email message. /// </summary> /// <returns>The current state object.</returns> private Imap4StateAdapter StartReceive() { // The manual reset event handler user to // block the current thread until the operation // completes the task, and create a new state // object to hold all state data. ManualResetEvent waitObject = null; Imap4StateAdapter state = new Imap4StateAdapter(); // Assign the current client // socket object. state.Socket = _socket; state.SslClient = _sslStream; // Get the event to wait on. waitObject = state.ReceiveComplete; // If a secure connection is required. if (_connection.UseSSLConnection) { // Start receiving data asynchrounusly. lock (_sslStream) _sslStream.BeginRead(_buffer, 0, EmailMessageParse.MAX_BUFFER_READ_SIZE, new AsyncCallback(ReceiveCallback), state); } else { // Start receiving data asynchrounusly. lock (_socket) _socket.BeginReceive(_buffer, 0, EmailMessageParse.MAX_BUFFER_READ_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } // Block the current thread until all // operations are complete. waitObject.WaitOne(); // The operations either completed or threw an exception. if (state.OperationException != null) { throw state.OperationException; } // Return the state object. return(state); }
/// <summary> /// Receive call back asynchrounus result. /// Handles the receiving of the email message. /// </summary> /// <param name="ar">The current asynchronus result.</param> private void ReceiveCallback(IAsyncResult ar) { // Get the state adapter from the // async result object. Imap4StateAdapter state = (Imap4StateAdapter)ar.AsyncState; try { // Get the socket from the // state adapter. Socket socket = state.Socket; SslStream sslStream = state.SslClient; // Read data from the remote device. int bytesRead = 0; // If a secure connection is required. if (_connection.UseSSLConnection) { lock (sslStream) // End the current asynchrounus // read operation. bytesRead = sslStream.EndRead(ar); } else { lock (socket) // End the current asynchrounus // read operation. bytesRead = socket.EndReceive(ar); } if (bytesRead > 0) { // Decode the current buffer and add the new data // to the message string builder. state.EmailMessage.Append(Encoding.ASCII.GetString(_buffer, 0, bytesRead)); // If the progress call back handler // is not null then send to the client // the number of bytes read. if (_callbackHandler != null) { _callbackHandler((long)bytesRead); } } // Receive more data if we expect more. // note: a literal "." (or more) followed by // "OK" in an email is prefixed a value if (!state.EmailMessage.ToString().Contains(_prefixNumber + " OK") && !state.EmailMessage.ToString().Contains(_prefixNumber + " NO") && !state.EmailMessage.ToString().Contains(_prefixNumber + " BAD")) { // If a secure connection is required. if (_connection.UseSSLConnection) { lock (sslStream) sslStream.BeginRead(_buffer, 0, EmailMessageParse.MAX_BUFFER_READ_SIZE, new AsyncCallback(ReceiveCallback), state); } else { lock (socket) socket.BeginReceive(_buffer, 0, EmailMessageParse.MAX_BUFFER_READ_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } } else { // The end of the message has been reached // indicate by the ManualResetEvent thread // handler the that operation is complete // indicated to the ManualResetEvent handler // to stop blocking. state.ReceiveComplete.Set(); } } catch (Exception e) { // An exception has occurred, assign the // current operation exception and set // the recieved ManualResetEvent thread // handler to set indicating that the // operation must stop. state.OperationException = e; state.ReceiveComplete.Set(); } }