/// <summary> /// Takes posession of the <see cref="Pop3Stream"/> and reads the greeting. /// </summary> /// <remarks> /// Takes posession of the <see cref="Pop3Stream"/> and reads the greeting. /// </remarks> /// <param name="pop3">The pop3 stream.</param> /// <param name="cancellationToken">The cancellation token</param> public void Connect(Pop3Stream pop3, CancellationToken cancellationToken) { if (stream != null) { stream.Dispose(); } Capabilities = Pop3Capabilities.User; AuthenticationMechanisms.Clear(); State = Pop3EngineState.Disconnected; ApopToken = null; stream = pop3; // read the pop3 server greeting var greeting = ReadLine(cancellationToken).TrimEnd(); int index = greeting.IndexOf(' '); string token, text; if (index != -1) { token = greeting.Substring(0, index); while (index < greeting.Length && char.IsWhiteSpace(greeting[index])) { index++; } if (index < greeting.Length) { text = greeting.Substring(index); } else { text = string.Empty; } } else { text = string.Empty; token = greeting; } if (token != "+OK") { stream.Dispose(); stream = null; throw new Pop3ProtocolException(string.Format("Unexpected greeting from server: {0}", greeting)); } index = text.IndexOf('>'); if (text.Length > 0 && text[0] == '<' && index != -1) { ApopToken = text.Substring(0, index + 1); Capabilities |= Pop3Capabilities.Apop; } State = Pop3EngineState.Connected; }
void AddAuthenticationMechanisms(string text, int startIndex) { int index = startIndex; while (ReadNextToken(text, ref index, out var tokenIndex, out var length)) { var mechanism = text.Substring(tokenIndex, length); AuthenticationMechanisms.Add(mechanism); } }
private async Task ConnectToServer(IEmailConfiguration emailConfiguration, IMailService emailClient) { await emailClient.ConnectAsync(emailConfiguration.ServerAddress, emailConfiguration.Port, emailConfiguration.RequireSSL); // if the user has added extra authentication mechnanisms add them to the email client if (AuthenticationMechanisms != null && AuthenticationMechanisms.Any()) { foreach (var authMechanism in AuthenticationMechanisms) { emailClient.AuthenticationMechanisms.Add(authMechanism); } } emailClient.AuthenticationMechanisms.Remove("XOAUTH2"); await emailClient.AuthenticateAsync(emailConfiguration.Username, emailConfiguration.Password); }
async Task <Pop3CommandStatus> QueryCapabilitiesAsync(bool doAsync, CancellationToken cancellationToken) { if (stream == null) { throw new InvalidOperationException(); } // clear all CAPA response capabilities (except the APOP and USER capabilities) Capabilities &= Pop3Capabilities.Apop | Pop3Capabilities.User; AuthenticationMechanisms.Clear(); Implementation = null; ExpirePolicy = 0; LoginDelay = 0; var pc = QueueCommand(cancellationToken, CapaHandler, "CAPA"); while (await IterateAsync(doAsync).ConfigureAwait(false) < pc.Id) { // continue processing commands... } return(pc.Status); }
public Pop3CommandStatus QueryCapabilities(CancellationToken cancellationToken) { if (stream == null) { throw new InvalidOperationException(); } // clear all CAPA response capabilities (except the APOP capability) Capabilities &= Pop3Capabilities.Apop; AuthenticationMechanisms.Clear(); Implementation = null; ExpirePolicy = 0; LoginDelay = 0; var pc = QueueCommand(cancellationToken, CapaHandler, "CAPA"); while (Iterate() < pc.Id) { // continue processing commands... } return(pc.Status); }
async Task ConnectAsync(Pop3Stream pop3, bool doAsync, CancellationToken cancellationToken) { if (stream != null) { stream.Dispose(); } Capabilities = Pop3Capabilities.User; AuthenticationMechanisms.Clear(); State = Pop3EngineState.Disconnected; ApopToken = null; stream = pop3; // read the pop3 server greeting var greeting = (await ReadLineAsync(doAsync, cancellationToken).ConfigureAwait(false)).TrimEnd(); int index = greeting.IndexOf(' '); string token, text; if (index != -1) { token = greeting.Substring(0, index); while (index < greeting.Length && char.IsWhiteSpace(greeting[index])) { index++; } if (index < greeting.Length) { text = greeting.Substring(index); } else { text = string.Empty; } } else { text = string.Empty; token = greeting; } if (token != "+OK") { stream.Dispose(); stream = null; throw new Pop3ProtocolException(string.Format("Unexpected greeting from server: {0}", greeting)); } index = text.IndexOf('<'); if (index != -1 && index + 1 < text.Length) { int endIndex = text.IndexOf('>', index + 1); if (endIndex++ != -1) { ApopToken = text.Substring(index, endIndex - index); Capabilities |= Pop3Capabilities.Apop; } } State = Pop3EngineState.Connected; }
/// <summary> /// Authenticates using the supplied credentials. /// </summary> /// <remarks> /// <para>If the SMTP server supports authentication, then the SASL mechanisms /// that both the client and server support are tried in order of greatest /// security to weakest security. Once a SASL authentication mechanism is /// found that both client and server support, the credentials are used to /// authenticate.</para> /// <para>If, on the other hand, authentication is not supported, then /// this method simply returns without attempting to authenticate.</para> /// </remarks> /// <param name="credentials">The user's credentials.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="credentials"/> is <c>null</c>. /// </exception> /// <exception cref="System.InvalidOperationException"> /// The <see cref="SmtpClient"/> is not connected or is already authenticated. /// </exception> /// <exception cref="System.NotSupportedException"> /// The SMTP server does not support authentication. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.Security.Authentication.AuthenticationException"> /// Authentication using the supplied credentials has failed. /// </exception> /// <exception cref="MailKit.Security.SaslException"> /// A SASL authentication error occurred. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="SmtpCommandException"> /// The SMTP command failed. /// </exception> /// <exception cref="SmtpProtocolException"> /// An SMTP protocol error occurred. /// </exception> public void Authenticate(ICredentials credentials, CancellationToken cancellationToken) { if (!IsConnected) { throw new InvalidOperationException("The SmtpClient must be connected before you can authenticate."); } if (authenticated) { throw new InvalidOperationException("The SmtpClient is already authenticated."); } if ((Capabilities & SmtpCapabilities.Authentication) == 0) { throw new NotSupportedException("The SMTP server does not support authentication."); } if (credentials == null) { throw new ArgumentNullException("credentials"); } var uri = new Uri("smtp://" + host); SmtpResponse response; string challenge; string command; foreach (var authmech in SaslMechanism.AuthMechanismRank) { if (!AuthenticationMechanisms.Contains(authmech)) { continue; } var sasl = SaslMechanism.Create(authmech, uri, credentials); cancellationToken.ThrowIfCancellationRequested(); // send an initial challenge if the mechanism supports it if ((challenge = sasl.Challenge(null)) != null) { command = string.Format("AUTH {0} {1}", authmech, challenge); } else { command = string.Format("AUTH {0}", authmech); } response = SendCommand(command, cancellationToken); if (response.StatusCode == SmtpStatusCode.AuthenticationMechanismTooWeak) { continue; } while (!sasl.IsAuthenticated) { if (response.StatusCode != SmtpStatusCode.AuthenticationChallenge) { throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } challenge = sasl.Challenge(response.Response); response = SendCommand(challenge, cancellationToken); } if (response.StatusCode == SmtpStatusCode.AuthenticationSuccessful) { Ehlo(cancellationToken); authenticated = true; return; } throw new AuthenticationException(); } throw new NotSupportedException("No compatible authentication mechanisms found."); }