ASP.NET CORE: Sending Email with Gmail and Homtail Account using ASP.NET Core services

Standard

Sending email from any SMTP server from ASP.NET CORE application is pretty easy, but the flow of command is slight different in core environment.

Gmail SMTP server address is smtp.gmail.com. It requires implicit SSL or explicit SSL (TLS) connection, and you should use your Gmail email address as the user name for ESMTP authentication.

So basically we will read email smtp address, port, username and password from appsettings.json, then will inject these config to email service class, in the end we will inject email service class to controller and consumer email send operation.

Step 1: Define email specific information in appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": ""
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "EmailSettings": {
    "PrimaryDomain": "smtp.gmail.com",
    "PrimaryPort": "587",
    "SecondayDomain": "smtp.live.com",
    "SecondaryPort": "587",
    "UsernameEmail": "emailId@gmail.com",
    "UsernamePassword": "emailPassword",
    "FromEmail": "fromEmail",
    "ToEmail": "toEmail",
    "CcEmail": "ccEmail"
  }
}

SmtpServer: The name of the server that will be used to send the emails.

SmtpPort: The port, which the server will use to send SMTP transactions (emails).

EnableSsl: True, if the server should use SSL (Secure Socket Layer) encryption.

Smtp Server Address and Port #

Server Name SMTP Address Port SSL
Yahoo! smtp.mail.yahoo.com 587 Yes
GMail smtp.gmail.com 587 Yes
Hotmail smtp.live.com 587 Yes

Step 2: Create a class to encapsulate EmailSettings properties from appsettings.json

public class EmailSettings
    {
        public String PrimaryDomain { get; set; }

        public int PrimaryPort { get; set; }

        public String SecondayDomain { get; set; }

        public int SecondaryPort { get; set; }

        public String UsernameEmail { get; set; }

        public String UsernamePassword { get; set; }

        public String FromEmail { get; set; }

        public String ToEmail { get; set; }

        public String CcEmail { get; set; }
    }

Step 3: Register class in startup.cs for DI purposes

services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

Step 4: Create an Email sender interface

public interface IEmailSender
{
    Task SendEmailAsync(string email, string subject, string message);
}

Step 5: Create a message service class which will implement this interface

Inject EmailSettings class in message service using options pattern, so that email configuration defined in appsettings.json is available in this service.

We will use SmtpClient class to allow applications to send e-mail by using the Simple Mail Transfer Protocol (SMTP).

public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<EmailSettings> emailSettings)
        {
            _emailSettings = emailSettings.Value;
        }

        public EmailSettings _emailSettings { get; }

        public Task SendEmailAsync(string email, string subject, string message)
        {

            Execute (email, subject, message).Wait();
            return Task.FromResult(0);
        }

        public async Task Execute(string email, string subject, string message)
        {
          try
          {
            string toEmail = string.IsNullOrEmpty(email) 
                             ? _emailSettings.ToEmail 
                             : email;
            MailMessage mail = new MailMessage()
            {
                From = new MailAddress(_emailSettings.UsernameEmail, "Muhammad Hassan Tariq")
            };
            mail.To.Add(new MailAddress(toEmail));
            mail.CC.Add(new MailAddress(_emailSettings.CcEmail));

            mail.Subject = "Personal Management System - " + subject;
            mail.Body = message;
            mail.IsBodyHtml = true;
            mail.Priority = MailPriority.High;

            using (SmtpClient smtp = new SmtpClient(_emailSettings.SecondayDomain, _emailSettings.SecondaryPort))
            {
                smtp.Credentials = new NetworkCredential(_emailSettings.UsernameEmail, _emailSettings.UsernamePassword);
                smtp.EnableSsl = true;
                await smtp.SendMailAsync(mail);
            }
          }
          catch(Exception ex)
          {
             //do something here
          }
        }
    }

*exception handling is left for you to implement 🙂

  • You can attach one or several files:
mail.Attachments.Add(new Attachment(Server.MapPath("~/myimage.jpg")));
  • You can send to more than one person at the same time
mail.To.Add("test@email.com");
mail.To.Add("test2@email.com");
  • You can set a name for the sender
mail.From = new MailAddress("test@email.com", "Hello");
  • You can send HTML e-mails, instead of the default plaintext mails
mail.IsBodyHtml = true;
mail.Body = "Testing <b>123!</b>";
  • You can use the CC and BCC fields
mail.CC.Add("test@email.com");
mail.Bcc.Add("test2@email.com");
  • You can set the priority of an e-mail
mail.Priority = MailPriority.High;

Step 6: Register email sender service in startup.cs, so that it can be injected in controllers

services.AddTransient<IEmailSender, AuthMessageSender>();

Step 7: Controller code (consumer)

Inject email sender service in controller constructor and then invoke SendEmailAsync method of it

public class TestController : Controller
    {
        private readonly IEmailSender _emailSender;

        public AccountController(IEmailSender emailSender)
        {
            _emailSender = emailSender;
        }
        
        public async Task TestAction()
        {
           await _emailSender.SendEmailAsync("test@gmail.com", "subject",
                        $"Enter email body here");
        }
    }

Note:

Google may block sign in attempts from some apps or devices that do not use modern security standards. Since these apps and devices are easier to break into, blocking them helps keep your account safer.

Please make sure, in Gmail settings of your account, enable access for less secure apps to avoid below error:

The SMTP server requires a secure connection or the client was not 
authenticated. The server response was: 5.5.1 Authentication Required?

ASP.NET: Store Email Template in .NET

Standard

Simple and Easy to edit way to store email templates in your .net project is string email body in html file.

Step 1: Create a HTML mail message

2016-10-04-16_04_18-_c__users_hassan-muhammad_desktop_new-14-html-notepad

Step 1(a): You can introduce as many as variable in HTML template by any character scheme (@PARAMETER@ or #PARAMETER# or $$PARAMETER$$). Replace all names/variables with things like #VaraibleName#
The confirmation number is: <b>#confirmNumber#</b>
Step 2: Right click on web project and select Properties from right click menu

2016-10-04-16_08_58-recruiting-microsoft-visual-studio-administrator

Step 3: Select Resources tab from left, choose Add Resource, select Add Existing File and choose appropriate html file

2016-10-04-16_24_57-recruiting-microsoft-visual-studio-administrator

Step 4: File will be visible in Resources display pan

2016-10-04-16_26_31-recruiting-microsoft-visual-studio-administrator

Step 5: For Server side C# code

You can refer to HTML email template from Properties.Resources.EmailTemplate. You can use it as a string. Replace the #PARAMETER# text with the actual values.

private void SendConfirmationEmail(string email, string confirmNumber)
{
    var emailBody = Properties.Resources.EmailTemplate.Replace("#confirmNumber#", confirmNumber);
    MailMessage message =
        new MailMessage
        {
            From =
            new MailAddress("Sender Email Address"),
            Subject = "Email Subject Content",
            Body = string.Format(emailBody),
            IsBodyHtml = true
        };
 
    message.To.Add(new MailAddress(email));
    SmtpClient client = new SmtpClient("11.111.111.11");
    client.Send(message);
}