In this article, we will discuss how to send emails using a Template file in ASP.NET Core Application. Sending emails using a Template file is similar to sending emails using plain text. The only difference is that now, the source of the content is a text file rather than direct content for email.
If you don’t know how to send email in ASP.NET Core applications, please refer to my previous article Configure Email Service In ASP.NET Core Using MailKit. Let's assume, we have already configured the email service in the ASP.NET Core application.
Milestones
- Create a Simple Email Template.
- Configure Email Setting in ASP.NET Core Application.
- Read content from Email Template using StreamReader()
- Personalize Email Content
- Send Email to User
Creating a simple email template
We will keep the template file separate so that we can change the file design and content anytime. Let's keep these template files under wwwroot => Templates => EmailTemplate.
Step 1. For this, create a new folder named Templates under the wwwroot folder.
Step 2. Create a new folder named Email Template under the Templates folder.
Step 3. Add a new Item in the Email Template (right-click on Email Template folder >> add New Item).
Step 4. Select ASP.NET Core and then HTML Page.
Step 5. Set a name for the HTML file. In my case, I have named it Welcome_EmailTemplate.html (But I will be using Confirm_Account_Registration.htm for demo purposes whose design is the same with a different file name).
Once you have created Email Templates, the Solution Explorer looks like below. (In my case, there are 5 Email Templates).
Now, you can write your own design codes using inline CSS and HTML to create Email. In my case, the template looks like this.
The code for the above sample Email Template is given below.
Code Snippet
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome Email from TCP</title>
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" valign="top" bgcolor="#ffe77b" style="background-color:#ffe77b;">
<br>
<br>
<table width="600" border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="70" align="left" valign="middle"></td>
</tr>
<tr>
<td align="left" valign="top"><img src="http://localhost:2131/Templates/EmailTemplate/images/top.png" width="600" height="13" style="display:block;"></td>
</tr>
<tr>
<td align="left" valign="top" bgcolor="#564319" style="background-color:#564319; font-family:Arial, Helvetica, sans-serif; padding:10px;">
<div style="font-size:36px; color:#ffffff;">
<b>{0}</b>
</div>
<div style="font-size:13px; color:#a29881;">
<b>{1} : ASP.NET Core Demp App</b>
</div>
</td>
</tr>
<tr>
<td align="left" valign="top" bgcolor="#ffffff" style="background-color:#ffffff;">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" valign="middle" style="padding:10px; color:#564319; font-size:28px; font-family:Georgia, 'Times New Roman', Times, serif;">
Congratulations! <small>You are registered.</small>
</td>
</tr>
</table>
<table width="95%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="40%" align="center" valign="middle" style="padding:10px;">
<img src="http://localhost:2131/Templates/EmailTemplate/images/Weak_Password.gif" width="169" height="187" style="display:block">
</td>
<td align="left" valign="middle" style="color:#525252; font-family:Arial, Helvetica, sans-serif; padding:10px;">
<div style="font-size:16px;">
Dear {2},
</div>
<div style="font-size:12px;">
Thank you for showing your interest in our website.
All you need to do is click the button below (it only takes a few seconds).
You won’t be asked to log in to your account – we're simply verifying ownership of this email address.
<hr>
<center>
<button type="button" title="Confirm Account Registration" style="background: #1b97f1">
<a href="{6}" style="font-size:22px; padding: 10px; color: #ffffff">
Confirm Email Now
</a>
</button>
</center>
</div>
</td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" valign="middle" style="padding:5px;">
<img src="http://localhost:2131/Templates/EmailTemplate/images/divider.gif" width="566" height="30">
</td>
</tr>
</table>
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" style="margin-bottom:15px;">
<tr>
<td align="left" valign="middle" style="padding:15px; font-family:Arial, Helvetica, sans-serif;">
<div style="font-size:20px; color:#564319;">
<b>Please keep your credentials confidential for future use.</b>
</div>
<div style="font-size:16px; color:#525252;">
<b>Email :</b> {2}
<br />
<b>Username :</b> {3}
<br />
<b>Password :</b> {4}
</div>
</td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="margin-bottom:10px;">
<tr>
<td align="left" valign="middle" style="padding:15px; background-color:#564319; font-family:Arial, Helvetica, sans-serif;">
<div style="font-size:20px; color:#fff;">
<b>Update your password now.</b>
</div>
<div style="font-size:13px; color:#ffe77b;">
Weak passwords get stolen and lead to hacked accounts. Celebrate World Password Day with a new, strong password.
<br>
<br>
<a href="#" style="color:#ffe77b; text-decoration:underline;">CLICK HERE</a> TO CHANGE PASSWORD
</div>
</td>
</tr>
</table>
<table width="95%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="50%" align="left" valign="middle" style="padding:10px;">
<table width="75%" border="0" cellspacing="0" cellpadding="4">
<tr>
<td align="left" valign="top" style="font-family:Verdana, Geneva, sans-serif; font-size:14px; color:#000000;">
<b>Follow Us On</b>
</td>
</tr>
<tr>
<td align="left" valign="top" style="font-family:Verdana, Geneva, sans-serif; font-size:12px; color:#000000;">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="33%" align="left" valign="middle">
<a href="https://twitter.com" title="Facebook">
<img src="http://localhost:2131/Templates/EmailTemplate/images/tweet48.png" width="48" height="48">
</a>
</td>
<td width="34%" align="left" valign="middle">
<a href="https://linkedin.com" title="Linkedin">
<img src="http://localhost:2131/Templates/EmailTemplate/images/in48.png" width="48" height="48">
</a>
</td>
<td width="33%" align="left" valign="middle">
<a href="https://facebook.com" title="Facebook">
<img src="http://localhost:2131/Templates/EmailTemplate/images/face48.png" width="48" height="48">
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td width="50%" align="left" valign="middle" style="color:#564319; font-size:11px; font-family:Arial, Helvetica, sans-serif; padding:10px;">
<b>Hours:</b> Mon-Fri 9:30-5:30, Sat. 9:30-3:00, Sun. Closed <br>
<b>Customer Support:</b> <a href="mailto:[email protected]" style="color:#564319; text-decoration:none;">[email protected]</a><br>
<br>
<b>Company Address</b><br>
Company URL: <a href="http://www.yourcompanyname.com" target="_blank" style="color:#564319; text-decoration:none;">http://www.yourcompanyname.com</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left" valign="top"><img src="http://localhost:2131/Templates/EmailTemplate/images/bot.png" width="600" height="37" style="display:block;"></td>
</tr>
</table>
<br>
<br>
</td>
</tr>
</table>
</body>
</html>
Now, our Email Template is ready.
Scenario 1. Verifying user's email ownership on registration
We need to send a confirmation email to verify the ownership of the email to the user, just after first registration with his/her email on our application.
The process is.
- Collect user details from the Registration Form.
- Register Method of Account Controller of type [HttpPost] creates a new user using the following code.
// Take user details from Registration Form
// ie. model carries data from Registration form to here
var user = new ApplicationUser
{
UserName = model.Email,
Email = model.Email
};
// CreateAsync inside UserManager creates new user
// when userdetails and password supplied.
var result = await _userManager.CreateAsync(user, model.Password);
- Generate unique code for new user details.
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
- A unique random callback is generated using the generated code and UserId.
var callbackUrl = Url.Action(
nameof(ConfirmEmail),
"Account",
new { userId = user.Id, code = code },
protocol: HttpContext.Request.Scheme
);
- Send callbackUrl to the user via email.
string Message = "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>";
// Send Email to User
await _emailSender.SendEmailAsync(model.Email, subject, messageBody);
- When a user clicks the send callback URL, he/she is sent back to the ConfirmEmail Method of Account Controller.
// Find User Details by userId
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return View("Error");
}
var result = await _userManager.ConfirmEmailAsync(user, code);
ViewData["Message"] = "Your email has been confirmed. Please Login now.";
ViewData["MessageValue"] = "1";
- This line will match the received user details and code via callback URL and set ConfirmedEmail to true in the database.
Now, during this process, if we want to send email using our custom Email Templates, we need to.
- Read the content of the Email Template.
- Read User Details received from the User Registration Form.
- Pass User Details to contents of Email Template.
- Replace {0}, {1}, {2} with respective values.
- Send an email to the user. (Using Mail Kit for now).
Reading contents from a template file
Step 1. Get Information about the web Hosting Environment where our application is running.
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly ILogger _logger;
private readonly string _externalCookieScheme;
private IHostingEnvironment _env;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IOptions<IdentityCookieOptions> identityCookieOptions,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IHostingEnvironment env)
{
_userManager = userManager;
_signInManager = signInManager;
_externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_env = env;
}
Step 2. Get the wwwroot Folder.
var webRoot = _env.WebRootPath; // Get wwwroot Folder
Step 3. Get TemplateFile located at wwwroot/Templates/EmailTemplate/Register_EmailTemplate.html
// Get TemplateFile located at wwwroot/Templates/EmailTemplate/Confirm_Account_Registration.html
var pathToFile = _env.WebRootPath
+ Path.DirectorySeparatorChar.ToString()
+ "Templates"
+ Path.DirectorySeparatorChar.ToString()
+ "EmailTemplate"
+ Path.DirectorySeparatorChar.ToString()
+ "Confirm_Account_Registration.html";
Step 4. Initialise BoduBuilder().
var builder = new BodyBuilder();
Step 5. Read the Content of the Template file using StreamReader and append it to BodyBuilder().
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}
Passing value and formatting the content of the template with Dynamic values
Step 1. Use string.Format(format item, dynamic values as parameters) In our case, {x} values in Templates are to be replaced by dynamic values.
// {0} : Subject
// {1} : Current DateTime
// {2} : Email
// {3} : Username
// {4} : Password
// {5} : Message
// {6} : callbackURL
Code Snippet
string messageBody = string.Format(builder.HtmlBody,
subject,
String.Format("{0:dddd, d MMMM yyyy}", DateTime.Now),
model.Email,
model.Email,
model.Password,
Message,
callbackUrl
);
Send Email using Mailkit
If you don’t know how to send email using Mail kit in ASP.NET Core Applications please refer to my previous blog. For now, I am skipping setting up email service.
await _emailSender.SendEmailAsync(model.Email, subject, messageBody);
// Success Message
ViewData["Message"] = $"Please confirm your account by clicking this link: <a href='{callbackUrl}' class='btn btn-primary'>Confirmation Link</a>";
ViewData["MessageValue"] = "1";
await _emailSender.SendEmailAsync(model.Email, subject, messageBody); line will send email to user email.
Code used in Register Method of Account Controller.
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action(nameof(ConfirmEmail), "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
string Message = "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>";
var webRoot = _env.WebRootPath; //get wwwroot Folder
//Get TemplateFile located at wwwroot/Templates/EmailTemplate/Register_EmailTemplate.html
var pathToFile = _env.WebRootPath
+ Path.DirectorySeparatorChar.ToString()
+ "Templates"
+ Path.DirectorySeparatorChar.ToString()
+ "EmailTemplate"
+ Path.DirectorySeparatorChar.ToString()
+ "Confirm_Account_Registration.html";
var subject = "Confirm Account Registration";
var builder = new BodyBuilder();
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}
string messageBody = string.Format(builder.HtmlBody,
subject,
String.Format("{0:dddd, d MMMM yyyy}", DateTime.Now),
model.Email,
model.Email,
model.Password,
Message,
callbackUrl
);
await _emailSender.SendEmailAsync(model.Email, subject, messageBody);
ViewData["Message"] = $"Please confirm your account by clicking this link: <a href='{callbackUrl}' class='btn btn-primary'>Confirmation Link</a>";
ViewData["MessageValue"] = "1";
_logger.LogInformation(3, "User created a new account with password.");
return RedirectToLocal(returnUrl);
}
ViewData["Message"] = $"Error creating user. Please try again later";
ViewData["MessageValue"] = "0";
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
Application Execution and Output
Step 1. Now let's rebuild the solution and run the application.
Step 2. Let's register as a New user /Account/Register.
Once we register as new users, a confirmation email is sent on the registered email. Upon checking the email inbox, we receive emails like this.
We receive the personalized email sent from the Demo ASP.NET Core Application.
Scenarios where we need Email Templates.
- Send personalized emails to all/selected users for events and news.
- Newsletter
- Notices and Calls for events
- Welcome Email to New Users.
- Automatic Monthly report to Admins and Staff.
- and many more...
Summary
So far, we have learned how to send personalized emails to users by creating Email Templates.
You may also like