In this article, we will discuss how to send emails using a Template file in ASP.NET Core Application. Sending email using 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.
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 wwwroot folder.
Step 2
Create a new folder named Email Template under Templates folder.
Step 3
Add a new Item in 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 as Welcome_EmailTemplate.html (But I will be using Confirm_Account_Registration.html 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 PASSOWORD
- </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 - I : 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 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 callbackUrl 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 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 callbackUrl and sets ConfirmedEmail to true in database.
Now, during this process, if we want to send email using our custom Email Templates, we need to
- Read content of Email Template
- Read User Details received from User Registration Form.
- Pass User Details to contents of Email Template.
- Replace {0}, {1}, {2} with respective values.
- Send email to user. (Using Mail Kit for now)
Reading Contents from 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 wwwroot Folder
- var webRoot = _env.WebRootPath;
Step 3
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";
Step 4
Initialie BoduBuilder()
- var builder = new BodyBuilder();
Step 5
Read Content of Template file using StreamReader and append to BodyBuilder()
- using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
- {
- builder.HtmlBody = SourceReader.ReadToEnd();
- }
Passing value and Formatting the Content of Template with Dynamic Values
Step 1
use string.Format(format item, dynamic values as parameters) In our case, {x} values in Templates are to replace by dynamic values.
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);
-
- 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
-
- [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;
-
-
- 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);
- }
-
-
- return View(model);
- }
Appplication Execution and Output
Step 1
Now let's rebuild the soution and run the application.
Step 2Lets register as a New user /Account/Register
Once we register as new user, a confirmation email is sent on the registred email. Upon checking the email inbox, we receive email like this -
We receive the personalized email sent from the Demo ASP.NET Core Application.
Scenerio where we need Email Templates
- Send personalized emails to all/selected users for events and news.
- Newsletter
- Notices and Call for events
- Welcome Email to New Users.
- Automatic Monthly report to Admins and Staffs.
- and many more....
Summary
So far, we have learned how to send personalized emails to users creating Email Templates .
You may also like