Skip to content

Commit

Permalink
Added some System.Diagnostics.Metrics telemetry for SmtpClient
Browse files Browse the repository at this point in the history
Partial fix for issue #1499
  • Loading branch information
jstedfast committed Feb 14, 2024
1 parent 09969e9 commit 467e60b
Show file tree
Hide file tree
Showing 9 changed files with 957 additions and 32 deletions.
5 changes: 4 additions & 1 deletion MailKit/MailKit.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>An Open Source cross-platform .NET mail-client library that is based on MimeKit and optimized for mobile devices.</Description>
Expand Down Expand Up @@ -115,6 +115,7 @@
<Compile Include="Net\Smtp\SmtpAuthenticationSecretDetector.cs" />
<Compile Include="Net\Smtp\SmtpCapabilities.cs" />
<Compile Include="Net\Smtp\SmtpClient.cs" />
<Compile Include="Net\Smtp\SmtpClientMetrics.cs" />
<Compile Include="Net\Smtp\SmtpCommandException.cs" />
<Compile Include="Net\Smtp\SmtpDataFilter.cs" />
<Compile Include="Net\Smtp\SmtpProtocolException.cs" />
Expand All @@ -123,6 +124,7 @@
<Compile Include="Net\Smtp\SmtpStream.cs" />
<Compile Include="Net\IChannelBindingContext.cs" />
<Compile Include="Net\NetworkStream.cs" />
<Compile Include="Net\SocketMetrics.cs" />
<Compile Include="Net\SocketUtils.cs" />
<Compile Include="Net\SslStream.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down Expand Up @@ -272,6 +274,7 @@
<Compile Include="StoreAction.cs" />
<Compile Include="StoreFlagsRequest.cs" />
<Compile Include="StoreLabelsRequest.cs" />
<Compile Include="Telemetry.cs" />
<Compile Include="TextEncodings.cs" />
<Compile Include="ThreadingAlgorithm.cs" />
<Compile Include="UniqueId.cs" />
Expand Down
3 changes: 3 additions & 0 deletions MailKit/MailKitLite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
<Compile Include="Net\Smtp\SmtpAuthenticationSecretDetector.cs" />
<Compile Include="Net\Smtp\SmtpCapabilities.cs" />
<Compile Include="Net\Smtp\SmtpClient.cs" />
<Compile Include="Net\Smtp\SmtpClientMetrics.cs" />
<Compile Include="Net\Smtp\SmtpCommandException.cs" />
<Compile Include="Net\Smtp\SmtpDataFilter.cs" />
<Compile Include="Net\Smtp\SmtpProtocolException.cs" />
Expand All @@ -128,6 +129,7 @@
<Compile Include="Net\Smtp\SmtpStream.cs" />
<Compile Include="Net\IChannelBindingContext.cs" />
<Compile Include="Net\NetworkStream.cs" />
<Compile Include="Net\SocketMetrics.cs" />
<Compile Include="Net\SocketUtils.cs" />
<Compile Include="Net\SslStream.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down Expand Up @@ -275,6 +277,7 @@
<Compile Include="StoreAction.cs" />
<Compile Include="StoreFlagsRequest.cs" />
<Compile Include="StoreLabelsRequest.cs" />
<Compile Include="Telemetry.cs" />
<Compile Include="TextEncodings.cs" />
<Compile Include="ThreadingAlgorithm.cs" />
<Compile Include="UniqueId.cs" />
Expand Down
58 changes: 47 additions & 11 deletions MailKit/Net/Smtp/AsyncSmtpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Diagnostics;
using System.Globalization;
using System.Threading.Tasks;
using System.Collections.Generic;
Expand Down Expand Up @@ -458,7 +459,8 @@ async Task PostConnectAsync (Stream stream, string host, int port, SecureSocketO
}

connected = true;
} catch {
} catch (Exception ex) {
ReportClientDisconnected (ex);
Stream.Dispose ();
secure = false;
Stream = null;
Expand Down Expand Up @@ -550,7 +552,16 @@ public override async Task ConnectAsync (string host, int port = 0, SecureSocket

ComputeDefaultValues (host, ref port, ref options, out uri, out var starttls);

var stream = await ConnectNetworkAsync (host, port, cancellationToken).ConfigureAwait (false);
long connectStartedTimestamp = Stopwatch.GetTimestamp ();
Stream stream;

try {
stream = await ConnectNetworkAsync (host, port, cancellationToken).ConfigureAwait (false);
} catch (Exception ex) {
ReportClientConnectFailed (connectStartedTimestamp, ex);
throw;
}

stream.WriteTimeout = timeout;
stream.ReadTimeout = timeout;

Expand All @@ -562,6 +573,8 @@ public override async Task ConnectAsync (string host, int port = 0, SecureSocket
} catch (Exception ex) {
ssl.Dispose ();

ReportClientConnectFailed (connectStartedTimestamp, ex);

throw SslHandshakeException.Create (ref sslValidationInfo, ex, false, "SMTP", host, port, 465, 25, 587);
}

Expand All @@ -571,6 +584,8 @@ public override async Task ConnectAsync (string host, int port = 0, SecureSocket
secure = false;
}

ReportClientConnected (connectStartedTimestamp, stream);

await PostConnectAsync (stream, host, port, options, starttls, cancellationToken).ConfigureAwait (false);
}

Expand Down Expand Up @@ -717,6 +732,7 @@ public override async Task ConnectAsync (Stream stream, string host, int port =

ComputeDefaultValues (host, ref port, ref options, out uri, out var starttls);

long connectStartedTimestamp = Stopwatch.GetTimestamp ();
Stream network;

if (options == SecureSocketOptions.SslOnConnect) {
Expand All @@ -727,6 +743,8 @@ public override async Task ConnectAsync (Stream stream, string host, int port =
} catch (Exception ex) {
ssl.Dispose ();

ReportClientConnectFailed (connectStartedTimestamp, ex);

throw SslHandshakeException.Create (ref sslValidationInfo, ex, false, "SMTP", host, port, 465, 25, 587);
}

Expand All @@ -742,6 +760,8 @@ public override async Task ConnectAsync (Stream stream, string host, int port =
network.ReadTimeout = timeout;
}

ReportClientConnected (connectStartedTimestamp, network);

await PostConnectAsync (network, host, port, options, starttls, cancellationToken).ConfigureAwait (false);
}

Expand Down Expand Up @@ -945,6 +965,8 @@ async Task<string> SendAsync (FormatOptions options, MimeMessage message, Mailbo
size = -1;
}

long sendStartedTimestamp = Stopwatch.GetTimestamp ();

try {
// Note: if PIPELINING is supported, MailFrom() and RcptTo() will
// queue their commands instead of sending them immediately.
Expand Down Expand Up @@ -973,23 +995,37 @@ async Task<string> SendAsync (FormatOptions options, MimeMessage message, Mailbo
throw new SmtpCommandException (SmtpErrorCode.MessageNotAccepted, SmtpStatusCode.TransactionFailed, "No recipients were accepted.");
}

if (bdat)
return await BdatAsync (format, message, size, cancellationToken, progress).ConfigureAwait (false);
string result;

if (bdat) {
result = await BdatAsync (format, message, size, cancellationToken, progress).ConfigureAwait (false);
} else {
var dataResponse = await Stream.SendCommandAsync ("DATA\r\n", cancellationToken).ConfigureAwait (false);

ParseDataResponse (dataResponse);
dataResponse = null;

result = await MessageDataAsync (format, message, size, cancellationToken, progress).ConfigureAwait (false);
}

var dataResponse = await Stream.SendCommandAsync ("DATA\r\n", cancellationToken).ConfigureAwait (false);
ReportSendCompleted (sendStartedTimestamp);

ParseDataResponse (dataResponse);
dataResponse = null;
return result;
} catch (ServiceNotAuthenticatedException ex) {
ReportSendFailed (sendStartedTimestamp, ex);

return await MessageDataAsync (format, message, size, cancellationToken, progress).ConfigureAwait (false);
} catch (ServiceNotAuthenticatedException) {
// do not disconnect
await ResetAsync (cancellationToken).ConfigureAwait (false);
throw;
} catch (SmtpCommandException) {
} catch (SmtpCommandException ex) {
ReportSendFailed (sendStartedTimestamp, ex);

// do not disconnect
await ResetAsync (cancellationToken).ConfigureAwait (false);
throw;
} catch {
} catch (Exception ex) {
ReportSendFailed (sendStartedTimestamp, ex);

Disconnect (uri.Host, uri.Port, GetSecureSocketOptions (uri), false);
throw;
}
Expand Down
Loading

0 comments on commit 467e60b

Please sign in to comment.