Every app will interact with emails in a way or another, and sending emails is a core functionality of any app, you as a developer will be required to integrate this functionality in the most robust and efficient way possible that follows clean architecture principles.
we should also mention that we intend to switch implementation often based on the software requirement, so we need to be able to respond to this quickly and efficiently.
so starting from the bottom, how do we send emails?
How do emails work?
we are not going to talk in detail here, there are plenty of resources to know more about this in-depth. we just gonna scratch the surface.
just like the web with HTTP, emails also have protocol standards:
- SMTP: Simple Mail Transfer Protocol.
- IMAP: Internet Message Access Protocol.
- POP: Post Office Protocol
these three protocols are the most used ones to handle all email-related actions, for sending, retrieving, and managing electronic mails.
the one that we are interested in is SMTP, this protocol is the one responsible for defining the email sending functionality.
all we need are servers that talk SMTP, we send the email message to the server then based on the message content, the server will figure the recipient SMTP server and send the message to it.
do I need to build an SMTP server to be able to send emails?
no, but you can build your own server, it is difficult but not impossible, what we do is we use services that give you pre-build SMTP servers, like Gmail, Outlook, AmazonSES, Socketlabs, and many others.
for example, in development, you may start by using your Outlook account to send emails through the Microsoft Outlook SMTP server, which will not be an ideal solution for production apps, but it is ok while we are in development, as long you not going to send thousands of emails 😅.
so how do I connect to the server to send the emails?
if you are going to use Outlook or Gmail they have their SMTP server connection configuration available online on their sites, for instance, Gmail SMTP server configurations are:
Server host | smtp.gmail.com |
Port | 587 |
Requires SSL | Yes |
and you need to provide network credentials which are your Gmail login info.
for the other services like AmazonSES, Socketlabs, they will provide you with their server connection configuration, once you have it, then it is simple, you just need an SMTP client to send the email messages, you even can send the email with the telnet command in the Command Prompt.
C# SmtpClient
to send emails with C# is very simple we use the SmtpClient class, this class give us the functionally to send emails using the SMTP protocol, all we need to do is to create an instance of the SmtpClient class and supply the message content and then we send the email, here is a code example:
// 1- we need to define our server connection configuration.
var host = "smtp.gmail.com";
var port = 587;
var credentials = new NetworkCredential("your-gmail-email", "password");
// 2- create the SmtpClient instance, and set the server connection configuration.
using var smtpClient = new SmtpClient
{
Host = host,
Port = port,
EnableSsl = true,
Credentials = credentials,
};
// 3- create the email message
var emailMessage = new MailMessage
{
From = new MailAddress("[email protected]"),
Subject = "your email subject",
Body = "<p>your email body</p>",
IsBodyHtml = true,
};
emailMessage.To.Add(new MailAddress("[email protected]"));
// 4- send the email message using the smtp client
await smtpClient.SendMailAsync(emailMessage);
as we can see the logic is very simple and straightforward, but, you not going to use this in your code, in a matter of fact the SmtpClient class will be deprecated, Microsoft is not recommending using this class anymore. they recommend using MailKit instead.
now think about it for a second, what about the apps that use the SmtpClient heavily in their code, how they should move the logic to Mailkit or any other library without breaking or changing the internal implementation.
and that is what this article is about, how can we send emails in C# the right way? so that it doesn’t matter what implementation we use for sending the emails, because we will decouple the app from the email sending logic and make our code clean.
so how should we do this?
Clean architecture & the email sender
as you can see in the diagram above we hide the actual logic for sending emails three layers deep, this will give us a complete decoupling of email sending logic from our app logic, so that any changes we make will have no impact.
let’s break it down:
1- EmailSender:
the email sender is the high-level component that you will be interacting with within your app code, it contains the email sending commands and it is the place where we compose our email messages, for example,
- if you are using CQRS, it will be the commands like
– “SendUserConfirmationEmailCommand”,
– “SendUserPasswordResetEmailCommand”,
– etc, - or if you implementing onion architecture it will be an interface with functions like
– “SendUserConfirmationEmail()”,
– “SendUserPasswordResetEmail()”
– etc
so that inside the command handler of the function implementation, you will take the inputs like the user instance, and action link, and you will use these inputs to compose an email message, with a “To”, “Subject”, “Body” etc, and then we will take the message and pass it to the EmailService.
2- EmailService
the email service has a single responsibility, take the email message and pass it to the proper email provider (SmtpClient, MailKit, etc). it has one function “Send()” with an input which is the email message, and returns the sending result.
also, our email service should be configured globally in the app generic host configuration.
Email.Net
what we have seen above is exactly how I build all of my apps, and repeating the same logic for all the apps is not a good practice, so what I have done is I have created a package that implements this architecture, called Email.Net.
when you install it you will have access to the email service, with the “IEmailService” interface containing the “Send()” function. you can check the Email.Net Github page for more details on how it works and complete documentation on the Wiki page.
for a better explanation, I have created two ASP Core API projects that use Email.Net, one using CQRS, and the second, using onion architecture, you can find the source code of the blog post on Github here.
the two project samples will process the same case which is sending a password reset email to the user requesting the reset.
1- configuration
let’s first have a look at how we configure the package, to enable the centralized configuration concept.
Email.Net allows you to do all the configuration at the service registration level, with the option to register all the Email Providers you want to use, for example here we will be using SMTP with the SmtpClient, and Sokectlabs, and you can add more if you want.
now if you want to change the Email provider all you need to do is to set the “options.DefaultEmailDeliveryProvider” to the name of the EDP you are interested in, and that it, you don’t have to change any code anywhere.
2- EmailSender:
as you can see in the code example above, the email sender responsibility is to hide the logic of composing the email message, so that our code doesn’t have any interaction with the email logic.
once we are done composing the email message we pass it to the email service, which the email sender has a dependency on it. then based on the configuration of the Email.Net it will use the proper email provider to send the email message.
as I said there is complete documentation on how you can use the package, so check out the Github page, and if you like it give it a star ⭐️ 😉
I hope this was help full, if you have any questions don’t hesitate to leave a comment, and if you want me to explain even more just ask 😊
hello
thank you for your efforts, I have a question the different email providers are already added in code ??? do I need to add logic for email providers just use the code and the code will determine the provider and send the code? i read the github page I couldn’t find this info.
Hello,
you need to add the provider, first, you install Email.NET, then based on the provider you will be using, say for example you will be using SMTP, then you install Email.Net.MailKit, then you configure the provider for more details you can check the wiki page in GitHub, and to use SMTP with MailKit check out this link: https://github.com/YoussefSell/Email.Net/tree/master/src/EmailDeliveryProviders/Email.Net.MailKit