Header Ads

ASP.NET MVC5: SMTP Email Notification

Notifications to end-users are very crucial demand of interactive web development. Popular forms of notifications in web development are "Emails & SMS alerts". It is essentially a responsibility of the websites (that are especially maintaining end-user accounts) to notify end-users about various interactive happening done 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 SMTP email notification sending 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.

Download Link

Let's begin now.

1) Create new MVC5 web application project and name it "EmailNotification".
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 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 email address or mention that at the end of the email notifications that not to reply to this email address. The reason is simple that, 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
3) Create 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 address and password. You need to update that while executing this tutorial.

4) Now, Open "Views\Shared\_Layout.cshtml" page and replace following code in it i.e.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <center>
                <p><strong>Copyright &copy; @DateTime.Now.Year - <a href="http://wwww.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>
            </center>
        </footer>
    </div>

    @*Scripts*@
    @Scripts.Render("~/bundles/jquery")

    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/bootstrap")

    <!-- Custom Form -->
    @Scripts.Render("~/scripts/custom-form")

    @RenderSection("scripts", required: false)
</body>
</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.

5) Now, create "Models\EmailNotifyViewModel.cs" file and replace following code in this file i.e.

//-----------------------------------------------------------------------
// <copyright file="EmailNotifyViewModel.cs" company="None">
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.
// </copyright>
// <author>Asma Khalid</author>
//-----------------------------------------------------------------------

namespace EmailNotification.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    /// <summary>
    /// Email notification view model class.
    /// </summary>
    public class EmailNotifyViewModel
    {
        #region Properties

        /// <summary>
        /// Gets or sets to email address.
        /// </summary>
        [Required]
        [Display(Name = "To (Email Address)")]
        public string ToEmail { get; set; }

        #endregion
    }
}

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

6) Now, create "Controllers\EmailNotifyController.cs.cs" file and replace following code in it i.e.

//-----------------------------------------------------------------------
// <copyright file="EmailNotifyController.cs" company="None">
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.
// </copyright>
// <author>Asma Khalid</author>
//-----------------------------------------------------------------------

namespace EmailNotification.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Models;
    using System.Threading.Tasks;
    using System.Net.Mail;
    using Resources.Constants;
    using System.Net;

    /// <summary>
    /// Email notification controller class.
    /// </summary>
    public class EmailNotifyController : Controller
    {
        #region Index view method.

        #region Get: /EmailNotify/Index method.

        /// <summary>
        /// Get: /EmailNotify/Index method.
        /// </summary>        
        /// <returns>Return index view</returns>
        public ActionResult Index()
        {
            try
            {
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);
            }

            // Info.
            return this.View();
        }

        #endregion

        #region POST: /EmailNotify/Index

        /// <summary>
        /// POST: /EmailNotify/Index
        /// </summary>
        /// <param name="model">Model parameter</param>
        /// <returns>Return - Response information</returns>
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Index(EmailNotifyViewModel model)
        {
            try
            {
                // Verification
                if (ModelState.IsValid)
                {
                    // Initialization.
                    string emailMsg = "Dear " + model.ToEmail + ", <br /><br /> Thist is test <b style='color: red'> Notification </b> <br /><br /> Thanks & Regards, <br />Asma Khalid";
                    string emailSubject = EmailInfo.EMAIL_SUBJECT_DEFAUALT + " Test";

                    // Sending Email.
                    await this.SendEmailAsync(model.ToEmail, emailMsg, emailSubject);


                    // Info.
                    return this.Json(new { EnableSuccess = true, SuccessTitle = "Success", SuccessMsg = "Notification has been sent successfully! to '" + model.ToEmail + "' Check your email." });
                }
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);

                // Info
                return this.Json(new { EnableError = true, ErrorTitle = "Error", ErrorMsg = ex.Message });
            }

            // Info
            return this.Json(new { EnableError = true, ErrorTitle = "Error", ErrorMsg = "Something goes wrong, please try again later" });
        }

        #endregion

        #endregion

        #region Helper

        #region Send Email method.

        /// <summary>
        ///  Send Email method.
        /// </summary>
        /// <param name="email">Email parameter</param>
        /// <param name="msg">Message parameter</param>
        /// <param name="subject">Subject parameter</param>
        /// <returns>Return await task</returns>
        public async Task<bool> SendEmailAsync(string email, string msg, string subject = "")
        {
            // Initialization.
            bool isSend = false;

            try
            {
                // Initialization.
                var body = msg;
                var message = new MailMessage();

                // Settings.
                message.To.Add(new MailAddress(email));
                message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);
                message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;
                message.Body = body;
                message.IsBodyHtml = true;

                using (var smtp = new SmtpClient())
                {
                    // Settings.
                    var credential = new NetworkCredential
                    {
                        UserName = EmailInfo.FROM_EMAIL_ACCOUNT,
                        Password = EmailInfo.FROM_EMAIL_PASSWORD
                    };

                    // Settings.
                    smtp.Credentials = credential;
                    smtp.Host = EmailInfo.SMTP_HOST_GMAIL;
                    smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);
                    smtp.EnableSsl = true;

                    // Sending
                    await smtp.SendMailAsync(message);

                    // Settings.
                    isSend = true;
                }
            }
            catch (Exception ex)
            {
                // Info
                throw ex;
            }

            // info.
            return isSend;
        }

        #endregion

        #endregion
    }
}

The above piece of code consist 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 i.e.

// Initialization.
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, its 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 i.e.

        #region Send Email method.

        /// <summary>
        ///  Send Email method.
        /// </summary>
        /// <param name="email">Email parameter</param>
        /// <param name="msg">Message parameter</param>
        /// <param name="subject">Subject parameter</param>
        /// <returns>Return await task</returns>
        public async Task<bool> SendEmailAsync(string email, string msg, string subject = "")
        {
            // Initialization.
            bool isSend = false;

            try
            {
                // Initialization.
                var body = msg;
                var message = new MailMessage();

                // Settings.
                message.To.Add(new MailAddress(email));
                message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);
                message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;
                message.Body = body;
                message.IsBodyHtml = true;

                using (var smtp = new SmtpClient())
                {
                    // Settings.
                    var credential = new NetworkCredential
                    {
                        UserName = EmailInfo.FROM_EMAIL_ACCOUNT,
                        Password = EmailInfo.FROM_EMAIL_PASSWORD
                    };

                    // Settings.
                    smtp.Credentials = credential;
                    smtp.Host = EmailInfo.SMTP_HOST_GMAIL;
                    smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);
                    smtp.EnableSsl = true;

                    // Sending
                    await smtp.SendMailAsync(message);

                    // Settings.
                    isSend = true;
                }
            }
            catch (Exception ex)
            {
                // Info
                throw ex;
            }

            // info.
            return isSend;
        }

        #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 i.e.

                // Initialization.
                var body = msg;
                var message = new MailMessage();

                // Settings.
                message.To.Add(new MailAddress(email));
                message.From = new MailAddress(EmailInfo.FROM_EMAIL_ACCOUNT);
                message.Subject = !string.IsNullOrEmpty(subject) ? subject : EmailInfo.EMAIL_SUBJECT_DEFAUALT;
                message.Body = body;
                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 i.e.

                using (var smtp = new SmtpClient())
                {
                    // Settings.
                    var credential = new NetworkCredential
                    {
                        UserName = EmailInfo.FROM_EMAIL_ACCOUNT,
                        Password = EmailInfo.FROM_EMAIL_PASSWORD
                    };

                    // Settings.
                    smtp.Credentials = credential;
                    smtp.Host = EmailInfo.SMTP_HOST_GMAIL;
                    smtp.Port = Convert.ToInt32(EmailInfo.SMTP_PORT_GMAIL);
                    smtp.EnableSsl = true;

                    // Sending
                    await smtp.SendMailAsync(message);

                    // Settings.
                    isSend = true;
                }

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.

@using EmailNotification.Models

@model EmailNotification.Models.EmailNotifyViewModel

@{
    ViewBag.Title = "ASP.NET MVC5: SMTP Email Notification";
}


<div class="row">
    <div class="panel-heading">
        <div class="col-md-8">
            <h3>
                <i class="fa fa-file-text-o"></i>
                <span>ASP.NET MVC5: SMTP Email Notification</span>
            </h3>
        </div>
    </div>
</div>

<div class="row">
    <section class="col-md-4 col-md-push-4">
        @using (Ajax.BeginForm("Index", "EmailNotify", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onEmailNotifySuccess" }, new { @id = "EmailNotifyformId", @class = "form-horizontal", role = "form" }))
        {
            @Html.AntiForgeryToken()

            <div class="well bs-component">
                <br />

                <div class="row">
                    <div class="col-md-12 col-md-push-2">
                        <div class="form-group">
                            <div class="col-md-10 col-md-pull-1">
                                @Html.TextBoxFor(m => m.ToEmail, new { placeholder = Html.DisplayNameFor(m => m.ToEmail), @class = "form-control" })
                                @Html.ValidationMessageFor(m => m.ToEmail, "", new { @class = "text-danger custom-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-18">
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-4 col-md-push-2">
                                <div>
                                    <button type="submit"
                                            class="btn btn-warning"
                                            value="Process">

                                        <span class="ladda-label">Send Notification</span>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        }
    </section>
</div>

In the above code, I have created a simple razor ajax form and unobtrusive form validation.

8) Now, create "Scripts\custom-form.js"file and replace following code in it i.e.

$(document).ready(function () {
    $("#EmailNotifyformId").submit(function (event) {
        var dataString;
        event.preventDefault();
        event.stopImmediatePropagation();
        var action = $("#EmailNotifyformId").attr("action");

        // Setting.
        dataString = new FormData($("#EmailNotifyformId").get(0));
        contentType = false;
        processData = false;

        $.ajax({
            type: "POST",
            url: action,
            data: dataString,
            dataType: "json",
            contentType: contentType,
            processData: processData,
            success: function (result) {
                // Result.
                onEmailNotifySuccess(result);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                //do your own thing
                alert("fail");
            }
        });

    }); //end .submit()
});

var onEmailNotifySuccess = function (result) {
    if (result.EnableError) {
        // Setting.
        alert(result.ErrorMsg);
    }
    else if (result.EnableSuccess) {
        // Setting.
        alert(result.SuccessMsg);

        // Resetting form.
        $('#EmailNotifyformId').get(0).reset();
    }
}

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

9) Now, execute the project and you will be able to see following i.e.

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 i.e.
  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 login 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 email about sign-in attempt as shown below i.e.


So, in order to enable access permission for gmail account, perform following steps i .e.
  1. Login to your gmail account from 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 i.e.


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


Conclusion

In this article, you will learn about sending email notification to recipient email address from within your website. You will learn about SmtpClient library different configuration settings in order to send email notification. You will also learn about SMTP protocol host types for different common email provider. You will also learn to resolve source gmail account sign-in issue outside gmail client and allow sign-in access to less secure apps for your source gmail account.

No comments