Sending An Email In C#/.NET

How do you send an email in C#/.NET? That sounds like it should be simple, after all, electronic mail existed decades before the Internet.

If you've worked with emails for any length of time, you'll soon hear about the Simple Mail Transfer Protocol (SMTP) for sending and Internet Message Access Protocol (IMAP - which replaced POP3) for receiving. That's an important distinction to take note of: sending, and receiving emails use different protocols.

System.Net.Mail

At first glance, SMTP seems relatively straightforward.

Here's how to write an email using System.Net.Mail (there's a better way though):

var smtpClient = new SmtpClient("smtp.example.com"){
    Port = 587,
    Credentials = new NetworkCredential("username", "password"),
    EnableSsl = true,
};
smtpClient.Send("[email protected]", "[email protected]", "subject", "body");

That doesn't actually look that bad, and might be all you need at the moment.

You can even re-write it to make an email object called MailMessage first:

var mailMessage = new MailMessage{
    From = new MailAddress("[email protected]"),
    To = new MailAddress("[email protected]"),
    Subject = "subject",
    Body = "<p>Hello</p>",
    IsBodyHtml = true,
};
smtpClient.Send(mailMessage);

 You can also move the client definition to a separate appsettings.json file like so (if adding it manually then make sure to set Properties -> Copy to Output Directory -> Copy if newer):

{
  "EmailSender": {
    "SmtpHost": "smtp.gmail.com",
    "SmtpPort": 587,
    "SmtpCredential": {
      "UserName": "[email protected]",
      "Password": "App1icati0nP455w0rd"
    },
    "ProtocolLog": "Logs\\SmtpClient.txt"
  }
}

You could read those settings with Microsoft.Extensions.Configuration.Json and use them as follows (keep reading though, there's a better way!): 

using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var smtpClient = new SmtpClient(configuration["EmailSender:SmtpHost"]){
    Port = int.Parse(configuration["EmailSender:SmtpPort"]),
    Credentials = new NetworkCredential(configuration["EmailSender:SmtpCredential:UserName"], configuration["EmailSender:SmtpCredential:Password"]),
    EnableSsl = true,
};

Let's simplify that by parsing the configuration to a predefined object type (later we'll re-use MailKitSimplified.Sender.Models.EmailSenderOptions):

using Microsoft.Extensions.Configuration;
var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var emailSenderOptions = configuration.GetRequiredSection(EmailSenderOptions.SectionName).Get<EmailSenderOptions>();
var smtpClient = new SmtpClient(emailSenderOptions.SmtpHost){
    Port = emailSenderOptions.SmtpPort,
    Credentials = emailSenderOptions.SmtpCredential,
    EnableSsl = emailSenderOptions.SmtpPort == 587 ? true : false,
};

Unfortunately for us, System.Net.Mail doesn't fully implement Multipurpose Internet Mail Extensions (MIME) types defined in the RFC standards. That's all the Internet is reallly, connections based on global standards, so they should be adhered to. Is there a package that does?

MailKit and MimeKit

If you read about it online, you'll quickly discover that even Microsoft recommends using MailKit.

Here's how to write an email using MailKit and the MimeKit dependency:

var mailMessage = new MimeMessage();
mailMessage.From.Add(new MailboxAddress("from name", "[email protected]"));
mailMessage.To.Add(new MailboxAddress("to name", "[email protected]"));
mailMessage.Subject = "subject";
mailMessage.Body = new TextPart(){
    Text = "Hello"
};
using (var smtpClient = new SmtpClient()){
    smtpClient.Connect("smtp.example.com", 587, true);
    smtpClient.Authenticate("username", "password");
    smtpClient.Send(mailMessage);
    smtpClient.Disconnect(true);
}

Is it just me or did we just make sending an email harder than it was with System.Net.Mail? That's unfortunately the downside of being an all-in-one .NET solution for email. MailKit can have a bit of a learning curve to set up and use. Is there a easier way?

There is.

MailKitSimplified.Sender

By adding the MailKitSimplified.Sender package from NuGet, you can still do everything MailKit does as that's still used under the hood, but all of the pain points go away:

using var smtpSender = SmtpSender.Create("smtp.example.com:587")
    .SetCredential("username", "password");
smtpSender.WriteEmail
    .From("[email protected]")
    .To("[email protected]")
    .Subject("Hello World")
    .BodyHtml("<p>Hi</p>")
    .Send();

What about defining the sender options in an application configuration file? We could do that manually with MailKitSimplified.Sender.Models.EmailSenderOptions like we did before:

using var smtpSender = SmtpSender.Create(emailSenderOptions);

If you know how dependency injection works then it's even easier using MailKitSimplified.Sender:

services.AddMailKitSimplifiedEmailSender(context.Configuration);

If you put all that together with a written email you can copy and re-use:

var template = smtpSender.WriteEmail
    .From("[email protected]")
    .Bcc("[email protected]")
    .Subject("Hello World")
    .BodyText("Hi")
    .BodyHtml("<p>Hi</p>")
    .TryAttach("CompanyLogo.png")
    .SaveTemplate();
await template.To("[email protected]").SendAsync();
await template.To("[email protected]").SendAsync();
//await template.SaveTemplateAsync(emlFilePath);

If you want to download and re-use an existing email as a template, read about it in the receiver section of the project wiki.

Next Steps

To see more examples and request new features, head over to https://github.com/danzuep/MailKitSimplified.

If you want to see more like this, keep reading about Receiving Emails In C#/.NET!


Similar Articles