Today we have multiple free options to send email from our apps. Let's review how to configure and use SendGrid and Azure to send emails from our ASP.NET Core apps and benefit from their extraordinary free plan.
Photo by Carol Jeng on Unsplash |
Long are the days that we had to use
Gmail App Passwords
to send and test emails from our apps. Today we have a plethora of
alternatives that cost nothing or close to nothing. On that category, SendGrid
offers Azure subscribers 25,000 free emails per month! So let's review how to
setup a free SendGrid account and build a simple ASP.NET website to send
emails from it.
On this post we will:
- create a SendGrid account directly in Azure
-
build a simple ASP.NET Core web app and review how to properly configure
it
- access and configure our SendGrid settings in SendGrid
- send emails using SMTP (not the RESTful API) from our console application
For a quick start, download the code from GitHub at:
github.com/hd9/aspnet-sendgrid
Creating a SendGrid account in Azure
The good news is that in case you don't have one already, you can create a
SendGrid account directly from Azure. Let's get straight to it. Open your
Azure portal and type sendgrid on the search tool bar and click on SendGrid
Accounts:
Click Add to create our account from Azure:
Enter your information on the next screen:
Review and confirm your package:
Wait until your deployment completes (it should take no more than 10 seconds). Now go back to SendGrid Accounts and you should see your new account
there:
Clicking on it would take you to the SendGrid pane showing you essential
information about your new resource:
Did you notice that Manage button? Clicking that button will take us directly
to SendGrid where we'll be able to configure out account, create api keys,
monitor our usage and a lot more.
I won't expand much in
what SendGrid offers (tldr; a lot!). For more of that, feel free to visit their website.
Configuring SendGrid
The first time you login to SendGrid, you'll be requested to confirm your
email address. After confirmation, this is the what you should see a screen
similar to the below, showing you a general overview of your account:
Creating our SMTP API Key
To be able to send emails from SendGrid, we'll have first to generate a
password. First click on Settings -> API Keys:
Choose Restricted Access:
Select Mail Send (for this demo we only need that one):
And click create. You'll be presented with your password (api key). Copy it safely:
SendGrid Configuration
With the password in hand, here's a summary about the configuration we'll
need:
- Host: smtp.sendgrid.net
- Port: 587
- Username: apikey
- Password: SG.zGNcZ-**********************
Building our App
I guess that at this point, creating an ASP.NET web app is no surprise to
anyone. But if you're new to .NET Core, please check this documentation on
how to build and run ASP.NET Core on Linux. It's a different perspective from the Visual Studio-centric approach you'll
see elsewhere. To quickly create with VS, File -> Create a new project and
select Web Application (Model-View-Controller).
Configuring our App
With the configuration in hand, let's now review how to use it. To simplify
things, I built already a simple web app that captures 2 fields: name and
email of a potential newsletter subscriber. It looks like this and is
available on GitHub:
Apart from the visual, there are a couple of things on this app that are worth
looking into. Let's start with the configuration. If you open appsettings.json
on the root of the project you will see:
"SmtpOptions": {
"Host": "<smtp>",
"Port": "587",
"Username": "<account>",
"Password": "<password>",
"FromName": "<from-name>",
"FromEmail": "<from-email>",
"EmailOverride": "<email>"
},
"EmailTemplate": {
"Subject": "[HildenCo WebStore] Welcome to our newsletter!",
"Body": "Hello {0},\nThanks for signing up for our newsletter!\n\nBest Regards,\nHildenCo."
}
"Host": "<smtp>",
"Port": "587",
"Username": "<account>",
"Password": "<password>",
"FromName": "<from-name>",
"FromEmail": "<from-email>",
"EmailOverride": "<email>"
},
"EmailTemplate": {
"Subject": "[HildenCo WebStore] Welcome to our newsletter!",
"Body": "Hello {0},\nThanks for signing up for our newsletter!\n\nBest Regards,\nHildenCo."
}
Since I already explained
how to bind that config to a class of our own, I'll not extend too much on the topic. Essentially we will:
- map the SmtpOptions configuration into a SmtpOptions class
- map the EmailTemplate config into the EmailConfig class
That mapping is done elegantly by the framework as this line from Startup.cs
shows:
cfg = configuration.Get<AppConfig>();
Inspecting cfg during debug confirms the successful binding:
Dependency Injection
Next, it's time to setup dependency injection. For our objective here,
ASP.NET's default
DependencyInjection
utility is good enough. Put the below in your
ConfigureServices method
to wire everything up:
services.AddSingleton(cfg.SmtpOptions);
services.AddSingleton(cfg.EmailTemplate);
services.AddTransient<IMailSender, MailSender>();
services.AddSingleton(cfg.EmailTemplate);
services.AddTransient<IMailSender, MailSender>();
Next, inject the dependencies needed by our Controller and our MailSender
classes:
readonly IMailSender _mailSender;
readonly ILogger<HomeController> _logger;
public HomeController(
IMailSender mailSender,
ILogger<HomeController> logger)
{
_logger = logger;
_mailSender = mailSender;
}
readonly ILogger<HomeController> _logger;
public HomeController(
IMailSender mailSender,
ILogger<HomeController> logger)
{
_logger = logger;
_mailSender = mailSender;
}
Invoking SendMail from our controller
To call MailSender from our controller, simply inject a SendMail
command
into and invoke it:
await _mailSender.Send(new SendMail
{
Name = signup.Name,
Email = signup.Email
});
{
Name = signup.Name,
Email = signup.Email
});
Our MailSender class
To finish, here's an excerpt of our MailSender class (see the
full source on GitHub):
// init our smtp client
var smtpClient = new SmtpClient
{
Host = _smtpOptions.Host,
Port = _smtpOptions.Port,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(_smtpOptions.Username, _smtpOptions.Password)
};
// init our mail message
var mail = new MailMessage
{
From = new MailAddress(_smtpOptions.FromEmail, _smtpOptions.FromName),
Subject = _tpl.Subject,
Body = string.Format(_tpl.Body, msg)
};
// send the message
await smtpClient.SendMailAsync(mail);
var smtpClient = new SmtpClient
{
Host = _smtpOptions.Host,
Port = _smtpOptions.Port,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(_smtpOptions.Username, _smtpOptions.Password)
};
// init our mail message
var mail = new MailMessage
{
From = new MailAddress(_smtpOptions.FromEmail, _smtpOptions.FromName),
Subject = _tpl.Subject,
Body = string.Format(_tpl.Body, msg)
};
// send the message
await smtpClient.SendMailAsync(mail);
Testing the App
Run the app with
Visual Studio 2019, enter a name and an email address. If all's configured correctly, you
should soon get an email in your inbox:
As well as SendGrid reporting a successful delivery:
Final Thoughts
The only remaining question is why SMTP? The advantages of using SMTP instead
of the API is that SMTP is a pretty standard protocol, works with
.NET's primitives, works with any programming language or framework and, contrary to the restful API, does not require any specific packages. SMTP also works well with containers, but I'll
leave that fore a future post. 😉
Conclusion
On this tutorial we reviewed how to create a SendGrid account directly from
Azure, we demoed how to configure it so we can send emails from our
applications. SendGrid is a great email service with a
very powerful API
that I recommend exploring and learning other topics such as creating your
own templates, using webhooks, etc. On
the future we'll revisit this example to send email from our own ASP.NET
containers in a microservice application. Keep tuned!
Source Code
As always, the source is available on GitHub.
References
See Also
- Microservices in ASP.NET
- My journey to 1 million articles read
- Adding Application Insights to your ASP.NET Core website
- Deploying Docker images to Azure App Services
- Configuration in .NET Core console applications
- Distributed caching in ASP.NET Core using Redis, MongoDB and Docker
- Monitor ASP.NET applications using Application Insights and Azure Alerts
- Building and Hosting Docker images on GitHub with GitHub Actions
- Hosting Docker images on GitHub
- How to Build and Run ASP.NET Core on Linux
- How to create a Ubuntu Desktop on Azure