Sending Automated Emails asynchronously using a C# Windows Service in conjunction with Database Email records – Part I

 

NOTE:
  1. C# windows Services are used perform long running operations on the server with limited interactivity. In a single word, they do their work without user interaction.
  2. We can start, stop, pause, and resume a windows service using Services Control Manager of operating system.
  3. These are very advantageous when it comes to perform a task on consistent basis in the server.

In this tutorial, we learn how to send automated birthday wish emails to the customers of our product. We first design our database with basic details of every customer, and of course with a Email address field. Then we create a class library to hold the classes of database interactivity and to send email asynchronously. We use ADO.Net (for this tutorial I am skipping Entity Framework implementation, which usually I prefer to interact with Database. For generating EF modules of database, kindly watch this tutorial – Click Here) with a stored procedure for database interaction (primarily to fetch email ids of customers to whom we got to send birthday wishes). Then finally we use a Windows Service (which obviously run background in the server)through which the previously created class library is accessed and async emails are send.

 

NOTE:-
  1. As usual the main concentration all along the article will be laid on “HOW TO?”
  2. The requirement mentioned in this tutorial is a basic one. To be more precise, there might be a wide range of situations where you can fit this solution. Some situations are like – Monitoring FileSystem and writing to reports, Sending Automated Newsletters to the clients, clearing up of unwanted resources in the server from time to time etc.
  3. Email module demonstrated in this requirement is an asynchronous module. That means instead of sending mail one by one, we use AsyncCallBack delegate to do the task with background threads of the system. This method uses the possible number of background threads (by default in .Net is 25, but still we can change them) to send emails simultaneously, and once a particular thread is completed it will be automatically allotted to another process. This reduces the burden of manual implementation (or monitoring) of threads, which is a sign of huge relief in thread management (which at times considered as deadlock situation).
  4. The email code is written with gmail credentials. For a different smtp server, kindly update the code with that particular smtp credentials.
  5. For better understanding of the tutorial – A minimal knowledge of ADO.Net and SQL server is appreciated along with C# Concepts.

================================================================================================

Database Design

Create a sample ‘CustomerDB’ in VS 2010, which holds the info about customers of our product.

================================================================================================

  1. Open VS 2010 -> View -> Server Explorer
  2. Right Click ‘Data Connections’ node -> Add new SQL Server Database
  3. Select a Server (from DropDownList) -> Prefer Windows Authentication -> Give a Name to the new database, here we use ‘CustomerDB’.

The database has been created, now we create a table.

  1. Expand ‘CustomerDB’ in the Server Explorer -> Right Click ‘Tables’ folder -> Select ‘Add New Table’.

Give the details of the table fields as shown below –

CustomerDB-Definition

Save (press CTRL + SHFT + S) the table, it asks to give a table name; in this case we use ‘CustomerDetails’.

To enter sample data –

  1. Right Click ‘CustomerDetails’ table in Server Explorer -> Select -> Show Table Data

In the displayed table data pane, enter random records for testing purpose as shown below.

 CustomerDB-SampleData

Save the Database – This completes the Database design. Now we write a stored procedure to get the details of the customers who are going to celebrate their birthday on that particular calendar date of the server.

================================================================================================

Stored Procedure

Create a Storepd Proc – ‘GetBirthdayBuddiesEmails’ – which is used to fetch the Birthday details of the Customers.

================================================================================================

To create a Stored Proc –

  1. Expnad CustomerDB in the Server Explorer -> Right Click -> Stored Procedures Folder -> Select -> Add new Stored Procedure

Remove complete code from the Stored Procedure and place the below code –

CREATE PROCEDURE dbo.GetBirthdayBuddiesEmails
AS
Select * from CustomerDetails
where DATEPART(m, CustomerDOB)=DATEPART(m,GETDATE()) AND 
DATEPART(d, CustomerDOB) = DATEPART(d, GETDATE())

And then save the Stored Procedure. This creates a Stored Proc with name –‘GetBirthdayBuddiesEmails’ and it can select records of the customers who are celebrating their birthday on that particular server date.

With this we complete the preparation on the Database side. The Database structure would be –

 CustomerDB-Structure

As the Database is ready, now we can start writing code to send our emails asynchronously. For better reusability of code, I would always prefer to create class library of the code, and then reuse it in all my applications (where ever I need it).

================================================================================================

Class Library

Create a Class Library ‘EmailComponent’ – which holds classes to access Database and also to send emails asynchronously.

================================================================================================

Let’s get started by creating a class library –

  1. Open VS 2010
  2. File -> New -> Project
  3. Select ‘Visual C#’ -> Select -> Class Library Template -> Give name – ‘EmailComponent’
  4. Delete the default class -> Class1.cs (which was created with Class Library).
  5. Right Click -> EailComponent Folder in Solution Explorer –> Select ‘Add New Item’.
  6. Select ‘Visual C# Items’ -> Select Class template -> Give name – GetEmailIdsFromDB.cs -> Click ADD.

In this class, we create a method to access database i.e., CustomerDB and get back all the email ids of the users whose birthdates are matching with the present server date (today). ADO.Net is used to make database operations. There are couple of properties (provided in the class) for setting up Connection string and stored procedure name from the Service which implements this class.

================================================================================================

GetEmailIdsFromDB.cs

This class gets the email Id’s of the Birthday boys – and returns the data as DataSet.

================================================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace EmailComponent
{
    public class GetEmailIdsFromDB
    {
        public string connectionString
        {
            get;
            set;
        }
        public string storedProcName
        {
            get;
            set;
        }
        public DataSet GetMailIds()
        {
            DataSet ds = new DataSet();
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                SqlCommand command = new SqlCommand(storedProcName,conn);
                command.CommandType = CommandType.StoredProcedure;

                SqlDataAdapter sda = new SqlDataAdapter(command);
                sda.Fill(ds);
            }
            return ds;
        }
    }
}

Now let’s code async email class –

  1. Right Click -> EailComponent Folder in Solution Explorer –> Select ‘Add New Item’.
  2. Select ‘Visual C# Items’ -> Select Class template -> Give name – Email.cs -> Click ADD.

================================================================================================

Email.cs

This class sends the Emails asynchronously. For more details on this class – see Note at the end of this PART – I.

================================================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Net;
using System.Runtime.Remoting.Messaging;

namespace EmailComponent
{
        public class Email
        {
            public string subject { get; set; }
            public string fromEmail { get; set; }
            public string fromName { get; set; }
            public string messageBody { get; set; }
            public string smtpServer { get; set; }
            public NetworkCredential smtpCredentials { get; set; }

            public bool SendEmail(string toEmail,string toName)
            {
                try
                {
                    MailMessage Message = new MailMessage();
                    Message.IsBodyHtml = true;
                    Message.To.Add(new MailAddress(toEmail, toName));
                    Message.From = (new MailAddress(this.fromEmail, this.fromName));
                    Message.Subject = this.subject;
                    Message.Body = this.messageBody;

                    SmtpClient sc = new SmtpClient();
                    sc.Host = this.smtpServer;
                    sc.Credentials = smtpCredentials;
                    sc.EnableSsl = true;

                    sc.Send(Message);
                }
                catch (Exception ex)
                {
                    return false;
                }
                return true;
            }

            public delegate bool SendEmailDelegate(string toEmail, string toName);

            public void GetResultsOnCallback(IAsyncResult ar)
            {
                SendEmailDelegate del = (SendEmailDelegate)((AsyncResult)ar).AsyncDelegate;
                try
                {
                    bool result = del.EndInvoke(ar);
                }
                catch (Exception ex)
                {
                    bool result = false;
                }
            }

            public bool SendEmailAsync(string toEmail, string toName)
            {
                try
                {
                    SendEmailDelegate dc = new SendEmailDelegate(this.SendEmail);
                    AsyncCallback cb = new AsyncCallback(this.GetResultsOnCallback);
                    IAsyncResult ar = dc.BeginInvoke(toEmail, toName, cb, null);
                }
                catch (Exception ex)
                {
                    return false;
                }
                return true;
            }
    }

}

Now -> Build the project. This completes the necessary code to send email. Class Library Structure would be –

EmailComponent-FolderStructure

With this we complete the PART – I of the tutorial. The only thing left behind is to create the C# Windows Service – which uses the above created Class Library (EmailComponent) and the Database (CustomerDB) to send emails in background to the server.

================================================================================================

Sending Automated Emails asynchronously using a C# Windows Service in conjunction with Database Email records PART – II

================================================================================================

NOTE :-
  1. We can use this Class Library (EmailComponent) not only in conjunction with Windows Services, but also with Web Applications too (where the requirement would be to send emails in async).
  2. The process flow of Email.cs class would be – The client should make a call to SendEmailAsync() method, which uses a AsyncCallBack Delegate to point to the actual SendEmail() Method. The SendEmailAsync() invokes the Async Operation by calling BeginInvoke() of delegate. At the end of the allotted process to the delegate, the GetResultsOnCallback() method would be called and EndInvoke() is raised.
  3. The main advantage with this approach is – there is no need for the programmer to bother about the system allotted threads for the async operation. Once the process allotted to a particular thread completes, the thread will be returned to the system, and waits for next allocation. There by reducing the overhead of maintaining threads manually.
  4. There are public properties in both the classes of the Class Library, the main intention in providing them is to to make the application flexible enough to be get manipulated from the windows service. So we can set the properties from the Windows Service (instead of hard coding them in the Class Library)  and send emails.
  5. At this junction, I would like to thank Dr. Peter Broomberg, for his original article on sending emails asynchronously.

Disclaimer:

All coding and suggestions made in the above discussion is strictly in point of view of the author. It is neither mentioned any where nor even concluded that this is the only possible way to go with, as there will be always a chance for a new approach in achieving the same requirement (in context of programming). The above mentioned code is strictly written and explained for the sake of new comers to C# and ASP.NET world.

You may also like...

2 Pingbacks/Trackbacks

  • ramiramilu

    @bhagat_prasad:disqus Please let me know where you are stuck, because this article clearly shows on how to install windows service.