Skip to content
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

Proposal: SmtpClient.SendMailAsync overload with cancellation #23756

Closed
jnm2 opened this issue Oct 6, 2017 · 5 comments
Closed

Proposal: SmtpClient.SendMailAsync overload with cancellation #23756

jnm2 opened this issue Oct 6, 2017 · 5 comments
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Net
Milestone

Comments

@jnm2
Copy link
Contributor

jnm2 commented Oct 6, 2017

Problem

Right now there's a SendAsyncCancel method which is used to cancel the event-based pre-TPL SendAsync. SendMailAsync is implemented as a wrapper around SendAsync (code) but for some reason neglects to take and apply the customary cancellation token.

This means people who want cancellation currently need to add a using statement:

using (cancellationToken.Register(smtpClient.SendAsyncCancel))
{
    await smtpClient.SendMailAsync(message);
}

Extension method for convenience, in case you want to operate on the original Task without wrapping in an async state machine:

public static Task SendMailAsync(this SmtpClient client, MailMessage message, CancellationToken cancellationToken)
{
    if (client == null) throw new ArgumentNullException(nameof(client));
    if (message == null) throw new ArgumentNullException(nameof(message));

    var cancellationRegistration = cancellationToken.Register(client.SendAsyncCancel);
    var task = client.SendMailAsync(message);
    task.ConfigureAwait(false).GetAwaiter().OnCompleted(cancellationRegistration.Dispose);
    return task;
}

The difficulty is that there's no guarantee that SendMailAsync will continue to be implemented in terms of SendAsync under the covers and that SendAsyncCancel will have any effect. Rather than an extension method, it's more future-proof to bring the responsibility of this coupling much closer to where it belongs: as a detail inside the implementation of SmtpClient.

Proposal

I propose adding these two overloads, copies of the existing overloads but appending a CancellationToken parameter:

class System.Net.Mail.SmtpClient
{
    public Task SendMailAsync(string from, string recipients, string subject, string body)
+   public Task SendMailAsync(string from, string recipients, string subject, string body, CancellationToken cancellationToken)
    public Task SendMailAsync(MailMessage message)
+   public Task SendMailAsync(MailMessage message, CancellationToken cancellationToken)
}

Implementation would likely be straightforward, with the non-cancellable overloads delegating to the cancellable ones and the SendCompletedEventHandler disposing the cancellation registration.

@jnm2
Copy link
Contributor Author

jnm2 commented Oct 13, 2017

What does api-needs-work mean? Are you waiting for me to do something?

@hillmarcus
Copy link

This is an issue I ran in to today as well. Is there anyway we can get an update on this or re-prioritize it?

@karelz
Copy link
Member

karelz commented Nov 26, 2018

@hillmarcus we do not plan to invest into SmtpClient - see:
https://github.com/dotnet/designs/issues/9
https://github.com/dotnet/platform-compat/blob/master/docs/DE0005.md

If there is enough need to have the overloads and the implementation is straightforward, I think we would be ok with taking a contribution. API approval should be formality in such case.

@hillmarcus
Copy link

hillmarcus commented Nov 26, 2018 via email

@terrajobst
Copy link
Member

terrajobst commented Oct 22, 2019

Video

Looks good as proposed.

namespace System.Net.Mail
{
    public partial class SmtpClient
    {
        public Task SendMailAsync(MailMessage message, CancellationToken cancellationToken);
        public Task SendMailAsync(string from, string recipients, string subject, string body, CancellationToken cancellationToken);
    }
}

@MihaZupan MihaZupan self-assigned this Nov 25, 2019
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 5.0 milestone Jan 31, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Net
Projects
None yet
Development

No branches or pull requests

6 participants