/// <summary> /// Authenticate the user with USER/PASS /// </summary> /// <param name="username">user name</param> /// <param name="password">password</param> private void SendUserPass(string username, string password) { PopCommandResponse response = SendCommand("USER " + username); if (!response.Success) { throw new PopAuthenticationException("USER/PASS Authentication: " + response.RawValue, response.ToException()); } response = SendCommand("PASS " + password); if (!response.Success) { if (Regex.IsMatch(response.RawValue, "lock", RegexOptions.IgnoreCase)) { throw new MailboxLockedException("Mailbox locked by another client. Try again later.", response.ToException()); } else { throw new PopAuthenticationException("USER/PASS Authentication: " + response.RawValue, response.ToException()); } } }
/// <summary> /// Authenticate the user with APOP /// </summary> /// <param name="username">user name</param> /// <param name="password">password</param> private void SendApop(string username, string password) { PopCommandResponse response = SendCommand("APOP " + username + " " + ComputeHashAsHexString(password)); if (!response.Success) { if (Regex.IsMatch(response.RawValue, "lock", RegexOptions.IgnoreCase)) { throw new MailboxLockedException("Mailbox locked by another client. Try again later.", response.ToException()); } else { throw new PopAuthenticationException("APOP Authentication: " + response.RawValue, response.ToException()); } } }
/// <summary> /// Connect to the server. Requires that the Port and Host properties be set. /// </summary> public void Connect() { if (Connected) { throw new InvalidOperationException("PopClient is already connected."); } if (Host == null || Host == default(string)) { throw new InvalidOperationException("The Host property must be set."); } string host = Host; int port = Port; SslProtocols sslProtocol = SslProtocol; ClientSocket.Connect(host, port); Stream stream = ClientSocket.GetStream(); if (SslProtocols.None != sslProtocol) { if (SslNegotiationMode.Connect == SslNegotiationMode) { //Implements POP3S capability for SSL/TLS connections on an alternate port. //For POPS/Connect, we negotiate an SslStream immediately. stream = NegotiateSslStream(host, sslProtocol, stream); } else { //UNDONE: test STARTTLS. (Need an account on a compatible server.) //For STLS, we have to start out with plain text and then issue the STLS command and if the server says +OK //we can negotiate TLS. Have to do this without using a StreamReader or StreamWriter because we need to change //the stream from a NetworkStream to an SslStream. The stream inside of a StreamReader and StreamWriter can't //be changed and closing the StreamReader or StreamWriter will close the stream upon which the SslStream is based. string response; try { //don't close or dispose these StreamReader and StreamWriter objects of the stream will be closed. StreamWriter writer = new StreamWriter(stream); StreamReader reader = new StreamReader(stream); writer.WriteLine("STLS"); response = reader.ReadLine(); } catch (Exception ex) { if (null != stream) { try{ stream.Dispose(); } catch (ObjectDisposedException) {} } this.Disconnect(); throw new StartTlsNegotiationException("STARTTLS negotiation failed. Consider using SslNegotiationMode.Connect.", ex); } if (PopCommandResponse.IsResponseSuccess(response)) { stream = NegotiateSslStream(host, sslProtocol, stream); } else { if (null != stream) { try{ stream.Dispose(); } catch (ObjectDisposedException) {} } this.Disconnect(); throw new StartTlsNegotiationException(response); } } } StreamReader = new StreamReader(stream, Encoding.Default, true); StreamWriter = new StreamWriter(stream); StreamWriter.AutoFlush = true; PopCommandResponse popresponse = PopCommandResponse.FromRawResponseString(StreamReader.ReadLine()); if (popresponse.Success) { Match match = Regex.Match(popresponse.RawValue, @"^\+OK\s.+(<.+>$)"); if (match.Success) { ApopTimestamp = match.Groups[1].Value; } } else { this.Disconnect(); popresponse.ToException(); } }