C# how to add Await to this function - SendEmailAsync - MailKit in Dot Net Core

6.6k views Asked by At

I have code based on MailKit. Where do I add the await keyword?

public async Task SendEmailAsync(string email, string subject, string mess)
{
    var message = new MimeMessage();
    message.From.Add(new MailboxAddress("Joey Tribbiani", "[email protected]"));
    message.To.Add(new MailboxAddress("Mrs. Chanandler Bong", "[email protected]"));
    message.Subject = "How you doin'?";

    message.Body = new TextPart("plain")
    {
        Text = @"Hey Chandler"
    };

    using (var client = new SmtpClient())
    {
        // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
        client.ServerCertificateValidationCallback = (s, c, h, e) => true;

        client.Connect("smtp.friends.com", 587, false);

        // Note: since we don't have an OAuth2 token, disable
        // the XOAUTH2 authentication mechanism.
        client.AuthenticationMechanisms.Remove("XOAUTH2");

        // Note: only needed if the SMTP server requires authentication
        client.Authenticate("joey", "password");

        client.Send(message);
        client.Disconnect(true);
    }
}

This is a similar implementation (but I couldn't find credential to make this work) so I changed to the above

    public async Task SendEmailAsync(string email, string subject, string message)
    {
        using (var client = new HttpClient { BaseAddress = new Uri("smtp.gmail.com") })
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                Convert.ToBase64String(Encoding.ASCII.GetBytes("api:key-*")));


            var content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("from", "postmaster@sandbox*.mailgun.org"),
                new KeyValuePair<string, string>("to", email),
                new KeyValuePair<string, string>("subject", subject),
                new KeyValuePair<string, string>("text", message)
            });

            await client.PostAsync("sandbox*.mailgun.org/messages", content).ConfigureAwait(false);
        }
    }
3

There are 3 answers

4
Mark Redman On BEST ANSWER

If you are using .Net core and MailKit, you should reference the MailKit libraries and send via those. My MailKit class for sending email is as follows:

using System;
using System.Threading;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using SmtpClient = MailKit.Net.Smtp.SmtpClient;

namespace App.Email
{
    public class MailKit : IMailKit
    {
        private readonly ILogger<MailKit> _logger;
        private readonly Settings _settings;

        public MailKit(ILogger<MailKit> logger, IOptions<Settings> settings)
        {
            _logger = logger;
            _settings = settings.Value;
        }

        /// <summary>
        /// Sends an email asynchronously using SMTP
        /// </summary>
        /// <param name="toEmailAddress"></param>
        /// <param name="subject"></param>
        /// <param name="bodyHtml"></param>
        /// <param name="bodyText"></param>
        /// <param name="retryCount"></param>
        /// <param name="toName"></param>
        public async void Send(string toName, string toEmailAddress, string subject, string bodyHtml, string bodyText, int retryCount = 4)
        {
            var message = new MimeMessage();

            message.From.Add(new MailboxAddress(_settings.MailKitFromName, _settings.MailKitFromAddress));

            message.To.Add(new MailboxAddress(toName, toEmailAddress));

            message.Subject = subject;
            var builder = new BodyBuilder
            {
                TextBody = bodyText,
                HtmlBody = bodyHtml
            };
            message.Body = builder.ToMessageBody();

            for (var count = 1; count <= retryCount; count++)
            {
                try
                {
                    using (var client = new SmtpClient())
                    {
                        client.LocalDomain = _settings.MailKitLocalDomain;
                        client.Authenticate(_settings.MailKitUsername, _settings.MailKitPassword);

                        SecureSocketOptions secureSocketOptions;

                        if (!Enum.TryParse(_settings.MailKitSecureSocketOption, out secureSocketOptions))
                        {
                            secureSocketOptions = SecureSocketOptions.Auto;
                        }

                        await client.ConnectAsync(_settings.MailKitHost, _settings.MailKitPort, secureSocketOptions).ConfigureAwait(false);
                        await client.SendAsync(message).ConfigureAwait(false);
                        await client.DisconnectAsync(true).ConfigureAwait(false);
                        return;
                    }
                }
                catch (Exception exception)
                {
                    _logger.LogError(0, exception, "MailKit.Send failed attempt {0}", count);
                    if (retryCount >= 0)
                    {
                        throw;
                    }
                    await Task.Delay(count * 1000);
                }
            }
        }
    }
}

Interface

namespace App.Email
{
    public interface IMailKit
    {
        void Send(string toName, string toEmailAddress, string subject, string bodyHtml, string bodyText, int retryCount = 4);
    }
}
0
Marcel Mateman On

this my simple solution, now I can send email with MailKit from IdentityServer in a asp core project.

public class EmailSender : Microsoft.AspNetCore.Identity.UI.Services.IEmailSender
{
    private readonly EmailConfiguration _emailConfig;
    public EmailSender(EmailConfiguration emailConfig)
    {
        _emailConfig = emailConfig;
    }

    public Task SendEmailAsync(string email, string subject, string htmlMessage)
    {
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress(_emailConfig.FromName, _emailConfig.FromEmail));
        message.To.Add(new MailboxAddress(email.Trim().ToLower(), email.Trim().ToLower()));
        message.Subject = subject;
        message.Body = new TextPart("html") { Text = htmlMessage };

        using (var client = new SmtpClient())
        {
            try
            {
                client.Connect(_emailConfig.SmtpServer, _emailConfig.Port, MailKit.Security.SecureSocketOptions.SslOnConnect);
                client.Authenticate(_emailConfig.UserName, _emailConfig.Password);
                client.Send(message);
                client.Disconnect(true);
                return Task.FromResult(true);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
            }
        }
    }

and in startup.cs -> ConfigureServices

        var emailConfig = Configuration.GetSection("EmailConfiguration")
            .Get<EmailService.EmailConfiguration>();
        services.AddSingleton(emailConfig);
        services.AddScoped<IEmailSender, EmailService.EmailSender>();
0
luqman ahmad On

You can use async functions like this:

public class Notification
{
    public Notification() { }
    private string emailSubject,receiverEmail,emailBody;

    public string EmailSubject { get => emailSubject; set => emailSubject = value; }
    public string ReceiverEmail { get => receiverEmail; set => receiverEmail = value; }
    public string EmailBody { get => emailBody; set => emailBody = value; }

    public async Task<bool> sendEmail(){
        try
        {
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress("Smart Living", "[email protected]"));
            message.To.Add(new MailboxAddress("Person", receiverEmail));
            message.Subject = emailSubject;
            message.Body = new TextPart("plain")
            {
                Text = emailBody
            };
            using (var client = new SmtpClient())
            {
                await client.ConnectAsync("smtp.gmail.com", 587, false);
                await client.AuthenticateAsync("[email protected]", "living@smart1122");
                await client.SendAsync(message);
                await client.DisconnectAsync(true);
                //                client.ServerCertificateValidationCallback=();
            };
            return true;
        }
        catch (Exception ex) {

            return false;
        }
    }
}