Send Email Using Templates In ASP.NET Core

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

  1. Create a Simple Email Template.
  2. Configure Email Setting in ASP.NET Core Application.
  3. Read content from Email Template using StreamReader()
  4. Personalize Email Content
  5. 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).

HTML Page

Once you have created Email Templates, the Solution Explorer looks like below. (In my case, there are 5 Email Templates).

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.

HTML

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.

  1. Read the content of the Email Template.
  2. Read User Details received from the User Registration Form.
  3. Pass User Details to contents of Email Template.
  4. Replace {0}, {1}, {2} with respective values.
  5. 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.

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.

Email inbox

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