ASP.NET MVC 5 - SMTP Email Notification

This article is about sending email notification to recipient email address from within your website.

Notifications to end-users are a very crucial need for interactive web development. Popular forms of notifications in web development are emails and SMS alerts. It is essentially a responsibility of the websites (that are maintaining end-user accounts) to notify end-users about various interactions happening with their accounts, simply, to feel more secure, more aware, and more in control of their accounts with third-party products.

In today's tutorial, I will demonstrate the method of sending SMTP email notification using ASP.NET MVC5 platform.


Prerequisites

Following are some prerequisites before you proceed any further in this tutorial:

  1. Knowledge about ASP.NET MVC5.
  2. Knowledge about HTML.
  3. Knowledge about Javascript.
  4. Knowledge about AJAX.
  5. Knowledge about CSS.
  6. Knowledge about Bootstrap.
  7. Knowledge about C# programming.
  8. Knowledge about C# LINQ.
  9. Knowledge about JQuery.

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2015 Enterprise.

Let's begin now.

Step 1

Create new MVC5 web application project and name it "EmailNotification".

Step 2

I like to keep my sensitive information into resource (.resx) files instead of web.config file. So, create a "Resources/Constants/EmailInfo.resx" resource (.resx) file and ensure that "Access Modifier" of the file is "Public" as shown below i.e.

 

Since I am going to use a Gmail account as a source email address for sending email notifications, hence, I will be using "smtp.gmail.com" as my host type configuration with port "587" which are essential configuration properties for SMTP protocol. You can use "587" port for other common email host types as well. Below are the list of host type configuration for other common email host types i.e.

  1. GMAIL SMTP HOST -> smtp.gmail.com
  2. YAHOO SMTP HOST -> smtp.mail.yahoo.com
  3. HOTMAIL/LIVE SMTP HOST -> smtp.live.com
  4. OUTLOOK/Exchange Server SMTP HOST -> smtp-mail.outlook.com

In order to send email notifications from your website to end-users of your web product, you need to have a source email account. The concept is simple here, you need an email account to send a notification to another email account. The only difference is that your source email account should not be your personal account, so, it cannot be misused. For example, when you receive email notifications from your social media accounts, notice that they specifically write "do-not-reply" in the name of the email address or mention that at the end of the email notifications that not to reply to this email address. The reason is simple -- they have fixed that particular email account for sending notifications only, according to the actions you perform on their websites. So, here below are the mandatory configuration properties within your code to configure your source email address for sending email notifications to the end-users i.e.:

  1. FROM_EMAIL_ACCOUNT
  2. FROM_EMAIL_PASSWORD
  3. SMTP_HOST_TYPE
  4. SMTP_PORT

Step 3

Create the following list of properties within the "Resources/Constants/EmailInfo.resx" resource (.resx) file as shown below, i.e.


Notice in the above that I have left "FROM_EMAIL_ACCOUNT" and "FROM_EMAIL_PASSWORD" configuration properties empty i.e.:


These are your source email account email addresses and passwords. You need to update that while executing this tutorial.

Step 4

Now, Open "Views\Shared\_Layout.cshtml" page and replace following code in it:

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
  6.     <title>@ViewBag.Title</title>  
  7.     @Styles.Render("~/Content/css")  
  8.     @Scripts.Render("~/bundles/modernizr")  
  9.   
  10.     <!-- Font Awesome -->  
  11.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />  
  12.   
  13. </head>  
  14. <body>  
  15.     <div class="navbar navbar-inverse navbar-fixed-top">  
  16.         <div class="container">  
  17.             <div class="navbar-header">  
  18.                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
  19.                     <span class="icon-bar"></span>  
  20.                     <span class="icon-bar"></span>  
  21.                     <span class="icon-bar"></span>  
  22.                 </button>  
  23.             </div>  
  24.         </div>  
  25.     </div>  
  26.     <div class="container body-content">  
  27.         @RenderBody()  
  28.         <hr />  
  29.         <footer>  
  30.             <center>  
  31.                 <p><strong>Copyright © @DateTime.Now.Year - <a href="http://wwww.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>  
  32.             </center>  
  33.         </footer>  
  34.     </div>  
  35.   
  36.     @*Scripts*@  
  37.     @Scripts.Render("~/bundles/jquery")  
  38.   
  39.     @Scripts.Render("~/bundles/jqueryval")  
  40.     @Scripts.Render("~/bundles/bootstrap")  
  41.   
  42.     <!-- Custom Form -->  
  43.     @Scripts.Render("~/scripts/custom-form")  
  44.   
  45.     @RenderSection("scripts", required: false)  
  46. </body>  
  47. </html> 

In the above code, I have simply created a basic layout design for the web pages and include necessary references to the require libraries.

Step 5

Now, create "Models\EmailNotifyViewModel.cs" file and replace following code in this file:

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="EmailNotifyViewModel.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace EmailNotification.Models  
  9. {  
  10.     using System.Collections.Generic;  
  11.     using System.ComponentModel.DataAnnotations;  
  12.   
  13.     /// <summary>  
  14.     /// Email notification view model class.  
  15.     /// </summary>  
  16.     public class EmailNotifyViewModel  
  17.     {  
  18.         #region Properties  
  19.   
  20.         /// <summary>  
  21.         /// Gets or sets to email address.  
  22.         /// </summary>  
  23.         [Required]  
  24.         [Display(Name = "To (Email Address)")]  
  25.         public string ToEmail { getset; }  
  26.  
  27.         #endregion  
  28.     }  

In the above code, I have simply created my View Model to attach it with the corresponding UI.

Step 6

Now, create "Controllers\EmailNotifyController.cs.cs" file and replace following code in it:

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="EmailNotifyController.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace EmailNotification.Controllers  
  9. {  
  10.     using System;  
  11.     using System.Collections.Generic;  
  12.     using System.Linq;  
  13.     using System.Web;  
  14.     using System.Web.Mvc;  
  15.     using Models;  
  16.     using System.Threading.Tasks;  
  17.     using System.Net.Mail;  
  18.     using Resources.Constants;  
  19.     using System.Net;  
  20.   
  21.     /// <summary>  
  22.     /// Email notification controller class.  
  23.     /// </summary>  
  24.     public class EmailNotifyController : Controller  
  25.     {  
  26.         #region Index view method.  
  27.  
  28.         #region Get: /EmailNotify/Index method.  
  29.   
  30.         /// <summary>  
  31.         /// Get: /EmailNotify/Index method.  
  32.         /// </summary>          
  33.         /// <returns>Return index view</returns>  
  34.         public ActionResult Index()  
  35.         {  
  36.             try  
  37.             {  
  38.             }  
  39.             catch (Exception ex)  
  40.             {  
  41.                 // Info  
  42.                 Console.Write(ex);  
  43.             }  
  44.   
  45.             // Info.  
  46.             return this.View();  
  47.         }  
  48.  
  49.         #endregion  
  50.  
  51.         #region POST: /EmailNotify/Index  
  52.   
  53.         /// <summary>  
  54.         /// POST: /EmailNotify/Index  
  55.         /// </summary>  
  56.         /// <param name="model">Model parameter</param>  
  57.         /// <returns>Return - Response information</returns>  
  58.         [HttpPost]  
  59.         [AllowAnonymous]  
  60.         [ValidateAntiForgeryToken]  
  61.         public async Task<ActionResult> Index(EmailNotifyViewModel model)  
  62.         {  
  63.             try  
  64.             {  
  65.                 // Verification  
  66.                 if (ModelState.IsValid)  
  67.                 {  
  68.                     // Initialization.  
  69.                     string emailMsg = "Dear " + model.ToEmail + ", <br /><br /> Thist is test <b style='color: red'> Notification </b> <br /><br /> Thanks & Regards, <br />Asma Khalid";  
  70.                     string emailSubject = EmailInfo.EMAIL_SUBJECT_DEFAUALT + " Test";  
  71.   
  72.                     // Sending Email.  
  73.                     await this.SendEmailAsync(model.ToEmail, emailMsg, emailSubject);  
  74.   
  75.   
  76.                     // Info.  
  77.                     return this.Json(new { EnableSuccess = true, SuccessTitle = "Success", SuccessMsg = "Notification has been sent successfully! to '" + model.ToEmail + "' Check your email." });  
  78.                 }  
  79.             }  
  80.             catch (Exception ex)  
  81.             {  
  82.                 // Info  
  83.                 Console.Write(ex);  
  84.   
  85.                 // Info  
  86.                 return this.Json(new { EnableError = true, ErrorTitle = "Error", ErrorMsg = ex.Message });  
  87.             }  
  88.   
  89.             // Info  
  90.             return this.Json(new { EnableError = true, ErrorTitle = "Error", ErrorMsg = "Something goes wrong, please try again later" });  
  91.         }  
  92.  
  93.         #endregion  
  94.  
  95.         #endregion  
  96.  
  97.         #region Helper  
  98.  
  99.         #region Send Email method.  
  100.   
  101.         /// <summary>  
  102.         ///  Send Email method.  
  103.         /// </summary>  
  104.         /// <param name="email">Email parameter</param>  
  105.         /// <param name="msg">Message parameter</param>  
  106.         /// <param name="subject">Subject parameter</param>  
  107.         /// <returns>Return await task</returns>  
  108.         public async Task<bool> SendEmailAsync(string email, string msg, string subject = "")  
  109.         {  
  110.             // Initialization.  
  111.             bool isSend = false;  
  112.   
  113.             try  
  114.             {  
  115.                 // Initialization.  
  116.                 var body = msg;  
  117.                 var message = new MailMessage();  
  118.   
  119.                 // Settings.  
  120.                 message.To.Add(new MailAddress(email));  
  121.                 message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);  
  122.                 message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;  
  123.                 message.Body = body;  
  124.                 message.IsBodyHtml = true;  
  125.   
  126.                 using (var smtp = new SmtpClient())  
  127.                 {  
  128.                     // Settings.  
  129.                     var credential = new NetworkCredential  
  130.                     {  
  131.                         UserName = EmailInfo.FROM_EMAIL_ACCOUNT,  
  132.                         Password = EmailInfo.FROM_EMAIL_PASSWORD  
  133.                     };  
  134.   
  135.                     // Settings.  
  136.                     smtp.Credentials = credential;  
  137.                     smtp.Host = EmailInfo.SMTP_HOST_GMAIL;  
  138.                     smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);  
  139.                     smtp.EnableSsl = true;  
  140.   
  141.                     // Sending  
  142.                     await smtp.SendMailAsync(message);  
  143.   
  144.                     // Settings.  
  145.                     isSend = true;  
  146.                 }  
  147.             }  
  148.             catch (Exception ex)  
  149.             {  
  150.                 // Info  
  151.                 throw ex;  
  152.             }  
  153.   
  154.             // info.  
  155.             return isSend;  
  156.         }  
  157.  
  158.         #endregion  
  159.  
  160.         #endregion  
  161.     }  

The above piece of code consists of both HttpGet & HttpPost Index(...) methods and the key helper method SendEmailAsync(...). HttpGet Index(...) method will return the details of the Index view page. While HttpPost Index(...) method will capture end-user inputs which is an email address for the recipient where I want to send my email notification. Notice that in HttpPost Index(...) method, I have composed a fix email notification message:

  1. // Initialization.  
  2. string emailMsg = "Dear " + model.ToEmail + ", <br /><br /> Thist is test <b style='color: red'> Notification </b> <br /><br /> Thanks & Regards, <br />Asma Khalid"

You can compose your own email notification message, static or dynamic; it's completely up to you.

Now, let's look closely at the key helper method "SendEmailSync(...)" which will actually send the email notification to the recipient email address which I have obtained from the end-user:

  1. #region Send Email method.  
  2.   
  3. /// <summary>  
  4. ///  Send Email method.  
  5. /// </summary>  
  6. /// <param name="email">Email parameter</param>  
  7. /// <param name="msg">Message parameter</param>  
  8. /// <param name="subject">Subject parameter</param>  
  9. /// <returns>Return await task</returns>  
  10. public async Task<bool> SendEmailAsync(string email, string msg, string subject = "")  
  11. {  
  12.     // Initialization.  
  13.     bool isSend = false;  
  14.   
  15.     try  
  16.     {  
  17.         // Initialization.  
  18.         var body = msg;  
  19.         var message = new MailMessage();  
  20.   
  21.         // Settings.  
  22.         message.To.Add(new MailAddress(email));  
  23.         message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);  
  24.         message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;  
  25.         message.Body = body;  
  26.         message.IsBodyHtml = true;  
  27.   
  28.         using (var smtp = new SmtpClient())  
  29.         {  
  30.             // Settings.  
  31.             var credential = new NetworkCredential  
  32.             {  
  33.                 UserName = EmailInfo.FROM_EMAIL_ACCOUNT,  
  34.                 Password = EmailInfo.FROM_EMAIL_PASSWORD  
  35.             };  
  36.   
  37.             // Settings.  
  38.             smtp.Credentials = credential;  
  39.             smtp.Host = EmailInfo.SMTP_HOST_GMAIL;  
  40.             smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);  
  41.             smtp.EnableSsl = true;  
  42.   
  43.             // Sending  
  44.             await smtp.SendMailAsync(message);  
  45.   
  46.             // Settings.  
  47.             isSend = true;  
  48.         }  
  49.     }  
  50.     catch (Exception ex)  
  51.     {  
  52.         // Info  
  53.         throw ex;  
  54.     }  
  55.   
  56.     // info.  
  57.     return isSend;  
  58. }  
  59.  
  60. #endregion 

In the above code, I am using "SmtpClient" to send email notification to the recipient email address. I first set essential configuration for message body with recipient email address:

  1. // Initialization.  
  2. var body = msg;  
  3. var message = new MailMessage();  
  4.   
  5. // Settings.  
  6. message.To.Add(new MailAddress(email));  
  7. message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);  
  8. message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;  
  9. message.Body = body;  
  10. message.IsBodyHtml = true

Next, I have configured my source email address account with host type & port settings and finally, send the email notification to the recipient:

  1. using (var smtp = new SmtpClient())  
  2. {  
  3.     // Settings.  
  4.     var credential = new NetworkCredential  
  5.     {  
  6.         UserName = EmailInfo.FROM_EMAIL_ACCOUNT,  
  7.         Password = EmailInfo.FROM_EMAIL_PASSWORD  
  8.     };  
  9.   
  10.     // Settings.  
  11.     smtp.Credentials = credential;  
  12.     smtp.Host = EmailInfo.SMTP_HOST_GMAIL;  
  13.     smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);  
  14.     smtp.EnableSsl = true;  
  15.   
  16.     // Sending  
  17.     await smtp.SendMailAsync(message);  
  18.   
  19.     // Settings.  
  20.     isSend = true;  

Step 7

To tie everything together, let's create the UI ajax form. So, create "Views\EmailNotify\Index.cshtml" file and replace following code in it i.e.

  1. @using EmailNotification.Models  
  2.   
  3. @model EmailNotification.Models.EmailNotifyViewModel  
  4.   
  5. @{  
  6.     ViewBag.Title = "ASP.NET MVC5: SMTP Email Notification";  
  7. }  
  8.   
  9.   
  10. <div class="row">  
  11.     <div class="panel-heading">  
  12.         <div class="col-md-8">  
  13.             <h3>  
  14.                 <i class="fa fa-file-text-o"></i>  
  15.                 <span>ASP.NET MVC5: SMTP Email Notification</span>  
  16.             </h3>  
  17.         </div>  
  18.     </div>  
  19. </div>  
  20.   
  21. <div class="row">  
  22.     <section class="col-md-4 col-md-push-4">  
  23.         @using (Ajax.BeginForm("Index", "EmailNotify", new AjaxOptions { HttpMethod = "POST"OnSuccess = "onEmailNotifySuccess" }, new { @id = "EmailNotifyformId", @class = "form-horizontal"role = "form" }))  
  24.         {  
  25.             @Html.AntiForgeryToken()  
  26.   
  27.             <div class="well bs-component">  
  28.                 <br />  
  29.   
  30.                 <div class="row">  
  31.                     <div class="col-md-12 col-md-push-2">  
  32.                         <div class="form-group">  
  33.                             <div class="col-md-10 col-md-pull-1">  
  34.                                 @Html.TextBoxFor(m => m.ToEmail, new { placeholder = Html.DisplayNameFor(m => m.ToEmail), @class = "form-control" })  
  35.                                 @Html.ValidationMessageFor(m => m.ToEmail, "", new { @class = "text-danger custom-danger" })  
  36.                             </div>  
  37.                         </div>  
  38.   
  39.                         <div class="form-group">  
  40.                             <div class="col-md-18">  
  41.                             </div>  
  42.                         </div>  
  43.   
  44.                         <div class="form-group">  
  45.                             <div class="col-md-4 col-md-push-2">  
  46.                                 <div>  
  47.                                     <button type="submit"  
  48.                                             class="btn btn-warning"  
  49.                                             value="Process">  
  50.   
  51.                                         <span class="ladda-label">Send Notification</span>  
  52.                                     </button>  
  53.                                 </div>  
  54.                             </div>  
  55.                         </div>  
  56.                     </div>  
  57.                 </div>  
  58.             </div>  
  59.         }  
  60.     </section>  
  61. </div> 

In the above code, I have created a simple Razor AJAX form and unobtrusive form validation.

Step 8

Now, create "Scripts\custom-form.js"file and replace following code in it:

  1. $(document).ready(function () {  
  2.     $("#EmailNotifyformId").submit(function (event) {  
  3.         var dataString;  
  4.         event.preventDefault();  
  5.         event.stopImmediatePropagation();  
  6.         var action = $("#EmailNotifyformId").attr("action");  
  7.   
  8.         // Setting.  
  9.         dataString = new FormData($("#EmailNotifyformId").get(0));  
  10.         contentType = false;  
  11.         processData = false;  
  12.   
  13.         $.ajax({  
  14.             type: "POST",  
  15.             url: action,  
  16.             data: dataString,  
  17.             dataType: "json",  
  18.             contentType: contentType,  
  19.             processData: processData,  
  20.             success: function (result) {  
  21.                 // Result.  
  22.                 onEmailNotifySuccess(result);  
  23.             },  
  24.             error: function (jqXHR, textStatus, errorThrown) {  
  25.                 //do your own thing  
  26.                 alert("fail");  
  27.             }  
  28.         });  
  29.   
  30.     }); //end .submit()  
  31. });  
  32.   
  33. var onEmailNotifySuccess = function (result) {  
  34.     if (result.EnableError) {  
  35.         // Setting.  
  36.         alert(result.ErrorMsg);  
  37.     }  
  38.     else if (result.EnableSuccess) {  
  39.         // Setting.  
  40.         alert(result.SuccessMsg);  
  41.   
  42.         // Resetting form.  
  43.         $('#EmailNotifyformId').get(0).reset();  
  44.     }  

The above code is essential part of razor ajax form, I will not go into its details.

Step 9

Now, execute the project and you will be able to see the following:


Type recipient email address and press "Send Notification" button, you will see "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at" error i.e.


There are two main reasons for the above error:

  1. I am using localhost and not SSL enabled certificate i.e. "https://".
  2. I am using Gmail account as source email address and Gmail account explicitly requires access permission for logins outside Gmail client.

Even if you enable SSL certificate, you will still see the error because of Gmail explicit permission settings. The above error happens only for Gmail not by other providers. Gmail will also send you an email about sign-in attempts as shown below:

 


 

So, in order to enable access permission for gmail account, perform the following steps:

  1. Login to your Gmail account from the web browser.
  2. Go to "https://myaccount.google.com/lesssecureapps" link.
  3. Turn "Allow less secure apps" property "ON".

As shown below i.e.


Now, execute the project and type recipient email address and press "Send Notification" button, you will see success message as shown below:


Check the recipient account to verify the notification message and your recipient has received the email notification as shown below:



Conclusion

In this article, we learned  how to send an email notification to the recipient email address from our website. We leamed about SmtpClient library and different configuration settings in order to send the email notification. We saw SMTP protocol host types for different common email providers. You also learned to resolve the source Gmaill account sign-in issue outside the Gmail client and allow sign-in access to less secure apps for your source Gmail account.