Skip to content

Fix SmtpClientTest.SendAsync_CanBeCanceled_SendAsyncCancel test failure #116042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 30, 2025
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,8 @@ Exception ProcessException(Exception e, ref bool canceled, bool forceWrapExcepti
// for compatibility reasons, don't wrap these exceptions during sync executions
(typeof(TIOAdapter) == typeof(SyncReadWriteAdapter) &&
(e is SecurityException || e is AuthenticationException)) ||
e is SmtpException)
e is SmtpException ||
e is OperationCanceledException)
{
return e;
}
Expand All @@ -574,7 +575,9 @@ Exception ProcessException(Exception e, ref bool canceled, bool forceWrapExcepti
// SendCompleted event should ever be invoked only for asynchronous send completions.
if (invokeSendCompleted && !synchronous)
{
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(exception, canceled, userToken);
// If the operation was canceled, Error should be null
Exception? errorToReport = canceled ? null : exception;
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(errorToReport, canceled, userToken);
OnSendCompleted(eventArgs);
}
}
Expand Down
17 changes: 8 additions & 9 deletions src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,20 +314,19 @@ public async Task SendMailAsync_CanBeCanceled_CancellationToken()
server.ReceiveMultipleConnections = true;

// The server will introduce some fake latency so that the operation can be canceled before the request completes
ManualResetEvent serverMre = new ManualResetEvent(false);
server.OnConnected += _ => serverMre.WaitOne();

CancellationTokenSource cts = new CancellationTokenSource();

server.OnConnected += _ =>
{
// Cancel the operation during actual server communication
cts.Cancel();
};

var message = new MailMessage("[email protected]", "[email protected]", "Foo", "Bar");

Task sendTask = Task.Run(() => client.SendMailAsync(message, cts.Token));

cts.Cancel();
await Task.Delay(500);
serverMre.Set();

await Assert.ThrowsAsync<TaskCanceledException>(async () => await sendTask).WaitAsync(TestHelper.PassingTestTimeout);
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await sendTask).WaitAsync(TestHelper.PassingTestTimeout);

// We should still be able to send mail on the SmtpClient instance
await Task.Run(() => client.SendMailAsync(message)).WaitAsync(TestHelper.PassingTestTimeout);
Expand Down Expand Up @@ -370,7 +369,7 @@ public async Task SendAsync_CanBeCanceled_SendAsyncCancel()
AsyncCompletedEventArgs e = await tcs.Task.WaitAsync(TestHelper.PassingTestTimeout);
Assert.True(e.Cancelled, "SendAsync should have been canceled");
_output.WriteLine(e.Error?.ToString() ?? "No error");
Assert.IsType<OperationCanceledException>(e.Error.InnerException);
Assert.Null(e.Error);

// We should still be able to send mail on the SmtpClient instance
await client.SendMailAsync(message).WaitAsync(TestHelper.PassingTestTimeout);
Expand Down
Loading