Ejemplo n.º 1
0
        public Pop3Command QueueCommand(CancellationToken cancellationToken, Pop3CommandHandler handler, Encoding encoding, string format, params object[] args)
        {
            var pc = new Pop3Command(cancellationToken, handler, encoding, format, args);

            pc.Id = nextId++;
            queue.Add(pc);
            return(pc);
        }
Ejemplo n.º 2
0
        async Task SendCommandAsync(Pop3Command pc, bool doAsync, CancellationToken cancellationToken)
        {
            var buf = pc.Encoding.GetBytes(pc.Command + "\r\n");

            if (doAsync)
            {
                await stream.WriteAsync(buf, 0, buf.Length, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                stream.Write(buf, 0, buf.Length, cancellationToken);
            }
        }
Ejemplo n.º 3
0
        void ProcessCommand(Pop3Command pc)
        {
            string response, text;

            byte[] buf;

            buf = Encoding.UTF8.GetBytes(pc.Command + "\r\n");
            stream.Write(buf, 0, buf.Length);

            try {
                response = ReadLine(pc.CancellationToken).TrimEnd();
            } catch {
                pc.Status = Pop3CommandStatus.ProtocolError;
                Disconnect();
                throw;
            }

            pc.Status = GetCommandStatus(response, out text);
            switch (pc.Status)
            {
            case Pop3CommandStatus.ProtocolError:
                Disconnect();
                throw new Pop3ProtocolException(string.Format("Unexpected response from server: {0}", response));

            case Pop3CommandStatus.Continue:
            case Pop3CommandStatus.Ok:
                if (pc.Handler != null)
                {
                    try {
                        pc.Handler(this, pc, text);
                    } catch {
                        pc.Status = Pop3CommandStatus.ProtocolError;
                        Disconnect();
                        throw;
                    }
                }
                break;
            }
        }
Ejemplo n.º 4
0
        async Task ReadResponseAsync(Pop3Command pc, bool doAsync)
        {
            string response, text;

            try {
                response = (await ReadLineAsync(doAsync, pc.CancellationToken).ConfigureAwait(false)).TrimEnd();
            } catch {
                pc.Status = Pop3CommandStatus.ProtocolError;
                Disconnect();
                throw;
            }

            pc.Status     = GetCommandStatus(response, out text);
            pc.StatusText = text;

            switch (pc.Status)
            {
            case Pop3CommandStatus.ProtocolError:
                Disconnect();
                throw new Pop3ProtocolException(string.Format("Unexpected response from server: {0}", response));

            case Pop3CommandStatus.Continue:
            case Pop3CommandStatus.Ok:
                if (pc.Handler != null)
                {
                    try {
                        await pc.Handler(this, pc, text, doAsync).ConfigureAwait(false);
                    } catch {
                        pc.Status = Pop3CommandStatus.ProtocolError;
                        Disconnect();
                        throw;
                    }
                }
                break;
            }
        }
Ejemplo n.º 5
0
        void ReadResponse(Pop3Command pc)
        {
            string response, text;

            try {
                response = ReadLine(pc.CancellationToken).TrimEnd();
            } catch {
                pc.Status = Pop3CommandStatus.ProtocolError;
                Disconnect();
                throw;
            }

            pc.Status     = GetCommandStatus(response, out text);
            pc.StatusText = text;

            switch (pc.Status)
            {
            case Pop3CommandStatus.ProtocolError:
                Disconnect();
                throw new Pop3ProtocolException(string.Format("Unexpected response from server: {0}", response));

            case Pop3CommandStatus.Continue:
            case Pop3CommandStatus.Ok:
                if (pc.Handler != null)
                {
                    try {
                        pc.Handler(this, pc, text);
                    } catch {
                        pc.Status = Pop3CommandStatus.ProtocolError;
                        Disconnect();
                        throw;
                    }
                }
                break;
            }
        }
Ejemplo n.º 6
0
        static ProtocolException CreatePop3Exception(Pop3Command pc)
        {
            var command = pc.Command.Split (' ')[0].TrimEnd ();
            var message = string.Format ("POP3 server did not respond with a +OK response to the {0} command.", command);

            if (pc.Status == Pop3CommandStatus.Error)
                return new Pop3CommandException (message);

            return new Pop3ProtocolException (message);
        }
Ejemplo n.º 7
0
        static async Task CapaHandler(Pop3Engine engine, Pop3Command pc, string text, bool doAsync)
        {
            if (pc.Status != Pop3CommandStatus.Ok)
            {
                return;
            }

            string response;

            do
            {
                if ((response = await engine.ReadLineAsync(doAsync, pc.CancellationToken).ConfigureAwait(false)) == ".")
                {
                    break;
                }

                int index = response.IndexOf(' ');
                int startIndex, length, value;

                if (index == -1)
                {
                    index = response.Length;
                }

                if (IsCapability("EXPIRE", response, index, true))
                {
                    engine.Capabilities |= Pop3Capabilities.Expire;

                    if (ReadNextToken(response, ref index, out startIndex, out length))
                    {
                        if (IsToken("NEVER", response, startIndex, length))
                        {
                            engine.ExpirePolicy = -1;
                        }
                        else if (TryParseInt32(response, startIndex, length, out value))
                        {
                            engine.ExpirePolicy = value;
                        }
                    }
                }
                else if (IsCapability("IMPLEMENTATION", response, index, true))
                {
                    engine.Implementation = response.Substring(index + 1);
                }
                else if (IsCapability("LANG", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.Lang;
                }
                else if (IsCapability("LOGIN-DELAY", response, index, true))
                {
                    if (ReadNextToken(response, ref index, out startIndex, out length))
                    {
                        if (TryParseInt32(response, startIndex, length, out value))
                        {
                            engine.Capabilities |= Pop3Capabilities.LoginDelay;
                            engine.LoginDelay    = value;
                        }
                    }
                }
                else if (IsCapability("PIPELINING", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.Pipelining;
                }
                else if (IsCapability("RESP-CODES", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.ResponseCodes;
                }
                else if (IsCapability("SASL", response, index, true))
                {
                    engine.Capabilities |= Pop3Capabilities.Sasl;
                    engine.AddAuthenticationMechanisms(response, index);
                }
                else if (IsCapability("STLS", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.StartTLS;
                }
                else if (IsCapability("TOP", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.Top;
                }
                else if (IsCapability("UIDL", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.UIDL;
                }
                else if (IsCapability("USER", response, index))
                {
                    engine.Capabilities |= Pop3Capabilities.User;
                }
                else if (IsCapability("UTF8", response, index, true))
                {
                    engine.Capabilities |= Pop3Capabilities.UTF8;

                    while (ReadNextToken(response, ref index, out startIndex, out length))
                    {
                        if (IsToken("USER", response, startIndex, length))
                        {
                            engine.Capabilities |= Pop3Capabilities.UTF8User;
                        }
                    }
                }
            } while (true);
        }
Ejemplo n.º 8
0
        void ProcessCommand(Pop3Command pc)
        {
            string response, text;
            byte[] buf;

            buf = Encoding.UTF8.GetBytes (pc.Command + "\r\n");
            stream.Write (buf, 0, buf.Length);

            try {
                response = ReadLine (pc.CancellationToken).TrimEnd ();
            } catch {
                pc.Status = Pop3CommandStatus.ProtocolError;
                Disconnect ();
                throw;
            }

            pc.Status = GetCommandStatus (response, out text);
            switch (pc.Status) {
            case Pop3CommandStatus.ProtocolError:
                Disconnect ();
                throw new Pop3ProtocolException (string.Format ("Unexpected response from server: {0}", response));
            case Pop3CommandStatus.Continue:
            case Pop3CommandStatus.Ok:
                if (pc.Handler != null) {
                    try {
                        pc.Handler (this, pc, text);
                    } catch {
                        pc.Status = Pop3CommandStatus.ProtocolError;
                        Disconnect ();
                        throw;
                    }
                }
                break;
            }
        }
Ejemplo n.º 9
0
        static void CapaHandler(Pop3Engine engine, Pop3Command pc, string text)
        {
            // clear all CAPA response capabilities (except the APOP capability)
            engine.Capabilities &= Pop3Capabilities.Apop;
            engine.AuthenticationMechanisms.Clear ();
            engine.Implementation = null;
            engine.ExpirePolicy = 0;
            engine.LoginDelay = 0;

            if (pc.Status != Pop3CommandStatus.Ok)
                return;

            string response;

            do {
                if ((response = engine.ReadLine (pc.CancellationToken).TrimEnd ()) == ".")
                    break;

                int index = response.IndexOf (' ');
                string token, data;
                int value;

                if (index != -1) {
                    token = response.Substring (0, index);

                    while (index < response.Length && char.IsWhiteSpace (response[index]))
                        index++;

                    if (index < response.Length)
                        data = response.Substring (index);
                    else
                        data = string.Empty;
                } else {
                    data = string.Empty;
                    token = response;
                }

                switch (token) {
                case "EXPIRE":
                    engine.Capabilities |= Pop3Capabilities.Expire;
                    var tokens = data.Split (' ');

                    if (int.TryParse (tokens[0], out value))
                        engine.ExpirePolicy = value;
                    else if (tokens[0] == "NEVER")
                        engine.ExpirePolicy = -1;
                    break;
                case "IMPLEMENTATION":
                    engine.Implementation = data;
                    break;
                case "LOGIN-DELAY":
                    if (int.TryParse (data, out value)) {
                        engine.Capabilities |= Pop3Capabilities.LoginDelay;
                        engine.LoginDelay = value;
                    }
                    break;
                case "PIPELINING":
                    engine.Capabilities |= Pop3Capabilities.Pipelining;
                    break;
                case "RESP-CODES":
                    engine.Capabilities |= Pop3Capabilities.ResponseCodes;
                    break;
                case "SASL":
                    engine.Capabilities |= Pop3Capabilities.Sasl;
                    foreach (var authmech in data.Split (new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
                        engine.AuthenticationMechanisms.Add (authmech);
                    break;
                case "STLS":
                    engine.Capabilities |= Pop3Capabilities.StartTLS;
                    break;
                case "TOP":
                    engine.Capabilities |= Pop3Capabilities.Top;
                    break;
                case "UIDL":
                    engine.Capabilities |= Pop3Capabilities.UIDL;
                    break;
                case "USER":
                    engine.Capabilities |= Pop3Capabilities.User;
                    break;
                }
            } while (true);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Mark the specified messages for deletion.
        /// </summary>
        /// <remarks>
        /// Messages marked for deletion are not actually deleted until the session
        /// is cleanly disconnected
        /// (see <see cref="Pop3Client.Disconnect(bool, CancellationToken)"/>).
        /// </remarks>
        /// <param name="indexes">The indexes of the messages.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="indexes"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <para>One or more of the <paramref name="indexes"/> are invalid.</para>
        /// <para>-or-</para>
        /// <para>No indexes were specified.</para>
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="Pop3Client"/> has been disposed.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// The <see cref="Pop3Client"/> is not connected.
        /// </exception>
        /// <exception cref="System.UnauthorizedAccessException">
        /// The <see cref="Pop3Client"/> is not authenticated.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="Pop3CommandException">
        /// The POP3 command failed.
        /// </exception>
        /// <exception cref="Pop3ProtocolException">
        /// A POP3 protocol error occurred.
        /// </exception>
        public override void DeleteMessages(IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken))
        {
            if (indexes == null)
                throw new ArgumentNullException ("indexes");

            if (indexes.Count == 0)
                throw new ArgumentException ("No indexes specified.", "indexes");

            CheckDisposed ();
            CheckConnected ();

            if (engine.State != Pop3EngineState.Transaction)
                throw new UnauthorizedAccessException ();

            var seqids = new int[indexes.Count];

            for (int i = 0; i < indexes.Count; i++) {
                if (indexes[i] < 0 || indexes[i] >= total)
                    throw new ArgumentException ("One or more of the indexes are invalid.", "indexes");

                seqids[i] = indexes[i] + 1;
            }

            if ((Capabilities & Pop3Capabilities.Pipelining) == 0) {
                for (int i = 0; i < seqids.Length; i++)
                    SendCommand (cancellationToken, "DELE {0}", seqids[i]);

                return;
            }

            var commands = new Pop3Command[seqids.Length];
            Pop3Command pc = null;

            for (int i = 0; i < seqids.Length; i++) {
                pc = engine.QueueCommand (cancellationToken, null, "DELE {0}", seqids[i]);
                commands[i] = pc;
            }

            while (engine.Iterate () < pc.Id) {
                // continue processing commands
            }

            for (int i = 0; i < commands.Length; i++) {
                if (commands[i].Status != Pop3CommandStatus.Ok)
                    throw CreatePop3Exception (commands[i]);
            }
        }
Ejemplo n.º 11
0
        static void CapaHandler(Pop3Engine engine, Pop3Command pc, string text)
        {
            // clear all CAPA response capabilities (except the APOP capability)
            engine.Capabilities &= Pop3Capabilities.Apop;
            engine.AuthenticationMechanisms.Clear();
            engine.Implementation = null;
            engine.ExpirePolicy   = 0;
            engine.LoginDelay     = 0;

            if (pc.Status != Pop3CommandStatus.Ok)
            {
                return;
            }

            string response;

            do
            {
                if ((response = engine.ReadLine(pc.CancellationToken).TrimEnd()) == ".")
                {
                    break;
                }

                int    index = response.IndexOf(' ');
                string token, data;
                int    value;

                if (index != -1)
                {
                    token = response.Substring(0, index);

                    while (index < response.Length && char.IsWhiteSpace(response[index]))
                    {
                        index++;
                    }

                    if (index < response.Length)
                    {
                        data = response.Substring(index);
                    }
                    else
                    {
                        data = string.Empty;
                    }
                }
                else
                {
                    data  = string.Empty;
                    token = response;
                }

                switch (token)
                {
                case "EXPIRE":
                    engine.Capabilities |= Pop3Capabilities.Expire;
                    var tokens = data.Split(' ');

                    if (int.TryParse(tokens[0], out value))
                    {
                        engine.ExpirePolicy = value;
                    }
                    else if (tokens[0] == "NEVER")
                    {
                        engine.ExpirePolicy = -1;
                    }
                    break;

                case "IMPLEMENTATION":
                    engine.Implementation = data;
                    break;

                case "LOGIN-DELAY":
                    if (int.TryParse(data, out value))
                    {
                        engine.Capabilities |= Pop3Capabilities.LoginDelay;
                        engine.LoginDelay    = value;
                    }
                    break;

                case "PIPELINING":
                    engine.Capabilities |= Pop3Capabilities.Pipelining;
                    break;

                case "RESP-CODES":
                    engine.Capabilities |= Pop3Capabilities.ResponseCodes;
                    break;

                case "SASL":
                    engine.Capabilities |= Pop3Capabilities.Sasl;
                    foreach (var authmech in data.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        engine.AuthenticationMechanisms.Add(authmech);
                    }
                    break;

                case "STLS":
                    engine.Capabilities |= Pop3Capabilities.StartTLS;
                    break;

                case "TOP":
                    engine.Capabilities |= Pop3Capabilities.Top;
                    break;

                case "UIDL":
                    engine.Capabilities |= Pop3Capabilities.UIDL;
                    break;

                case "USER":
                    engine.Capabilities |= Pop3Capabilities.User;
                    break;

                case "UTF8":
                    engine.Capabilities |= Pop3Capabilities.UTF8;

                    foreach (var item in data.Split(' '))
                    {
                        if (item == "USER")
                        {
                            engine.Capabilities |= Pop3Capabilities.UTF8User;
                        }
                    }
                    break;

                case "LANG":
                    engine.Capabilities |= Pop3Capabilities.Lang;
                    break;
                }
            } while (true);
        }
Ejemplo n.º 12
0
        void SendCommand(Pop3Command pc)
        {
            var buf = Encoding.UTF8.GetBytes(pc.Command + "\r\n");

            stream.Write(buf, 0, buf.Length);
        }
Ejemplo n.º 13
0
		void ReadResponse (Pop3Command pc)
		{
			string response, text;

			try {
				response = ReadLine (pc.CancellationToken).TrimEnd ();
			} catch {
				pc.Status = Pop3CommandStatus.ProtocolError;
				Disconnect ();
				throw;
			}

			pc.Status = GetCommandStatus (response, out text);
			pc.StatusText = text;

			switch (pc.Status) {
			case Pop3CommandStatus.ProtocolError:
				Disconnect ();
				throw new Pop3ProtocolException (string.Format ("Unexpected response from server: {0}", response));
			case Pop3CommandStatus.Continue:
			case Pop3CommandStatus.Ok:
				if (pc.Handler != null) {
					try {
						pc.Handler (this, pc, text);
					} catch {
						pc.Status = Pop3CommandStatus.ProtocolError;
						Disconnect ();
						throw;
					}
				}
				break;
			}
		}
Ejemplo n.º 14
0
		void SendCommand (Pop3Command pc)
		{
			var buf = Encoding.UTF8.GetBytes (pc.Command + "\r\n");

			stream.Write (buf, 0, buf.Length);
		}
Ejemplo n.º 15
0
        /// <summary>
        /// Mark the specified range of messages for deletion.
        /// </summary>
        /// <remarks>
        /// Messages marked for deletion are not actually deleted until the session
        /// is cleanly disconnected
        /// (see <see cref="Pop3Client.Disconnect(bool, CancellationToken)"/>).
        /// </remarks>
        /// <param name="startIndex">The index of the first message to mark for deletion.</param>
        /// <param name="count">The number of messages to mark for deletion.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// <paramref name="startIndex"/> and <paramref name="count"/> do not specify
        /// a valid range of messages.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="Pop3Client"/> has been disposed.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// The <see cref="Pop3Client"/> is not connected.
        /// </exception>
        /// <exception cref="System.UnauthorizedAccessException">
        /// The <see cref="Pop3Client"/> is not authenticated.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="Pop3CommandException">
        /// The POP3 command failed.
        /// </exception>
        /// <exception cref="Pop3ProtocolException">
        /// A POP3 protocol error occurred.
        /// </exception>
        public override void DeleteMessages(int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken))
        {
            if (startIndex < 0 || startIndex >= total)
                throw new ArgumentOutOfRangeException ("startIndex");

            if (count < 0 || count > (total - startIndex))
                throw new ArgumentOutOfRangeException ("count");

            CheckDisposed ();
            CheckConnected ();

            if (engine.State != Pop3EngineState.Transaction)
                throw new UnauthorizedAccessException ();

            if (count == 0)
                return;

            if ((Capabilities & Pop3Capabilities.Pipelining) == 0) {
                for (int i = 0; i < count; i++)
                    SendCommand (cancellationToken, "DELE {0}", startIndex + i + 1);

                return;
            }

            var commands = new Pop3Command[count];
            Pop3Command pc = null;

            for (int i = 0; i < count; i++) {
                pc = engine.QueueCommand (cancellationToken, null, "DELE {0}", startIndex + i + 1);
                commands[i] = pc;
            }

            while (engine.Iterate () < pc.Id) {
                // continue processing commands
            }

            for (int i = 0; i < commands.Length; i++) {
                if (commands[i].Status != Pop3CommandStatus.Ok)
                    throw CreatePop3Exception (commands[i]);
            }
        }
Ejemplo n.º 16
0
 public Pop3Command QueueCommand(CancellationToken cancellationToken, string format, params object[] args)
 {
     var pc = new Pop3Command (cancellationToken, format, args);
     pc.Id = nextId++;
     queue.Add (pc);
     return pc;
 }
Ejemplo n.º 17
0
        static async Task CapaHandler(Pop3Engine engine, Pop3Command pc, string text, bool doAsync)
        {
            if (pc.Status != Pop3CommandStatus.Ok)
            {
                return;
            }

            string response;

            do
            {
                if ((response = await engine.ReadLineAsync(doAsync, pc.CancellationToken).ConfigureAwait(false)) == ".")
                {
                    break;
                }

                int    index = response.IndexOf(' ');
                string token, data;
                int    value;

                if (index != -1)
                {
                    token = response.Substring(0, index);

                    while (index < response.Length && char.IsWhiteSpace(response[index]))
                    {
                        index++;
                    }

                    if (index < response.Length)
                    {
                        data = response.Substring(index);
                    }
                    else
                    {
                        data = string.Empty;
                    }
                }
                else
                {
                    data  = string.Empty;
                    token = response;
                }

                switch (token)
                {
                case "EXPIRE":
                    engine.Capabilities |= Pop3Capabilities.Expire;
                    var tokens = data.Split(' ');

                    if (int.TryParse(tokens[0], NumberStyles.None, CultureInfo.InvariantCulture, out value))
                    {
                        engine.ExpirePolicy = value;
                    }
                    else if (tokens[0] == "NEVER")
                    {
                        engine.ExpirePolicy = -1;
                    }
                    break;

                case "IMPLEMENTATION":
                    engine.Implementation = data;
                    break;

                case "LOGIN-DELAY":
                    if (int.TryParse(data, NumberStyles.None, CultureInfo.InvariantCulture, out value))
                    {
                        engine.Capabilities |= Pop3Capabilities.LoginDelay;
                        engine.LoginDelay    = value;
                    }
                    break;

                case "PIPELINING":
                    engine.Capabilities |= Pop3Capabilities.Pipelining;
                    break;

                case "RESP-CODES":
                    engine.Capabilities |= Pop3Capabilities.ResponseCodes;
                    break;

                case "SASL":
                    engine.Capabilities |= Pop3Capabilities.Sasl;
                    foreach (var authmech in data.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        engine.AuthenticationMechanisms.Add(authmech);
                    }
                    break;

                case "STLS":
                    engine.Capabilities |= Pop3Capabilities.StartTLS;
                    break;

                case "TOP":
                    engine.Capabilities |= Pop3Capabilities.Top;
                    break;

                case "UIDL":
                    engine.Capabilities |= Pop3Capabilities.UIDL;
                    break;

                case "USER":
                    engine.Capabilities |= Pop3Capabilities.User;
                    break;

                case "UTF8":
                    engine.Capabilities |= Pop3Capabilities.UTF8;

                    foreach (var item in data.Split(' '))
                    {
                        if (item == "USER")
                        {
                            engine.Capabilities |= Pop3Capabilities.UTF8User;
                        }
                    }
                    break;

                case "LANG":
                    engine.Capabilities |= Pop3Capabilities.Lang;
                    break;
                }
            } while (true);
        }
Ejemplo n.º 18
0
        IList<MimeMessage> GetMessagesForSequenceIds(IList<int> seqids, bool headersOnly, CancellationToken cancellationToken)
        {
            var messages = new List<MimeMessage> ();

            if ((Capabilities & Pop3Capabilities.Pipelining) == 0) {
                for (int i = 0; i < seqids.Count; i++)
                    messages.Add (GetMessageForSequenceId (seqids[i], headersOnly, cancellationToken));

                return messages;
            }

            var commands = new Pop3Command[seqids.Count];
            Pop3Command pc = null;

            Pop3CommandHandler handler = (pop3, cmd, text) => {
                if (cmd.Status != Pop3CommandStatus.Ok)
                    return;

                try {
                    pop3.Stream.Mode = Pop3StreamMode.Data;

                    messages.Add (ParseMessage (cancellationToken));
                } catch (FormatException ex) {
                    // consume any remaining data and capture the exception...
                    cmd.Exception = CreatePop3ParseException (ex, "Failed to parse message.");
                    pop3.Stream.CopyTo (Stream.Null, 4096);
                } finally {
                    pop3.Stream.Mode = Pop3StreamMode.Line;
                }
            };

            for (int i = 0; i < seqids.Count; i++) {
                if (headersOnly)
                    pc = engine.QueueCommand (cancellationToken, handler, "TOP {0} 0", seqids[i]);
                else
                    pc = engine.QueueCommand (cancellationToken, handler, "RETR {0}", seqids[i]);

                commands[i] = pc;
            }

            while (engine.Iterate () < pc.Id) {
                // continue processing commands
            }

            for (int i = 0; i < commands.Length; i++) {
                if (commands[i].Status != Pop3CommandStatus.Ok)
                    throw CreatePop3Exception (commands[i]);

                if (commands[i].Exception != null)
                    throw commands[i].Exception;
            }

            return messages;
        }