DEV Community

loading...

A complete guide to send email in .NET (2021)

lukencode profile image Luke Lowrey Originally published at lukelowrey.com on 惻7 min read

A complete guide to send email in .NET (2021)

FluentEmail is an open-source .NET library (created by me but with lots of help) that helps you implement complete email sending functionality in you dotnet app in less than 10 minutes (probably). It features built in providers for the most popular email senders including SendGrid and Mailgun along with Razor or Liquid templates out of the box.

Why use FluentEmail?

FluentEmail pieces together the components your application needs for sending email.

  • The API is so simple that autocomplete (almost) writes your code for you!
  • Well tested providers for the popular email senders and template engines are available out of the box (keep reading to see examples)
  • Solid dependency injection keeps your code clean and allows you to easily write tests or switch out email options for different tenants/environments

Basic Usage

FluentEmail and its providers can be installed via Nuget. The FluentEmail.Core library is all you need to get started.

dotnet add package FluentEmail.Core

To construct and send an email you just keep building up the fluent methods on the IEmail class. When you are ready to send call SendAsync().

var email = await Email
    .From("bill.gates@microsoft.com")
    .To("luke.lowrey@example.com", "Luke")
    .Subject("Hi Luke!")
    .Body("Fluent email looks great!")
    .SendAsync();

Enter fullscreen mode Exit fullscreen mode

There are the most common methods available on the email object (for the full list see IFluentEmail.cs)

  • . To (string emailAddress) - add recipients
  • . SetFrom (string emailAddress) - change the sender address
  • . CC/BCC (string emailAddress) - add CC or BCC
  • . Subject (string subject) - set the subject
  • . Body (string body) - set the message body (without templating)
  • . Attach (Attachment attachment) - add attachments
  • UsingTemplate (string template, T model, bool isHtml = true) - set a template, keep reading for more templating information
  • SendAsync () - send the email using the configured sender

Dependency Injection

The best way to use FluentEmail is to configure your sender and template choices with dependency injection. There is good out of the box support for the built in .NET DependencyInjection classes.

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")
        .AddRazorRenderer()
        .AddSmtpSender("localhost", 25);
}

Enter fullscreen mode Exit fullscreen mode

This example sets up FluentEmail with a default SendFrom address and uses the injection helpers to add the SmtpSender and RazorRenderer.

  • ISender - this interface is the provider that will be used to send the email. In this example the AddSmtpSender() method configures an SmtpSender provider.
  • ITemplateRenderer - this is an optional interface to provide email templating support. In the example the AddRazorRenderer() method is setting up the RazorRenderer provider.

Using dependency injection will make a couple of interfaces available to your code. See the example below for sending email with the configured services.

public class EmailExampleController : Controller
{
    public async Task<IActionResult> SendSingleEmail([FromServices] IFluentEmail singleEmail)
    {    
        var email = singleEmail
            .To("test@test.test")
            .Subject("Test email")
            .Body("This is a single email");

        await email.SendAsync();

        return Ok();
    }

    public async Task<IActionResult> SendMultipleEmail([FromServices] IFluentEmailFactory emailFactory)
    {    
        var email1 = emailFactory
            .Create()
            .To("test@test.test")
            .Subject("Test email 1")
            .Body("This is the first email");

        await email1.SendAsync();

        var email2 = emailFactory
            .Create()
            .To("test@test.test")
            .Subject("Test email 2")
            .Body("This is the second email");

        await email2.SendAsync();

        return Ok();
    }
}

Enter fullscreen mode Exit fullscreen mode
  • IEmail - this is a single instance of an email to be sent as demonstrated in the basic example above. Use this to send one email (but no more!)
  • IEmailFactory - this interface has a method .Create() which will give you an IEmail instance. Use this interface to send multiple emails in the same method or request - see the following example.

Template Rendering

FluentEmail has core support for multiple template renderer providers. To use template rendering, include one of the providers and configure it as part of your dependency injection.

// Using Razor templating package (or set using AddRazorRenderer in services)
Email.DefaultRenderer = new RazorRenderer();

var template = "Dear @Model.Name, You are totally @Model.Compliment.";
var model = new 
{
    Name = "Luke Lowrey",
    Position = "Developer",
    Message = "Hi Luke, this is an email message"
};

var email = Email
    .From("bob@hotmail.com")
    .To("somedude@gmail.com")
    .Subject("woo nuget")
    .UsingTemplate(template, model);

Enter fullscreen mode Exit fullscreen mode

The UsingTemplate method accepts a string for the template and an object for the model to use. The template itself will depend on the provider you are using, this example uses the standard RazorRenderer

FluentEmail also providers helper methods to source template files from disk or as embedded resources as well as serving different templates based on culture.

  • UsingTemplateFromEmbedded (string path, T model, Assembly assembly) - pass the assembly with the embedded resource and the path eg "YourApp.EmailTemplates.Welcome.txt"".
  • UsingTemplateFromFile (string filename, T model) - pass the file path for the template.

Razor Email Templates

The examples above use the FluentEmail.Razor template renderer. This is the most popular option for templating. The Razor render uses the RazorLightlibrary to render Razor strings.

dotnet add package FluentEmail.Razor

The RazorRenderer supports any valid Razor code. This example (taken from the test project) shows how you can use layout pages in templates.

//configure the Razor Renderer
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")

        //pass in the root directory for files
        .AddRazorRenderer(Directory.GetCurrentDirectory()) 

        //OR pass in the root assembly if you use embedded resources
        .AddRazorRenderer(Assembly.GetExecutingAssembly()) 
}

//In your template code include a layout file
//the template could be sourced from file/embedded if that is configured
var template = @"
    @{ Layout = ""./Shared/_Layout.cshtml""; }

    Hi @Model.Name here is a list @foreach(var i in Model.Numbers) { @i }
";

var model = new { Name = "LUKE", Numbers = new[] { "1", "2", "3" } };

var email = new Email()
    .To("test@test.test")
    .Subject("Razor template example")    
    .UsingTemplate(template, model});

Enter fullscreen mode Exit fullscreen mode

Liquid Templates

Liquid templates are a more restricted templating language created by Shopify. They are more lightweight than Razor templates as well as safer and simpler for end users to create. Properties on the model are made available as Liquid properties in the template. FluentEmail uses Fluid (see samples) to render the templates in C#.

//configure the Razor Renderer
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")     
        .AddLiquidRenderer(options =>
        {
            // file provider is used to resolve layout files if they are in use
            options.FileProvider = new PhysicalFileProvider(Path.Combine(someRootPath, "EmailTemplates")); ;
        });
}

// Liquid template which utilizes layout
var template = @"
    {% layout '_layout.liquid' %}    
    Dear {{ Name }}, You are totally {{ Compliment }}.
";

var model = new ViewModel { Name = "Luke", Compliment = "Awesome" };

var email = Email
    .From()
    .To("somedude@gmail.com")
    .Subject("Liquid templates")
    .UsingTemplate(template, model);

Enter fullscreen mode Exit fullscreen mode

Email Senders

FluentEmail allows you to plug in popular email sending providers (or build your own by implementing ISender). To use a sender include the provider and configure it as part of dependency injection.

The following senders are available as core libraries. The same core FluentEmail methods are used to send emails, the only difference is what sender you configure.

SMTP Sender

The SMTP sender use System.Net.Mail.SmtpClient to send email. It is set up using dependency injection. You can provide basic host and port details or a full SmtpClient instance.

dotnet add package FluentEmail.Smtp

//configure smtp sender
public void ConfigureServices(IServiceCollection services)
{
    services
       .AddFluentEmail("fromemail@test.test")
       .AddSmtpSender("yoursmtphost.com", 25) //configure host and port
       .AddSmtpSender(new SmtpClient() { }); //OR provide your own SmtpClient instance
}

//Send email as per examples above
await new Email
    .To("test@test.test")
    .Subject("Email example")    
    .Body("Email body")
    .SendAsync(); //this will use the SmtpSender

Enter fullscreen mode Exit fullscreen mode

Mailgun Sender

Mailgun is an API based email sender. The FluentEmail Mailgun sender supports most functionality including attachments, tags and headers.

dotnet add package FluentEmail.Mailgun

//configure Mailgun sender
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")
        .AddMailGunSender("domainname.com", "yourapikey", FluentEmail.Mailgun.MailGunRegion.USA);
}

//Send email as per examples above
await new Email()
    .To("test@test.test")
    .Subject("Mailgun example")
    .Body("Email body")
    .Tag("tagname") //the Mailgun sender supports tags
    .SendAsync() //this will use the MailgunSender

Enter fullscreen mode Exit fullscreen mode

SendGrid Sender

SendGridis another popular API based email sender. The FluentEmail SendGrid provider can be used in "live" or "sandbox" mode.

dotnet add package FluentEmail.Mailgun

//configure SendGrid sender
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")
        .AddSendGridSender("apikey");
}

//Send emails as per examples above
Enter fullscreen mode Exit fullscreen mode

MimeKit Sender

MimeKitis an open source .NET email library with support for IMAP, POP3, and SMTP. If you need to do anything advanced with email protocols you need to use MimeKit.

The MimeKit sender for FluentEmail lets you to set up whatever flavour of email sending you need and include it in the FluentEmail framework.

dotnet add package FluentEmail.MailKit

//configure MailKit sender
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddFluentEmail("fromemail@test.test")
        .AddMailKitSender(new SmtpClientOptions
        {
            Server = "server",
            Port = 25,
            Password = "password",
            UseSsl = true,
            User = "user"
        });
}

//Send emails as per examples above
Enter fullscreen mode Exit fullscreen mode

Other Senders

Other people in the open source community have built and maintain senders for different email providers.

Extending FluentEmail

FluentEmail was built to make it easy to plug in your own providers for templating and sending. If you are working on something you think belongs in the core repository head on over to the Github repoand let me know.


If you found this post useful and want to help me (and others out) please share the thread on twitter.

Discussion (2)

pic
Editor guide
Collapse
anonymous675 profile image
anonymous675 • Edited

Looks great, the API seems simple, gonna try it on my website.

Do I need to configure something else to use a custom email?

Collapse
lukencode profile image
Luke Lowrey Author

All you need to do is configure an email sender (smtp, sendgrid etc) then use the api to construct your email. If you want to do templated emails you will need to add either the razorrenderer or liquidrenderer.