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

  • Vishalatchi

    Fantastic article save my time……..thanks a lot, step by step explanation very clear and useful for beginners like me,keep up the gud work!!!!

  • Thao

    An useful artical.Thank you very much

  • AME

    Thank you, saved me a from doing a ton of last minute work!

  • snehasis

    Hi,

    Seriously people like you takes lot of developers burden.Thanks a lot and keep helping us.

  • Abe

    Great work Rami, just what i needed, implemented the solution into my code and works like a charm. Thanks

  • Hanamant Vibhute

    very Nice, with step by step approach…It taught lots of things….
    realy gri8 1…..thanks…

  • Mateen

    Really nice article with step by step explanation…. Helpful

  • vijitha

    Thanks a lot!

  • vsics

    good

  • Kaltalo

    Hello,

    Thanks a lot for this usefull class.
    But I use it on my website and i have a bug with it.

    In fact i have no error in my application, even on my server.
    But when i try to send 96 emails, i received only 52 on the first try and i received only 58 on the second try.

    Do you have an idea about this problem ?

  • pooja

    I am not able to find my .dll file…!! how is this possible?

  • RamiVemula

    Pooja – When you build the EmailComponent, you should be finding DLL in BIN folder of the project in the windows explorer.

    Thanks,

  • KMikita

    Is there any difference if I am using Visual Studio 2008?

  • vipul

    really nice article

  • vipul

    good article

  • sunil

    Thank u so much for your kind response and ur precise effort.
    I ve successfully debugged the project, then i ve installed the BirthdayEmailServiceSetup setup.exe successfully and started the services from services folder, Now my main problem is, i m getting the proper response in the event viewer “Message Sent SUCCESS to – xyz” but i m unable to receive the email to specific email id. Even i checked the smtp protocol. plz let me know whether i m missing something or not

  • RamiVemula

    @KMikita – Probably NO.

  • RamiVemula

    @Sunil – Check your SMTP Ports which are open or closed. also check your Mail Spam, sometimes email might enter into it.

  • Rupesh Deshmukh

    Thank You for this superb code and explanation.
    Very Easy To Understand. It will me very nice if you explained something on
    AsyncCallback and IAsyncResult.

  • Pingback: Send Email in Asp.net C# « Share your knowledge()

  • Shah Zeb

    Rami no doubt you have written a fantastic article. The first one i read of you and i am really impressed with the step by step explanation. Keep it up.

  • Alok

    Can we use this approach to send sms on particular time..

  • RamiVemula

    @Alok – Yes, if you have a proper 3rd party SMS API.

  • vikram`

    How to debug the service after installing it.

  • RamiVemula

    @Vikram – You got to attach the process of Windows Service and then start debugging it – http://forum.codecall.net/topic/70194-windows-service-part-2-installing-debugging-windows-service/#axzz2JAytnlvr

  • mahesh

    Good one

  • Reshma

    Hi Ramivemula,
    I need to send automatic mails from my website using asp.net and sqlserver hosted in arvixe server(Sharing server),There window service is not possilbe.
    So how I will do this?Please help

  • RamiVemula

    @Reshma – Go for SQL Server Agent jobs.

  • sureshkannan

    very clear and superb.

  • Raj

    Newletter Subscription:
    Dear RamiVemula Sir,
    My website has been hosted on Godaddy’s server.
    Now i’ve to add one more functionality that is “sending automatic emails from a database” on weekly basis without any intervention. Is it possible?
    If yes please help me.

  • aldz

    Hi!

    may i know what type of solution did you use. I just notices that you started adding projects on the solution.

    Thanks!

  • RamiVemula

    @aldz – you can get started with a blank solution and then you can continue added projects described in the tutorial.

  • venkata rao

    Hi Sir,
    Thank u for ur step by step explanation. How to send mail to every day 8 p.m. without user interaction.
    plz help me.

  • RamiVemula

    @Venkat Rao – Try out exactly the same way mentioned in the tutorial, but customize the timer which I used to 8PM. Try it out and let me know.

  • siva

    Its nice article…………

  • siva

    How to send mail to every day 8 AM. without user interaction.

  • RamiVemula

    @Siva – you can handle the timer in a better way by checking what time is it on every tick event. There by you can achieve sending emails everyday by 8AM.

  • Mayuri Raut

    How to send mail to client every last day of month on 10 AM.without user interaction.

  • Mayuri Raut

    In Sending Email Method is showing in email log

  • tawseef

    please help me,I have got this error when debug the project

    The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.

  • Pingback: [RESOLVED]auto send mail | ASP Web Form Data Control()

  • Nirav Prajapati

    i want to send aoto sms on specific date and time
    abd window service work on server…?

  • Suresh

    we want to send automatic mail same day without user intervention.

  • RamiVemula

    @Suresh – I think you can change Windows Service code to tweak a little bit to send automated emails on the same day.

  • RamiVemula

    @Nirav, Sending SMS is out of scope of this article.