diff --git a/MailKit/Net/Smtp/AsyncSmtpClient.cs b/MailKit/Net/Smtp/AsyncSmtpClient.cs index f179b1c952..cd28ee0ef7 100644 --- a/MailKit/Net/Smtp/AsyncSmtpClient.cs +++ b/MailKit/Net/Smtp/AsyncSmtpClient.cs @@ -81,6 +81,16 @@ async Task FlushCommandQueueAsync (MimeMessage message, MailboxAdd return ParseCommandQueueResponses (message, sender, recipients, responses, rex); } + async Task SendCommandInternalAsync (string command, CancellationToken cancellationToken) + { + try { + return await Stream.SendCommandAsync (command, cancellationToken).ConfigureAwait (false); + } catch { + Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); + throw; + } + } + /// /// Asynchronously send a custom command to the SMTP server. /// @@ -109,7 +119,7 @@ async Task FlushCommandQueueAsync (MimeMessage message, MailboxAdd /// /// An SMTP protocol exception occurred. /// - protected async Task SendCommandAsync (string command, CancellationToken cancellationToken = default) + protected Task SendCommandAsync (string command, CancellationToken cancellationToken = default) { if (command == null) throw new ArgumentNullException (nameof (command)); @@ -122,25 +132,17 @@ protected async Task SendCommandAsync (string command, Cancellatio if (!command.EndsWith ("\r\n", StringComparison.Ordinal)) command += "\r\n"; - try { - return await Stream.SendCommandAsync (command, cancellationToken).ConfigureAwait (false); - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + return SendCommandInternalAsync (command, cancellationToken); } - async Task SendEhloAsync (bool connecting, string helo, CancellationToken cancellationToken) + Task SendEhloAsync (bool connecting, string helo, CancellationToken cancellationToken) { var command = CreateEhloCommand (helo); - try { - return await Stream.SendCommandAsync (command, cancellationToken).ConfigureAwait (false); - } catch { - if (!connecting) - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + if (connecting) + return Stream.SendCommandAsync (command, cancellationToken); + + return SendCommandInternalAsync (command, cancellationToken); } async Task EhloAsync (bool connecting, CancellationToken cancellationToken) @@ -225,7 +227,7 @@ public override async Task AuthenticateAsync (SaslMechanism mechanism, Cancellat detector.IsAuthenticating = true; try { - response = await Stream.SendCommandAsync (command, cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync (command, cancellationToken).ConfigureAwait (false); if (response.StatusCode == SmtpStatusCode.AuthenticationMechanismTooWeak) throw new AuthenticationException (response.Response); @@ -233,18 +235,15 @@ public override async Task AuthenticateAsync (SaslMechanism mechanism, Cancellat try { while (response.StatusCode == SmtpStatusCode.AuthenticationChallenge) { challenge = await mechanism.ChallengeAsync (response.Response, cancellationToken).ConfigureAwait (false); - response = await Stream.SendCommandAsync (challenge + "\r\n", cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync (challenge + "\r\n", cancellationToken).ConfigureAwait (false); } saslException = null; } catch (SaslException ex) { // reset the authentication state - response = await Stream.SendCommandAsync ("\r\n", cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync ("\r\n", cancellationToken).ConfigureAwait (false); saslException = ex; } - } catch (Exception ex) when (ex is not AuthenticationException) { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; } finally { detector.IsAuthenticating = false; } @@ -358,7 +357,7 @@ public override async Task AuthenticateAsync (Encoding encoding, ICredentials cr saslException = null; try { - response = await Stream.SendCommandAsync (command, cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync (command, cancellationToken).ConfigureAwait (false); if (response.StatusCode == SmtpStatusCode.AuthenticationMechanismTooWeak) continue; @@ -369,18 +368,15 @@ public override async Task AuthenticateAsync (Encoding encoding, ICredentials cr break; challenge = await sasl.ChallengeAsync (response.Response, cancellationToken).ConfigureAwait (false); - response = await Stream.SendCommandAsync (challenge + "\r\n", cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync (challenge + "\r\n", cancellationToken).ConfigureAwait (false); } saslException = null; } catch (SaslException ex) { // reset the authentication state - response = await Stream.SendCommandAsync ("\r\n", cancellationToken).ConfigureAwait (false); + response = await SendCommandInternalAsync ("\r\n", cancellationToken).ConfigureAwait (false); saslException = ex; } - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; } finally { detector.IsAuthenticating = false; } @@ -818,14 +814,7 @@ public override async Task NoOpAsync (CancellationToken cancellationToken = defa if (!IsConnected) throw new ServiceNotConnectedException ("The SmtpClient is not connected."); - SmtpResponse response; - - try { - response = await Stream.SendCommandAsync ("NOOP\r\n", cancellationToken).ConfigureAwait (false); - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + var response = await SendCommandInternalAsync ("NOOP\r\n", cancellationToken).ConfigureAwait (false); if (response.StatusCode != SmtpStatusCode.Ok) throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); @@ -940,15 +929,10 @@ async Task MessageDataAsync (FormatOptions options, MimeMessage message, async Task ResetAsync (CancellationToken cancellationToken) { - try { - var response = await Stream.SendCommandAsync ("RSET\r\n", cancellationToken).ConfigureAwait (false); - if (response.StatusCode != SmtpStatusCode.Ok) - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - } catch (SmtpCommandException) { - // do not disconnect - } catch { + var response = await SendCommandInternalAsync ("RSET\r\n", cancellationToken).ConfigureAwait (false); + + if (response.StatusCode != SmtpStatusCode.Ok) Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - } } async Task SendAsync (FormatOptions options, MimeMessage message, MailboxAddress sender, IList recipients, CancellationToken cancellationToken, ITransferProgress progress) @@ -956,7 +940,6 @@ async Task SendAsync (FormatOptions options, MimeMessage message, Mailbo var format = Prepare (options, message, sender, recipients, out var extensions); var pipeline = (capabilities & SmtpCapabilities.Pipelining) != 0; var bdat = UseBdatCommand (extensions); - SmtpResponse dataResponse = null; long size; if (bdat || (Capabilities & SmtpCapabilities.Size) != 0 || progress != null) { @@ -996,7 +979,7 @@ async Task SendAsync (FormatOptions options, MimeMessage message, Mailbo if (bdat) return await BdatAsync (format, message, size, cancellationToken, progress).ConfigureAwait (false); - dataResponse = await Stream.SendCommandAsync ("DATA\r\n", cancellationToken).ConfigureAwait (false); + var dataResponse = await Stream.SendCommandAsync ("DATA\r\n", cancellationToken).ConfigureAwait (false); ParseDataResponse (dataResponse); dataResponse = null; @@ -1175,7 +1158,7 @@ public override Task SendAsync (FormatOptions options, MimeMessage messa /// public async Task ExpandAsync (string alias, CancellationToken cancellationToken = default) { - var response = await Stream.SendCommandAsync (CreateExpandCommand (alias), cancellationToken).ConfigureAwait (false); + var response = await SendCommandInternalAsync (CreateExpandCommand (alias), cancellationToken).ConfigureAwait (false); return ParseExpandResponse (response); } @@ -1222,7 +1205,7 @@ public async Task ExpandAsync (string alias, CancellationTo /// public async Task VerifyAsync (string address, CancellationToken cancellationToken = default) { - var response = await Stream.SendCommandAsync (CreateVerifyCommand (address), cancellationToken).ConfigureAwait (false); + var response = await SendCommandInternalAsync (CreateVerifyCommand (address), cancellationToken).ConfigureAwait (false); return ParseVerifyResponse (response); } diff --git a/MailKit/Net/Smtp/SmtpClient.cs b/MailKit/Net/Smtp/SmtpClient.cs index 67be740b76..ca303fcab9 100644 --- a/MailKit/Net/Smtp/SmtpClient.cs +++ b/MailKit/Net/Smtp/SmtpClient.cs @@ -655,6 +655,16 @@ QueueResults FlushCommandQueue (MimeMessage message, MailboxAddress sender, ILis return ParseCommandQueueResponses (message, sender, recipients, responses, rex); } + SmtpResponse SendCommandInternal (string command, CancellationToken cancellationToken) + { + try { + return Stream.SendCommand (command, cancellationToken); + } catch { + Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); + throw; + } + } + /// /// Send a custom command to the SMTP server. /// @@ -696,12 +706,7 @@ protected SmtpResponse SendCommand (string command, CancellationToken cancellati if (!command.EndsWith ("\r\n", StringComparison.Ordinal)) command += "\r\n"; - try { - return Stream.SendCommand (command, cancellationToken); - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + return SendCommandInternal (command, cancellationToken); } static bool ReadNextLine (string text, ref int index, out int lineStartIndex, out int lineEndIndex) @@ -871,13 +876,10 @@ SmtpResponse SendEhlo (bool connecting, string helo, CancellationToken cancellat { var command = CreateEhloCommand (helo); - try { + if (connecting) return Stream.SendCommand (command, cancellationToken); - } catch { - if (!connecting) - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + + return SendCommandInternal (command, cancellationToken); } void Ehlo (bool connecting, CancellationToken cancellationToken) @@ -981,7 +983,7 @@ public override void Authenticate (SaslMechanism mechanism, CancellationToken ca detector.IsAuthenticating = true; try { - response = Stream.SendCommand (command, cancellationToken); + response = SendCommandInternal (command, cancellationToken); if (response.StatusCode == SmtpStatusCode.AuthenticationMechanismTooWeak) throw new AuthenticationException (response.Response); @@ -989,18 +991,15 @@ public override void Authenticate (SaslMechanism mechanism, CancellationToken ca try { while (response.StatusCode == SmtpStatusCode.AuthenticationChallenge) { challenge = mechanism.Challenge (response.Response, cancellationToken); - response = Stream.SendCommand (challenge + "\r\n", cancellationToken); + response = SendCommandInternal (challenge + "\r\n", cancellationToken); } saslException = null; } catch (SaslException ex) { // reset the authentication state - response = Stream.SendCommand ("\r\n", cancellationToken); + response = SendCommandInternal ("\r\n", cancellationToken); saslException = ex; } - } catch (Exception ex) when (ex is not AuthenticationException) { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; } finally { detector.IsAuthenticating = false; } @@ -1133,7 +1132,7 @@ public override void Authenticate (Encoding encoding, ICredentials credentials, saslException = null; try { - response = Stream.SendCommand (command, cancellationToken); + response = SendCommandInternal (command, cancellationToken); if (response.StatusCode == SmtpStatusCode.AuthenticationMechanismTooWeak) continue; @@ -1144,18 +1143,15 @@ public override void Authenticate (Encoding encoding, ICredentials credentials, break; challenge = sasl.Challenge (response.Response, cancellationToken); - response = Stream.SendCommand (challenge + "\r\n", cancellationToken); + response = SendCommandInternal (challenge + "\r\n", cancellationToken); } saslException = null; } catch (SaslException ex) { // reset the authentication state - response = Stream.SendCommand ("\r\n", cancellationToken); + response = SendCommandInternal ("\r\n", cancellationToken); saslException = ex; } - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; } finally { detector.IsAuthenticating = false; } @@ -1667,14 +1663,7 @@ public override void NoOp (CancellationToken cancellationToken = default) if (!IsConnected) throw new ServiceNotConnectedException ("The SmtpClient is not connected."); - SmtpResponse response; - - try { - response = Stream.SendCommand ("NOOP\r\n", cancellationToken); - } catch { - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - throw; - } + var response = SendCommandInternal ("NOOP\r\n", cancellationToken); if (response.StatusCode != SmtpStatusCode.Ok) throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response); @@ -2214,15 +2203,10 @@ string MessageData (FormatOptions options, MimeMessage message, long size, Cance void Reset (CancellationToken cancellationToken) { - try { - var response = Stream.SendCommand ("RSET\r\n", cancellationToken); - if (response.StatusCode != SmtpStatusCode.Ok) - Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - } catch (SmtpCommandException) { - // do not disconnect - } catch { + var response = SendCommandInternal ("RSET\r\n", cancellationToken); + + if (response.StatusCode != SmtpStatusCode.Ok) Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false); - } } /// @@ -2328,7 +2312,6 @@ string Send (FormatOptions options, MimeMessage message, MailboxAddress sender, var format = Prepare (options, message, sender, recipients, out var extensions); var pipeline = (capabilities & SmtpCapabilities.Pipelining) != 0; var bdat = UseBdatCommand (extensions); - SmtpResponse dataResponse = null; long size; if (bdat || (Capabilities & SmtpCapabilities.Size) != 0 || progress != null) { @@ -2368,7 +2351,7 @@ string Send (FormatOptions options, MimeMessage message, MailboxAddress sender, if (bdat) return Bdat (format, message, size, cancellationToken, progress); - dataResponse = Stream.SendCommand ("DATA\r\n", cancellationToken); + var dataResponse = Stream.SendCommand ("DATA\r\n", cancellationToken); ParseDataResponse (dataResponse); dataResponse = null; @@ -2627,7 +2610,7 @@ static InternetAddressList ParseExpandResponse (SmtpResponse response) /// public InternetAddressList Expand (string alias, CancellationToken cancellationToken = default) { - var response = Stream.SendCommand (CreateExpandCommand (alias), cancellationToken); + var response = SendCommandInternal (CreateExpandCommand (alias), cancellationToken); return ParseExpandResponse (response); } @@ -2701,7 +2684,7 @@ static MailboxAddress ParseVerifyResponse (SmtpResponse response) /// public MailboxAddress Verify (string address, CancellationToken cancellationToken = default) { - var response = Stream.SendCommand (CreateVerifyCommand (address), cancellationToken); + var response = SendCommandInternal (CreateVerifyCommand (address), cancellationToken); return ParseVerifyResponse (response); }