static void ProcessMailFromResponse(SmtpResponse response, MailboxAddress mailbox) { switch (response.StatusCode) { case SmtpStatusCode.Ok: break; case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: throw new SmtpCommandException(SmtpErrorCode.SenderNotAccepted, response.StatusCode, mailbox, response.Response); case SmtpStatusCode.AuthenticationRequired: throw new UnauthorizedAccessException(response.Response); default: throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
static void ProcessRcptToResponse(SmtpResponse response, MailboxAddress mailbox) { switch (response.StatusCode) { case SmtpStatusCode.UserNotLocalWillForward: case SmtpStatusCode.Ok: break; case SmtpStatusCode.UserNotLocalTryAlternatePath: case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: case SmtpStatusCode.MailboxBusy: throw new SmtpCommandException(SmtpErrorCode.RecipientNotAccepted, response.StatusCode, mailbox, response.Response); case SmtpStatusCode.AuthenticationRequired: throw new UnauthorizedAccessException(response.Response); default: throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
static void ProcessRcptToResponse(SmtpResponse response, MailboxAddress mailbox) { switch (response.StatusCode) { case SmtpStatusCode.UserNotLocalWillForward: case SmtpStatusCode.Ok: break; case SmtpStatusCode.UserNotLocalTryAlternatePath: case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: case SmtpStatusCode.MailboxBusy: throw new SmtpCommandException (SmtpErrorCode.RecipientNotAccepted, response.StatusCode, mailbox, response.Response); case SmtpStatusCode.AuthenticationRequired: throw new UnauthorizedAccessException (response.Response); default: throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
static void ProcessMailFromResponse(SmtpResponse response, MailboxAddress mailbox) { switch (response.StatusCode) { case SmtpStatusCode.Ok: break; case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: throw new SmtpCommandException (SmtpErrorCode.SenderNotAccepted, response.StatusCode, mailbox, response.Response); case SmtpStatusCode.AuthenticationRequired: throw new UnauthorizedAccessException (response.Response); default: throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
bool ProcessRcptToResponse (MimeMessage message, MailboxAddress mailbox, SmtpResponse response) { switch (response.StatusCode) { case SmtpStatusCode.UserNotLocalWillForward: case SmtpStatusCode.Ok: OnRecipientAccepted (message, mailbox, response); return true; case SmtpStatusCode.UserNotLocalTryAlternatePath: case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: case SmtpStatusCode.MailboxBusy: OnRecipientNotAccepted (message, mailbox, response); return false; case SmtpStatusCode.AuthenticationRequired: throw new ServiceNotAuthenticatedException (response.Response); default: throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
/// <summary> /// Invoked when a recipient is not accepted by the SMTP server. /// </summary> /// <remarks> /// The default implementation throws an appropriate <see cref="SmtpCommandException"/>. /// </remarks> /// <param name="message">The message being sent.</param> /// <param name="mailbox">The mailbox used in the <c>RCPT TO</c> command.</param> /// <param name="response">The response to the <c>RCPT TO</c> command.</param> protected virtual void OnRecipientNotAccepted (MimeMessage message, MailboxAddress mailbox, SmtpResponse response) { throw new SmtpCommandException (SmtpErrorCode.RecipientNotAccepted, response.StatusCode, mailbox, response.Response); }
/// <summary> /// Invoked when a recipient is accepted by the SMTP server. /// </summary> /// <remarks> /// The default implementation does nothing. /// </remarks> /// <param name="message">The message being sent.</param> /// <param name="mailbox">The mailbox used in the <c>RCPT TO</c> command.</param> /// <param name="response">The response to the <c>RCPT TO</c> command.</param> protected virtual void OnRecipientAccepted (MimeMessage message, MailboxAddress mailbox, SmtpResponse response) { }
void ProcessMailFromResponse (MimeMessage message, MailboxAddress mailbox, SmtpResponse response) { switch (response.StatusCode) { case SmtpStatusCode.Ok: OnSenderAccepted (message, mailbox, response); break; case SmtpStatusCode.MailboxNameNotAllowed: case SmtpStatusCode.MailboxUnavailable: OnSenderNotAccepted (message, mailbox, response); break; case SmtpStatusCode.AuthenticationRequired: throw new ServiceNotAuthenticatedException (response.Response); default: throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } }
/// <summary> /// Invoked when the sender is accepted by the SMTP server. /// </summary> /// <remarks> /// The default implementation does nothing. /// </remarks> /// <param name="message">The message being sent.</param> /// <param name="mailbox">The mailbox used in the <c>MAIL FROM</c> command.</param> /// <param name="response">The response to the <c>MAIL FROM</c> command.</param> protected virtual void OnSenderAccepted (MimeMessage message, MailboxAddress mailbox, SmtpResponse response) { }
/// <summary> /// Establishes a connection to the specified SMTP server. /// </summary> /// <remarks> /// <para>Establishes a connection to an SMTP or SMTP/S server. If the schema /// in the uri is "smtp", a clear-text connection is made and defaults to using /// port 25 if no port is specified in the URI. However, if the schema in the /// uri is "smtps", an SSL connection is made using the /// <see cref="ClientCertificates"/> and defaults to port 465 unless a port /// is specified in the URI.</para> /// <para>It should be noted that when using a clear-text SMTP connection, /// if the server advertizes support for the STARTTLS extension, the client /// will automatically switch into TLS mode before authenticating unless the /// <paramref name="uri"/> contains a query string to disable it.</para> /// If a successful connection is made, the <see cref="AuthenticationMechanisms"/> /// and <see cref="Capabilities"/> properties will be populated. /// </remarks> /// <param name="uri">The server URI. The <see cref="System.Uri.Scheme"/> should either /// be "smtp" to make a clear-text connection or "smtps" to make an SSL connection.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para>The <paramref name="uri"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.ArgumentException"> /// The <paramref name="uri"/> is not an absolute URI. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="SmtpClient"/> has been disposed. /// </exception> /// <exception cref="System.InvalidOperationException"> /// The <see cref="SmtpClient"/> is already connected. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="SmtpCommandException"> /// An SMTP command failed. /// </exception> /// <exception cref="SmtpProtocolException"> /// An SMTP protocol error occurred. /// </exception> public void Connect(Uri uri, CancellationToken cancellationToken) { CheckDisposed(); if (uri == null) { throw new ArgumentNullException("uri"); } if (!uri.IsAbsoluteUri) { throw new ArgumentException("The uri must be absolute.", "uri"); } if (IsConnected) { throw new InvalidOperationException("The SmtpClient is already connected."); } Capabilities = SmtpCapabilities.None; authmechs.Clear(); MaxSize = 0; bool smtps = uri.Scheme.ToLowerInvariant() == "smtps"; int port = uri.Port > 0 ? uri.Port : (smtps ? 465 : 25); var ipAddresses = Dns.GetHostAddresses(uri.DnsSafeHost); var query = uri.ParsedQuery(); SmtpResponse response = null; Socket socket = null; string value; var starttls = !smtps && (!query.TryGetValue("starttls", out value) || Convert.ToBoolean(value)); for (int i = 0; i < ipAddresses.Length; i++) { socket = new Socket(ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp); cancellationToken.ThrowIfCancellationRequested(); try { socket.Connect(ipAddresses[i], port); localEndPoint = socket.LocalEndPoint; break; } catch { if (i + 1 == ipAddresses.Length) { throw; } } } if (smtps) { var ssl = new SslStream(new NetworkStream(socket, true), false, ValidateRemoteCertificate); ssl.AuthenticateAsClient(uri.Host, ClientCertificates, SslProtocols.Default, true); stream = ssl; } else { stream = new NetworkStream(socket, true); } host = uri.Host; logger.LogConnect(uri); try { // read the greeting response = ReadResponse(cancellationToken); if (response.StatusCode != SmtpStatusCode.ServiceReady) { throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } // Send EHLO and get a list of supported extensions Ehlo(cancellationToken); if (starttls && (Capabilities & SmtpCapabilities.StartTLS) != 0) { response = SendCommand("STARTTLS", cancellationToken); if (response.StatusCode != SmtpStatusCode.ServiceReady) { throw new SmtpCommandException(SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); } var tls = new SslStream(stream, false, ValidateRemoteCertificate); tls.AuthenticateAsClient(uri.Host, ClientCertificates, SslProtocols.Tls, true); stream = tls; // Send EHLO again and get the new list of supported extensions Ehlo(cancellationToken); } IsConnected = true; } catch { stream.Dispose(); stream = null; throw; } }