How to Send Emails in ASP.NET Core 1.0

ASP.NET Core 1.0 is a reboot of the ASP.NET framework which can target the traditional full .NET framework or the new .NET Core framework. Together ASP.NET Core and .NET Core have been designed to work cross platform and have a lighter, faster footprint compared to the current full .NET framework. Many of the .NET Core APIs are the same as they are in the full framework and the team have worked hard to try and keep things reasonably similar where it makes sense and is practical to do so. However, as a consequence of developing a smaller, more modular framework of dependant libraries and most significantly making the move to support cross platform development and hosting; some of libraries have been lost. Take a look at this post from Immo Landwerth which describes the changes in more detail and discusses considerations for porting existing applications to .NET Core.

I’ve been working with ASP.NET Core for quite a few months now and generally I have enjoyed the experience. Personally I’ve hit very few issues along the way and expect to continue using the new framework going forward wherever possible. Recently though I did hit a roadblock on a project at work where I had a requirement to send email from within my web application. In the full framework I’d have used the SmtpClient class in system.net.mail namespace. However in .NET Core this is not currently available to us.

Solutions available in the cloud world include services such as SendGrid; which, depending on the scenario I can see as a very reasonable solution. For my personal projects and tests this would indeed be my preferred approach, since I don’t have to worry about maintaining and supporting an SMTP server. However at work we have SMTP systems in place and a specialised support team who manage them, so I ideally needed a solution to allow me to send emails directly as we do in our traditionally ASP.NET 4.x applications.

As with most coding challenges I jumped straight onto Google to see who else had had this requirement and how they solved the problem. However I didn’t find as many documented solutions that helped me as I was expecting to. Eventually I landed on this issue within the corefx repo on Github. That led me onto the MailKit library maintained by Jeffrey Stedfast and it turned out to be a great solution for me as it has recently been updated to work on .NET Core.

In this post I will take you through how I got this working for the two scenarios I needed to tackle. Firstly sending mail directly via an SMTP relay and secondly the possibility to save the email message into an SMTP pickup folder. Both turned out to be pretty painless to get going.

Adding MailKit to your Project

The first step is to add the reference to the NuGet package for MailKit. I now prefer to use the project.json file directly to setup my dependencies. You’ll need to add the MailKit library – which is at version 1.3.0-beta6 at the time of writing this post – to your dependencies section in the project.json file.

On a vanilla ASP.NET Core web application your dependencies should look like this:

Dependancies

Once you save the change VS should trigger a restore of the necessary NuGet packages and their dependencies.

Sending email via a SMTP server

I tested this solution in a default ASP.NET Core web application project which already includes an IEmailSender interface and a class AuthMessageSender which just needs implementing. It was an obvious choice for me to test the implementation using this class as DI is already hooked up for it. For this post I’ll show the bare bones code needed to get started with sending emails via an SMTP server.

To follow along, open up the MessageServices.cs file in your web application project.

We need three using statements at the top of the file.

using MailKit.Net.Smtp;
using MimeKit;
using MailKit.Security;

The SendEmailAsync method can now be updated as follows:

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

	emailMessage.From.Add(new MailboxAddress("Joe Bloggs", "jbloggs@example.com"));
	emailMessage.To.Add(new MailboxAddress("", email));
	emailMessage.Subject = subject;
	emailMessage.Body = new TextPart("plain") { Text = message };

	using (var client = new SmtpClient())
	{
		client.LocalDomain = "some.domain.com";                
		await client.ConnectAsync("smtp.relay.uri", 25, SecureSocketOptions.None).ConfigureAwait(false);
		await client.SendAsync(emailMessage).ConfigureAwait(false);
		await client.DisconnectAsync(true).ConfigureAwait(false);
	}
}

First we declare a new MimeMessage object which will represent the email message we will be sending. We can then set some of it’s basic properties.

The MimeMessage has a “from” address list and a “to” address list that we can populate with our sender and recipient(s). For this example I’ve added a single new MailboxAddress for each. The basic constructor for the MailboxAddress takes in a display name and the email address for the mailbox. In my case the “to” mailbox takes the address which is passed into the SendEmailAsync method by the caller.

We then add the subject string to the email message object and then define the body. There are a couple of ways to build up the message body but for now I’ve used a simple approach to populate the plain text part using the message passed into the SendEmailAsync method. We could also populate a Html body for the message if required.

That leaves us with a very simple email message object, just enough to form a proof of concept here. The final step is to send the message and to do that we use a SmtpClient. Note that this isn’t the SmtpClient from system.net.mail, it is part of the MailKit library.

We create an instance of the SmtpClient wrapped with a using statement to ensure that it is disposed of when we’re done with it. We don’t want to keep connections open to the SMTP server once we’ve sent our email. You can if required (and I have done in my code) set the LocalDomain used when communicating with the SMTP server. This will be presented as the origin of the emails. In my case I needed to supply the domain so that our internal testing SMTP server would accept and relay my emails.

We then asynchronously connect to the SMTP server. The ConnectAsync method can take just the uri of the SMTP server or as I’ve done here be overloaded with a port and SSL option. For my case when testing with our local test SMTP server no SSL was required so I specified this explicitly to make it work.

Finally we can send the message asynchronously and then close the connection. At this point the email should have been fired off via the SMTP server.

Sending email via a SMTP pickup folder

As I mentioned earlier I also had a requirement to drop a message into a SMTP pickup folder running on the web server rather than sending it directly through the SMTP server connection. There may well be a better way to do this (I got it working in my test so didn’t dig any deeper) but what I ended up doing was as follows:

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

	emailMessage.From.Add(new MailboxAddress("Joe Bloggs", "jbloggs@example.com"));
	emailMessage.To.Add(new MailboxAddress("", email));
	emailMessage.Subject = subject;
	emailMessage.Body = new TextPart("plain") { Text = message };

	using (StreamWriter data = System.IO.File.CreateText("c:\\smtppickup\\email.txt"))
	{
		emailMessage.WriteTo(data.BaseStream);
	}
}

The only real difference from my earlier code was the removal of the use of SmtpClient. Instead, after generating my email message object I create a steamwriter which creates a text file on a local directory. I then used the MimeMessage.WriteTo method passing in the base stream so that the RFC822 email message file is created in my pickup directory. This is picked up and sent via the smtp system.

Summing Up

MailKit seems like a great library and it’s solved my immediate requirements. There are indications that the Microsoft team will be working on porting their own SmtpClient to support ASP.NET Core at some stage but it’s great that the community have solved the problem for those adopting / testing .NET Core now.

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #2040()

  • Pingback: Emails using Mailgun in ASP.NET Core | Eric L. Anderson()

  • Pingback: Les liens de la semaine – Édition #173 (bissextile, en plus!) | French Coding()

  • Pingback: 주간닷넷 2016년 2월 23일 - Korea Evangelist - Site Home - MSDN Blogs()

  • Pingback: 주간닷넷 2016년 2월 23일 | Korea Evangelist()

  • Nadav

    Hi,
    What are the benefits of MailKit over .net simple mail package ?

    • Steve Gordon

      I’m not sure exactly which package you are referring to? There certainly may be others available but whether they support .NET core is something you’d need to check. Anything relying on the System.Net.Mail namespace would not be suitable in ASP.NET Core.

  • David

    I’m currently trying to figure out about adding the smtp host name and sender name/email in my AppSettings, and have the AuthMessageSender read that, instead of hard-coding it, so that I can have proper local dev and production values in the appropriate places. While it’s technically beyond the scope of this task, it would be helpful to include it, or at least link to instructions elsewhere.

    Otherwise, I wish I’d found your tutorial a couple hours ago. 🙂 Thank you.

    • Steve Gordon

      It was a bit beyond the scope of what I was looking at in this case so I didn’t include anything since it may require explaining the new configuration API’s. However you can try taking a look at https://channel9.msdn.com/Series/aspnetmonsters/Episode-5-Configuration-Settings for an intro to the new configuration options which can indeed provide different settings for dev/prod environments.

    • waqar

      Waht you can do it to Utilize the potential of UserSecrets in this situation.
      Google how to use them in your project, you’ll be good to go.

  • Rafał

    How to fix: “Unable to locate Dependency MailKit >= 1.3.0-beta7”

    project.json
    {
    “version”: “1.0.0-*”,
    “compilationOptions”: {
    “emitEntryPoint”: true
    },

    “dependencies”: {
    “Microsoft.AspNet.IISPlatformHandler”: “1.0.0-rc1-final”,
    “Microsoft.AspNet.Mvc”: “6.0.0-rc1-final”,
    “Microsoft.AspNet.Server.Kestrel”: “1.0.0-rc1-final”,
    “Microsoft.AspNet.StaticFiles”: “1.0.0-rc1-final”,
    “MailKit”: “1.3.0-beta7”
    },

    “commands”: {
    “web”: “Microsoft.AspNet.Server.Kestrel”
    },

    “frameworks”: {
    “dnx451”: { },
    “dnxcore50”: { }
    },

    “exclude”: [
    “wwwroot”,
    “node_modules”
    ],
    “publishExclude”: [
    “**.user”,
    “**.vspscc”
    ]
    }

  • Marty

    Thanks for the example. Using async is a good plan – but the example does not show how any means by which to check for successful submission, which is essential. It would be nice to include this.

    • Steve Gordon

      Hi Marty,
      Thanks for your feedback. I’m glad you found it useful. This post was quite a basic introduction. I can see that the SendAsync accepts an ITransferProgress parameter which seems to be a way to get feedback on the number of bytes transmitted to there server. I think with that you’d be able to determine the send progress for messages and act accordingly. There is also a SmtpResponse class as well which I’m assuming can provide further details back from the SMTP server.
      Steve

  • john

    Thanks for this, I moved my project to ASP.NET Core and this saved me a lot of time.

    A slightly amended version for folks who need to use smtp authentication:

    var emailMessage = new MimeMessage();

    emailMessage.From.Add(new MailboxAddress(fromName, from));
    emailMessage.To.Add(new MailboxAddress(“”, to));
    emailMessage.Subject = subject;
    emailMessage.Body = new TextPart(“plain”) { Text = body };

    using (var client = new SmtpClient())
    {
    var credentials = new NetworkCredential
    {
    UserName = “username@domain.com”, // replace with valid value
    Password = “password” // replace with valid value
    };

    client.LocalDomain = “domain.com”;
    // check your smtp server setting and amend accordingly:
    await client.ConnectAsync(“smtp.office365.com”, 587, SecureSocketOptions.Auto).ConfigureAwait(false);
    await client.AuthenticateAsync(credentials);
    await client.SendAsync(emailMessage).ConfigureAwait(false);
    await client.DisconnectAsync(true).ConfigureAwait(false);

    • SYED

      Thank you so much JOHN for the amazing solution, i was searching this solution since from the last two days and
      Now i got it and Actually i’m a newbie of Asp.net core and probably i dont have any idea about sending email
      in .NET core but now i got the solution.Thanks once again!

    • Kelsey Steele

      Hi Steve and everyone in the comments.

      I am so confused. I am completely new to asp.net core and sending e-mails from any application. I can kind of see what you are doing here, but I don’t know what to do after adding this method to the application. I’ve read through the GitHub documentation a few times and they also seem to fall short of actually explaining what MailKit does and how to execute it until you actually do send an e-maill.

      The problem that I am facing is that I have a form that I want to be e-mailed to an employee when the form is filled out a certain way. I also want to be able to log into my asp.net core website and be able to send an e-mail directly to website users who have submitted their e-mail address. I’ve been Googling for days and I keep being directed to this page and similar resources.

      Does anyone know of a resource for complete beginners? Thanks!!!

      • Steve Gordon

        Hi Kelsey,

        There would be a lot of considerations for your requirement and ultimately you might be better off looking at services such as SendGrid for managing mailing lists of users which you could collect via your website.

        If you did want to do this in the website directly then you would need to setup an MVC controller with an action to handle a form post of the message you want to send. This action would then call into the SendEmailAsync method to actually send the email(s). In your case, I presume you’d want to load the list of recipients from a database of registered users. You can add multiple CC email addresses when sending a message.

        That’s the very high level, but I recommend you spend time with some more general MVC/ASP.NET Core tutorials and samples before trying to write this feature. Here is the best generalised link I can give – https://docs.microsoft.com/en-us/aspnet/core – Check out some of the tutorials there which might help.

  • Does this support SSL? Last time I tried this, sending simple emails wasn’t so tricky, infact I had a small class to do it for me in pure .NET core, but SSL was another kettle of fish. For some reason using MailKit seemed to work, until you try deploying it to a device that is not running full windows, such as a Pi 2 and Windows 10 IoT, or Ubuntu, it would choke on the absence of the SecureStream (I think that’s the name) class, but on full Windows even though you only target core it seemed to still pickup the full framework SecureStream.

  • Pingback: Emails using Mailgun in ASP.NET Core – Eric L. Anderson()

  • Don’t forget to add environment variables if you don’t load the x509 for connecting to your SMTP server in Startup.cs. This happens in NetCore 1.10, dotnet crashes when trying to send emails.
    https://github.com/dotnet/corefx/issues/13814
    http://stackoverflow.com/questions/31049152/publish-to-iis-setting-environment-variable/36836533#36836533

  • Pingback: Email with ASP.NET Core Using Mailgun – Eric L. Anderson()

  • Johnny Trinh

    Use this code for outlook365

    using System;

    using MailKit.Net.Smtp;
    using MailKit.Security;
    using MailKit;
    using MimeKit;

    namespace TestClient {
    class Program
    {
    public static void Main (string[] args)
    {
    var message = new MimeMessage ();
    message.From.Add (new MailboxAddress (“”, “test.user@mydomain.com”));
    message.To.Add (new MailboxAddress (“”, “test.recipient@anotherdomain.com”));
    message.Subject = “Test message”;

    message.Body = new TextPart (“plain”) { Text = “This is the message body.” };

    using (var client = new SmtpClient (new ProtocolLogger (“smtp.log”))) {
    client.Connect (“smtp.office365.com”, 587, SecureSocketOptions.StartTls);

    client.Authenticate (“test.user@mydomain.com”, “password”);

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

  • The mailket can’t install in vs2017 mvc core 1.1,how to do with it?

  • Checkout FluentMail as it’s ready for .net core and has MailGun, SendGrid and SMTP options…. great library!