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); }
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); } }
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; } }
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; } }
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; } }
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); }
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); }
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; } }
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); }
/// <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]); } }
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); }
void SendCommand(Pop3Command pc) { var buf = Encoding.UTF8.GetBytes(pc.Command + "\r\n"); stream.Write(buf, 0, buf.Length); }
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; } }
void SendCommand (Pop3Command pc) { var buf = Encoding.UTF8.GetBytes (pc.Command + "\r\n"); stream.Write (buf, 0, buf.Length); }
/// <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]); } }
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; }
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); }
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; }