Click here to Skip to main content
15,885,366 members
Articles / Web Development / ASP.NET

Send email with .Net Core using Dependency Injection

Rate me:
Please Sign up or sign in to vote.
4.83/5 (11 votes)
18 Jan 2017CPOL3 min read 46.5K   688   24   10
This blog explains how you can send email with .Net Core using Dependency Injection

When you build a website, there is a big chance that you need email functionality at some point. There are many email packages available for you for this task. Dot Net Core encourages you to configure your email, or other packages using the Dependency Injection principle. This blog shows you how.

Why Dependency Injection?

DI (Dependency Injection) helps you to create loosely coupled application modules. A class receives in the constructor a interface reference to the service object, rather then creating new instance to the service object. This is know as the Explicit Dependencies Principle or "constructor injection". The class has no knowledge about the service object, it just knows how to use it. This makes testing and migrating to an other service component much easier. Dot Net Core fully embrace the Dependency Injection patern. The service is registered during startup. After registration is the service available as a parameter in the controller class constructor. I explain this later in more detail.

Demo Application

With several steps I create a sample application, where we can see how it all works. We build the application in serveral steps.

  1. Create demo MVC application.
  2. Add email package.
  3. Configure email settings.
  4. Create email service interface and class.
  5. Register email service in startup.
  6. Inject email service in controller.

Create demo MVC application

Start Visual Studio and create a new MVC Core application. Authentication is not needed for this demo

Add mail package

I use the MailKit library for this demo. It works well and has an elegant API. Install the mail package from nuget:

pm> Install-Package NETCore.MailKit

Configure email settings in appsettings.json

It's good pratice to configure settings outside the application using a config file. In .Net Core settings are moved to the appsettings.json file. Adding the mail settings is the first step.

...  
"Email": {
    "FromName": "<fromname>",
    "FromAddress": "<fromaddress>",

    "LocalDomain": "<localdomain>",

    "MailServerAddress": "<mailserveraddress>",
    "MailServerPort": "<mailserverport>",

    "UserId": "<userid>",
    "UserPassword": "<userpasword>"
  },
...

You can read the settings with a customized class.

public class EmailConfig
  {
    public String FromName { get; set; }
    public String FromAddress { get; set; }
    
    public String LocalDomain { get; set; }

    public String MailServerAddress { get; set; }
    public String MailServerPort { get; set; }

    public String UserId { get; set; }
    public String UserPassword { get; set; }
  }

The EmailConfig class is used for reading the settings during startup. The section parameter specifies where to read within the appsettings.json file.

public void ConfigureServices(IServiceCollection services)
{
  ...
  // Read email settings
  services.Configure<EmailConfig>(Configuration.GetSection("Email"));
  ...
}

Create email service interface and class

.Net Core DI requires two items:

  1. Interface.
  2. Implementing class.

The interface defines the available functionality. The implementing class, as the name implies implements the interface functionality.

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

public class EmailService : IEmailService
{
  private readonly EmailConfig ec;

  public EmailService(IOptions<EmailConfig> emailConfig)
  {
    this.ec = emailConfig.Value;
  }

  public async Task SendEmailAsync(String email, String subject, String message)
  {
    try
    {
      var emailMessage = new MimeMessage();

      emailMessage.From.Add(new MailboxAddress(ec.FromName, ec.FromAddress));
      emailMessage.To.Add(new MailboxAddress("", email));
      emailMessage.Subject = subject;
      emailMessage.Body = new TextPart(TextFormat.Html) { Text = message };

      using (var client = new SmtpClient())
      {
        client.LocalDomain = ec.LocalDomain;

        await client.ConnectAsync(ec.MailServerAddress, Convert.ToInt32(ec.MailServerPort), SecureSocketOptions.Auto).ConfigureAwait(false);
        await client.AuthenticateAsync(new NetworkCredential(ec.UserId, ec.UserPassword));
        await client.SendAsync(emailMessage).ConfigureAwait(false);
        await client.DisconnectAsync(true).ConfigureAwait(false);
      }
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
    }
  }

The constructor parameter IOptions<EmailConfig> emailConfig provides easy access to the emailsettings without knowing where or how the settings are configured. The MailKit package is used to implement the actual mailing. Supose you want to switch to an other mail service, you only need to change this implementation class. This perfectly fits the Single Responsibility principle.

Register email service in startup.

The next step is to register the interface and the implementation class during startup.

public void ConfigureServices(IServiceCollection services)
{
  ...
  // Register email service 
  services.AddTransient<IEmailService, EmailService>();
  ...
}

Every time a IEmailService reference is requested, a EmailService instance delivered.

Inject email service in controller

After all this works comes the fun part. It's now very easy to make the emailservice available to a controler. Just add a IEmailService parameter in the controller constructor and the MVC framework takes care of the dependency injection!

public class HomeController : Controller
  {
    private readonly IEmailService _emailService;

    public HomeController(IEmailService emailService)
    {
      _emailService = emailService;
    }

Set a breakpoint, start the application and the debugger shows it's all working as expected:

The last step is to actually use the email service for sending a mail. I made simple input form and an action handler on the controller to demonstrate this.

[HttpPost()]
public async Task<IActionResult> Index(MailViewModel model)
{
  if (ModelState.IsValid)
  {
    await _emailService.SendEmailAsync(model.MailTo, model.Subject, model.Message);

    ViewBag.Succes = true;
  }
 
  return View(model);
}

I added the source code so you can play with it. The source code is base on .Net Core 1.10. You can download de SDK here.

Conclusion

You can send mail from a .Net Core application, configured with the DI (Dependency Injection) principle. Dot Net Core supports DI out of the box, there is no need for third party tooling. The DI configuration takes some effort. In return you get all the benefits such as loosely coupling, Single Point of Resposibility and better testing possibilities.

Further reading

MailKit New is glue

wiki deendency injection

Dot Net Core dependency injection    

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Netherlands Netherlands
I graduated as Bachelor of Mechanical Engineering. Soon I moved from mechanical to software engineering. With more than 20 years of experience in software design, development, and architecture I love building software that users enjoy en suit their needs.

Comments and Discussions

 
Questionhaving issues when trying to send html template Pin
Xletar16-Sep-20 3:31
Xletar16-Sep-20 3:31 
QuestionDI - Lifetime Pin
dogahas3-Sep-18 21:40
dogahas3-Sep-18 21:40 
AnswerRe: DI - Lifetime Pin
Pete Dragun14-Jan-24 13:20
Pete Dragun14-Jan-24 13:20 
SuggestionMore comfort in sending email with .Net Core Pin
axuno5-Nov-17 4:09
axuno5-Nov-17 4:09 
QuestionImplementing errors Pin
web_11127-Feb-17 5:23
web_11127-Feb-17 5:23 
AnswerRe: Implementing errors Pin
Bart-Jan Brouwer7-Mar-17 2:37
Bart-Jan Brouwer7-Mar-17 2:37 
QuestionAny Razor support Pin
Layinka24-Jan-17 5:12
professionalLayinka24-Jan-17 5:12 
AnswerRe: Any Razor support Pin
Bart-Jan Brouwer25-Jan-17 19:18
Bart-Jan Brouwer25-Jan-17 19:18 
QuestionMail Header Control Pin
JohnnySandaire20-Jan-17 8:14
JohnnySandaire20-Jan-17 8:14 
AnswerRe: Mail Header Control Pin
Bart-Jan Brouwer22-Jan-17 19:56
Bart-Jan Brouwer22-Jan-17 19:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.