Wednesday, 13 June 2012

Sending Automated Emails using C# Windows Service

This article explains the creation of a C# Windows Service to send Automated Emails depends on frequency daily, weekly or monthly.Concepts are involved for sending mail automatically are SMTP Server for sending mails, Window service used to mail automatically, Event log is used to see whether the window service is working.

1. Window Service 

 

Windows Service is used to create a application to run in a windows sessions. windows service can automatically run,  restart or paused when the system boots , we do not show any user interface for doing the window service. 

2. Event Log 

 

Eventlog class used to create or accessing the windows event logs. Administration privileges need to write to an event log for every logs.EventLog,class method are used to read from existing logs, write entries to logs and create a logs  or delete event sources. 

3. SMTP Server


The SMTP Server Class is used to Send Mail from a SMTP Server. .Net Framework 2.0 later supports the SMTP Server class from  System.Net.Mail namespace. 
System.Net.Mail namespace supports three class
a) MailMessage - used to describe the messages.
b) MailAddress -  used to define the sender and recipients.
c) Attachments - used to attach the file along with the mail.

4. Timer

 

.Net providers timer component is a server-based timer allows you to specify interval and the elapsed event is raised in your application. This event to provide regular processing. while create a service that uses a timer to periodically , it will check the server is running or not. 

Let’s get started with the creation of Windows Service.

  1. Open VS 2010
  2. File -- New -- Project
  3. Select ‘Visual C#’ -- Windows -- Windows Service --"SchedulerService"
  4. Delete default program file and change/move the main method in Service1.cs
  5. Add log.txt in bin folder
To access Database, add app.config file. To add app.config file -
  1. Right click 'SchedulerService’ in the solution explorer –- Select ‘Add New Item’.
  2. Select ‘Visual C#’ -- Select Application Configuration File -- Click ADD.
Put the following code in the created app.config file –

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<appSettings>
<add key="testconnection" value="Data Source=...;Initial Catalog=...;User ID=...;pwd=..;"></add>
<add key="StartTime" value="05:12 PM "/>
<add key="callDuration" value="2"/>
<add key="CallType" value="1"/> 
<add key="fromAdd" value=".................." />
<add key="BccAdd" value="................" />
</appSettings
<system.net>
      <mailSettings>
        <smtp from="..............">

          <network host="localhost" password="........." userName="......"/>
        </smtp>
      </mailSettings>
  </system.net>
</configuration>


Now, Writing code to Service1.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using Microsoft.Win32;
using System.Timers;
using System.Threading;
using System.IO;
using System.Security;
using System.Configuration;
using System.Net;
using System.Net.Mail;
using System.Xml;
using System.Data.SqlClient;
using System.Collections.Specialized;
using System.Text;
using System.Web;


namespace SchedulerService
{
    public class ScheduleService : System.ServiceProcess.ServiceBase
    {
        private string timeString;
        private System.ComponentModel.IContainer components;
        private System.Timers.Timer timer;
        public int getCallType;

        public ScheduleService()
        {
            InitializeComponent();
            int strTime = Convert.ToInt32(ConfigurationSettings.AppSettings["callDuration"]);
            getCallType = Convert.ToInt32(ConfigurationSettings.AppSettings["CallType"]);
            if (getCallType == 1)
            {
                timer = new System.Timers.Timer();
                double inter = (double)GetNextInterval();
                timer.Interval = inter;
                timer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);
            }
            else
            {
                timer = new System.Timers.Timer();
                timer.Interval = strTime * 1000;
                timer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);
            }
        }

        private double GetNextInterval()
        {
            timeString = ConfigurationSettings.AppSettings["StartTime"];
            DateTime t = DateTime.Parse(timeString);
            TimeSpan ts = new TimeSpan();
            int x;
            ts = t - System.DateTime.Now;
            if (ts.TotalMilliseconds < 0)
            {
                ts = t.AddDays(1) - System.DateTime.Now;
            }
            return ts.TotalMilliseconds;
        }

        private void timerElapsed(object sender, ElapsedEventArgs e)
        {
            timer.Stop();
            System.Threading.Thread.Sleep(1000000);
            SetTimer();
        }

        private void SetTimer()
        {
            try
            {
                double inter = (double)GetNextInterval();
                timer.Interval = inter;
                timer.Start();
            }
            catch (Exception ex)
            {
            }
        }

        [STAThread]
        static void Main()
        {
            System.ServiceProcess.ServiceBase[] ServicesToRun;
            ServicesToRun = new System.ServiceProcess.ServiceBase[] { new ScheduleService() };
            System.ServiceProcess.ServiceBase.Run(ServicesToRun);
        }

        private void InitializeComponent()
        {
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
            this.ServiceName = "EmailFrequencyScheduler";
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        protected override void OnStart(string[] args)
        {
            timer.AutoReset = true;
            timer.Enabled = true;
            string urlLogPath = System.Windows.Forms.Application.StartupPath + "\\Schedulerlog\\log.txt";
            string file = urlLogPath;
            if (File.Exists(file))
            {
                File.AppendAllText(file, "\n=================\n");
                File.AppendAllText(file, "Onstart" + System.DateTime.Now + " \r\n " );
            }
            else
            {
                File.Create(urlLogPath);
                File.AppendAllText(file, "File created on --" + System.DateTime.Now + " ");
                File.AppendAllText(file, "Onstart" + System.DateTime.Now + " \r\n ");
            }
        }

        protected override void OnStop()
        {
            timer.AutoReset = false;
            timer.Enabled = false;
        }

        private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
        {
            string timeInterval = ConfigurationSettings.AppSettings["callDuration"];
            string strondemand = ConfigurationSettings.AppSettings["testconnection"];
            string urlLogPath = System.Windows.Forms.Application.StartupPath + "\\Schedulerlog\\log.txt";
            string file = urlLogPath;

            try
            {
                DataTable dtemail = new DataTable();
                string strSql = "Select * from Email ";
                SqlConnection con = new SqlConnection(strondemand);
                con.Open();
                SqlDataAdapter adapter = new SqlDataAdapter(strSql, con);
                adapter.Fill(dtemail);
                string strSub = string.Empty;
                string strquery = string.Empty;
                string strAttachFile = string.Empty;
                if (dtemail.Rows.Count > 0)
                {
                    foreach (DataRow dremail in dtemail.Rows)
                    {
                        string strEmailTo = Convert.ToString(dremail["Email"]);
                        string frequency = Convert.ToString(dremail["Frequency"]);
                        string strEmailID = Convert.ToString(dremail["id"]);
                        strAttachFile = "C:\\Inetpub\\wwwroot\\EmailSchedule" + strEmailID + ".xls";

                        if (Convert.ToString(dremail["ScheduleDate"]) == "" || Convert.ToString(dremail["ScheduleDate"]) == null)
                        {
                            DateTime strUpDate;
                            DateTime currentDate = DateTime.Now; ;
                            DateTime UpdatedDate = currentDate;

                            if (Convert.ToString(dremail["Frequency"]) == "Daily")
                            {
                                strSub = "Report - Daily email";
                                strUpDate = currentDate;
                                strquery = "update Email set ScheduleDate = '" + strUpDate  + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                SqlCommand cmd = new SqlCommand(strquery, con);
                                cmd.ExecuteNonQuery();
                                sendEmailReport(strEmailTo, strSub, strAttachFile);
                            }
                            if (Convert.ToString(dremail["Frequency"]) == "Weekly")
                            {
                                strSub = "Report - Weekly email";
                                strUpDate = currentDate.AddDays(7);
                                strquery = "update Email set ScheduleDate = '" + strUpDate  + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                SqlCommand cmd = new SqlCommand(strquery, con);
                                cmd.ExecuteNonQuery();
                                sendEmailReport(strEmailTo, strSub, strAttachFile);
                            }
                            if (Convert.ToString(dremail["Frequency"]) == "Monthly")
                            {
                                strSub = "Report - Monthly email";
                                strUpDate = currentDate.AddMonths(1);
                                strquery = "update Email set ScheduleDate = '" + strUpDate + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                SqlCommand cmd = new SqlCommand(strquery, con);
                                cmd.ExecuteNonQuery();
                                sendEmailReport(strEmailTo, strSub, strAttachFile);
                            }
                        }
                        else
                        {
                            DateTime strtime = DateTime.Now;
                            TimeSpan span = new TimeSpan();
                            if (Convert.ToString(dremail["Frequency"]) == "Daily")
                            {
                                strSub = "Report - Daily email";
                                DateTime strlastdate = Convert.ToDateTime(dremail["ScheduleDate"]);
                                span = strtime.Subtract(strlastdate);
                                if (span.Minutes >= 59)
                                {
                                    strquery = "update Email set ScheduleDate = '" + strtime + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                    SqlCommand cmd = new SqlCommand(strquery, con);
                                    cmd.ExecuteNonQuery();
                                    sendEmailReport(strEmailTo, strSub, strAttachFile);
                                }
                            }
                            if (Convert.ToString(dremail["Frequency"]) == "Weekly")
                            {
                                strSub = "Report - Weekly email";
                                DateTime strlastdate = Convert.ToDateTime(dremail["ScheduleDate"]);
                                span = strtime.Subtract(strlastdate);
                                if (span.Days == 7)
                                {
                                    strquery = "update Email set ScheduleDate = '" + strtime + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                    SqlCommand cmd = new SqlCommand(strquery, con);
                                    cmd.ExecuteNonQuery();
                                    sendEmailReport(strEmailTo, strSub, strAttachFile);
                                }
                            }
                            if (Convert.ToString(dremail["Frequency"]) == "Monthly")
                            {
                                strSub = "Report - Monthly email";
                                DateTime strlastdate = Convert.ToDateTime(dremail["ScheduleDate"]);
                                span = strtime.Subtract(strlastdate);
                                if (span.Days == 30)
                                {
                                    strquery = "update Email set ScheduleDate = '" + strtime + "' where id ='" + Convert.ToString(dremail["id"]) + "'";
                                    SqlCommand cmd = new SqlCommand(strquery, con);
                                    cmd.ExecuteNonQuery();
                                    sendEmailReport(strEmailTo, strSub, strAttachFile);
                                }
                            }
                            if (File.Exists(file))
                            {
                                File.AppendAllText(file, "\n=================\n");
                                File.AppendAllText(file, "Span :" + span.Days);
                            }
                            else
                            {
                                File.Create(urlLogPath);
                                File.AppendAllText(file, "File created on --" + System.DateTime.Now + " ");
                                File.AppendAllText(file, "Span :" + span.Days);
                            }
                        }
                    }
                }

                string strResponse = "Mail is send successfully";

            }
            catch (Exception ex)
            {
                if (File.Exists(file))
                {
                    File.AppendAllText(file, "\n=================\n");
                    File.AppendAllText(file, ex.Message.ToString());
                }
                else
                {
                    File.Create(urlLogPath);
                    File.AppendAllText(file, "File created on --" + System.DateTime.Now + " ");
                    File.AppendAllText(file, ex.Message.ToString());
                }
            }
            if (getCallType == 1)
            {
                timer.Stop();
                System.Threading.Thread.Sleep(1000000);
                SetTimer();
            }
        }

        private void sendEmailReport(string strEmailTo, string strSubject, string strEmailAttachFile)
        {
            string urlLogPath = System.Windows.Forms.Application.StartupPath + "\\Schedulerlog\\log.txt";
            string file = urlLogPath;
            MailMessage MailMsg = new MailMessage();
            try
            {
               

                // Add your code to send Email

                smtpClient.Send(MailMsg);
                if (File.Exists(file))
                {
                    File.AppendAllText(file, "\n=================\n");
                    File.AppendAllText(file,  "Email sent to "+strEmailTo+" " + System.DateTime.Now + " \r\n ");
                }
                else
                {
                    File.Create(urlLogPath);
                    File.AppendAllText(file, "File created on --" + System.DateTime.Now + " \r\n ");
                    File.AppendAllText(file, "Email sent to " + strEmailTo + " " + System.DateTime.Now + " \r\n ");
                }
            }
            catch (Exception ex)
            {
                if (File.Exists(file))
                {
                    File.AppendAllText(file, "\n=================\n");
                    File.AppendAllText(file, ex.Message.ToString());
                }
                else
                {
                    File.Create(urlLogPath);
                    File.AppendAllText(file, "File created on --" + System.DateTime.Now + " ");
                    File.AppendAllText(file, ex.Message.ToString());
                }
            }
            finally
            {
                MailMsg.Attachments.Dispose();
                MailMsg.Dispose();
            }
        }   
    }
}


 

Once written coding,compile if no error occurs. Then  Rightclick in design mode -- Select Add installer -- it will create two components
a) ServiceProcessInstaller -- used to define the windows service work in which account.Here we can set the account type as LocalSystem,User,Network service. In my project i have used LocalSystem
b) ServiceInstaller -- Set ServiceName for ex. (EmailFrequencyScheduler) and Starttype as Automatic.

Once Set the property and Build. Now created web service.

Now, Create Windows Service Setup project

 

1. In solution explorer, Add new project -- select setup and deployment under other project types and add setup named "EmailSchedulerService". Add Project Output -- Primary Output in Application folder and log.txt (which is previously added in bin folder) file also. It looks like.....

2. In Solution Explorer, right-click the EmailSchedulerService setup project -- point to View -- then choose Custom Actions. And add Primary Output to  four nodes of custom actions i.e. Install, Commit, Rollback and Uninstall. Looks like...


3. In Solution Explorer, right-click the EmailSchedulerService setup project and choose Build.


The complete Folder structure would be -


Install the Windows Service

 

To install, right-click the setup project in the Solution Explorer and select Install
To uninstall, right-click the setup project in the solution explorer and select uninstall options. 

Stop and Start Window Service 

 

Click Start --> Programs --> Control Panel –> Administrative Tools –> Services --> click Start.


View event log files 

 

Click Start --> Programs --> Control Panel –> Administrative Tools –> Event Viewer –> Applications and Services Logs.  

Debug Window Service

 

1. Build the Solution.
2. Start your Service.
3. While your Service is starting, Goto --> Debug --> Attach Process
4. Make sure "Show Process from all users" and "Show Process in all sessions" are checked.
5. Find your "" in the list and click "Attach".
6. You should now be at the breakpoint you inserted.
     
Download Files: EmailScheduler.rar
 
Its Done. Please feel free to send your feedback. Thank you.

 


3 comments:

  1. On click of above DOWNLOAD link it is asking gmail id password. on Providing it is telling i don't access rights. please do the needful as quick you can.

    ReplyDelete
  2. I download your source and when i run it i got the following error :

    Cannot start service from the command line or debugger. A Windows service must be installed(using installutil.exe) and then start with the server explorer, windows service administrative tool or the NET START command.

    ReplyDelete