SharePoint 2010 Custom Timer Job - Send an Email

1. Open Visual Studio 2010 and goto FILE -> New Project -> Empty SharePoint Project.

2. Select SharePoint 2010 under Installed Templates under left Navigation.

3. Select Deploy as Farm Solution Option and replace https://<<ServerName>>/ with proper URL of the SharePoint site.

4. Right Click on the Project and Create a New Item

5. Select Code from Installed Templates of left Navigation and name the file as "NotificationTimerJob.cs"

6. Paste the following code

 

 using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.SharePoint.Administration; 
using Microsoft.SharePoint; 
using System.Net.Mail; 
 
namespace NotificationCustomTimerJob 
{ 
 public class NotificationTimerJob : Microsoft.SharePoint.Administration.SPJobDefinition 
 { 
 /// <summary> 
 /// Default Consructor 
 /// </summary> 
 public NotificationTimerJob() 
 : base() 
 { 
 } 
 
 /// <summary> 
 /// Parameterized Constructor 
 /// </summary> 
 /// <param name="jobName">Name of Job to display in central admin</param> 
 /// <param name="service">SharePoint Service </param> 
 /// <param name="server">Name of the server</param> 
 /// <param name="targetType">job type is for content db or job</param> 
 public NotificationTimerJob(string jobName, SPService service, SPServer server, SPJobLockType targetType) 
 : base(jobName, service, server, targetType) 
 { 
 } 
 
 /// <summary> 
 /// Parameterized Constructor 
 /// </summary> 
 /// <param name="jobName"></param> 
 /// <param name="webApplication"></param> 
 public NotificationTimerJob(string jobName, SPWebApplication webApplication) 
 : base(jobName, webApplication, null, SPJobLockType.ContentDatabase) 
 { 
 this.Title = "Email Notification Job"; 
 } 
 
 /// <summary> 
 /// Execute method called when the timer job starts executing. It runs on "DB News Announcements" list which checks for all 
 /// approved annoucements and sends out an email to all users for all approved news. 
 /// </summary> 
 /// <param name="contentDbId"></param> 
 public override void Execute(Guid contentDbId) 
 { 
 string from = string.Empty; 
 string smtpAddress = string.Empty; 
 string to = "someone@somecompany.com"; 
 string subject = "Email Notification"; 
 string body = "<h1> Email Sending from Email Notification Job </h1>"; 
 
 SPSecurity.RunWithElevatedPrivileges(delegate() 
 { 
 // get a reference to the current site collection's content database 
 SPWebApplication webApplication = this.Parent as SPWebApplication; 
 SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId]; 
 
 // get a reference to the "Tasks" list in the RootWeb of the first site collection in the content database 
 SPWeb rootWeb = contentDb.Sites[0].RootWeb; 
 
 // Get the DB News Announcements List 
 SPList listjob = rootWeb.Lists.TryGetList("Tasks"); 
 
 // Get sender address from web application settings 
 from = rootWeb.Site.WebApplication.OutboundMailSenderAddress; 
 
 // Get SMTP address from web application settings 
 smtpAddress = rootWeb.Site.WebApplication.OutboundMailServiceInstance.Server.Address; 
 
 // Send an email if the news is approved 
 bool emailSent = SendMail(smtpAddress, subject, body, true, from, to, null, null); 
 
 if (listjob != null && emailSent) 
 { 
 SPListItem newListItem = listjob.Items.Add(); 
 newListItem["Title"] = string.Concat("Email Notification Sent at : ", DateTime.Now.ToString()); 
 newListItem.Update(); 
 } 
 }); 
 
 } 
 
 /// <summary> 
 /// Send an email to indented users 
 /// </summary> 
 /// <param name="smtpAddress">SMTP address to sending email</param> 
 /// <param name="subject">subject of email</param> 
 /// <param name="body">body of email</param> 
 /// <param name="isBodyHtml">whether body is html or text</param> 
 /// <param name="from">from address</param> 
 /// <param name="to">to users(multiple email address can be seperated by comma(,) )</param> 
 /// <param name="cc">cc users</param> 
 /// <param name="bcc">bcc users</param> 
 /// <returns>Status whether email successfully sent or not</returns> 
 public bool SendMail(string smtpAddress, string subject, string body, bool isBodyHtml, string from, string to, string cc, string bcc) 
 { 
 bool mailSent = false; 
 SmtpClient smtpClient = null; 
 
 try 
 { 
 // Assign SMTP address 
 smtpClient = new SmtpClient(); 
 smtpClient.Host = smtpAddress; 
 
 //Create an email message 
 MailMessage mailMessage = new MailMessage(from, to, subject, body); 
 if (!String.IsNullOrEmpty(cc)) 
 { 
 MailAddress CCAddress = new MailAddress(cc); 
 mailMessage.CC.Add(CCAddress); 
 } 
 if (!String.IsNullOrEmpty(bcc)) 
 { 
 MailAddress BCCAddress = new MailAddress(bcc); 
 mailMessage.Bcc.Add(BCCAddress); 
 } 
 mailMessage.IsBodyHtml = isBodyHtml; 
 
 // Send the email 
 smtpClient.Send(mailMessage); 
 mailSent = true; 
 } 
 catch (Exception) 
 { 
 mailSent = false; 
 } 
 
 return mailSent; 
 } 
 
 
 } 
} 

 

 7. Now add a new feature

 

 

 Rename the feature to NotificationTimerJobFeature and add add an event receiver for registering the timer job and scheduling it for every 5 minutes. Change the scope to Site

 

 9. Paste the below code snippet in event receiver for Feature activation and deactivation.
  
 using System; 
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using Microsoft.SharePoint; 
using Microsoft.SharePoint.Security; 
using System.Linq; 
 
namespace NotificationCustomTimerJob.Features.NotificationTimerJobFeature 
{ 
 /// <summary> 
 /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade. 
 /// </summary> 
 /// <remarks> 
 /// The GUID attached to this class may be used during packaging and should not be modified. 
 /// </remarks> 
 
 [Guid("67388410-1290-41d2-8645-5a1203b27bc4")] 
 public class NotificationTimerJobFeatureEventReceiver : SPFeatureReceiver 
 { 
 // Name of the Timer Job, but not the Title which is displayed in central admin 
 private const string List_JOB_NAME = "NotificationTimerJob"; 
 
 // Uncomment the method below to handle the event raised after a feature has been activated. 
 
 public override void FeatureActivated(SPFeatureReceiverProperties properties) 
 { 
 SPSecurity.RunWithElevatedPrivileges(delegate() 
 { 
 SPSite site = properties.Feature.Parent as SPSite; 
 
 // make sure the job isn't already registered 
 site.WebApplication.JobDefinitions.Where(t => t.Name.Equals(List_JOB_NAME)).ToList().ForEach(j => j.Delete()); 
 
 // install the job 
 NotificationTimerJob listLoggerJob = new NotificationTimerJob(List_JOB_NAME, site.WebApplication); 
 SPMinuteSchedule schedule = new SPMinuteSchedule(); 
 schedule.BeginSecond = 0; 
 schedule.EndSecond = 59; 
 schedule.Interval = 5; 
 listLoggerJob.Schedule = schedule; 
 listLoggerJob.Update(); 
 }); 
 } 
 
 
 // Uncomment the method below to handle the event raised before a feature is deactivated. 
 
 public override void FeatureDeactivating(SPFeatureReceiverProperties properties) 
 { 
 SPSecurity.RunWithElevatedPrivileges(delegate() 
 { 
 SPSite site = properties.Feature.Parent as SPSite; 
 
 // delete the job 
 site.WebApplication.JobDefinitions.Where(t => t.Name.Equals(List_JOB_NAME)).ToList().ForEach(j => j.Delete()); 
 }); 
 } 
 
 
 // Uncomment the method below to handle the event raised after a feature has been installed. 
 
 //public override void FeatureInstalled(SPFeatureReceiverProperties properties) 
 //{ 
 //} 
 
 
 // Uncomment the method below to handle the event raised before a feature is uninstalled. 
 
 //public override void FeatureUninstalling(SPFeatureReceiverProperties properties) 
 //{ 
 //} 
 
 // Uncomment the method below to handle the event raised when a feature is upgrading. 
 
 //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters) 
 //{ 
 //} 
 } 
} 
  
 10. Deploy the feature by right click on the project and deploy.

  
 11. Now navigate to  Central Administration -> Monitoring -> Review Job Definitions  under Timer Jobs section.
  

 12. Administrator can change the settings of the timer job schedule. Now this job sends an email and adds a Task in the task list.
  
  

Comments

  • Anonymous
    February 07, 2012
    I'm trying to create a job that will send an email every time it runs. i used you code to create it and I made some changes. It seems as it is not working at all when it is not connected to the Tasks list. Can you please help?

  • Anonymous
    February 08, 2012
    What error you are getting? Are you able to debug it?

  • Anonymous
    March 04, 2012
    Can't see NotificationTimerJob class from Event Receiver The type or namespace name 'NotificationTimerJob' could not be found (are you missing a using directive or an assembly reference?) C:VSProjectMyProject2MyProject2FeaturesNotificationTimerJobFeatureNotificationTimerJobFeature.EventReceiver.cs 35 17 MyProject2

  • Anonymous
    March 04, 2012
    Never mind. Wrong namespace.  How to deploy to another server? Thanks.

  • Anonymous
    March 12, 2012
    It is a WSP package, SharePoint automatically propogates wsp deployment to all servers

  • Anonymous
    May 08, 2012
    I've just seen this linked from the Technet forums.  Good work, I'll be making use of this I suspect. Thanks for the contribution.

  • Anonymous
    May 10, 2012
    I got this error message Error 3 Error occurred in deployment step 'Add Solution': Failed to create receiver object from assembly "NotificationCustomTimerJob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bd543d68a922f01a", class "$SharePoint.Type.ab8160cd-5f1d-4021-8636-64008c6b0c8b.FullName$" for feature "NotificationCustomTimerJob_NotificationTimerJobFeature" (ID: f4c6159e-d292-403c-b5fc-fab3c39508b9).: System.ArgumentNullException: Value cannot be null. Parameter name: type   at System.Activator.CreateInstance(Type type, Boolean nonPublic)   at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject() 0 0 NotificationCustomTimerJob

  • Anonymous
    June 04, 2012
    I need to send a weekly email for changes made to a site's lists. One email listing changes made to multiple lists. Is this possible?

  • Anonymous
    June 21, 2012
    hi, all are configured well,mail not send  

  • Anonymous
    July 31, 2012
    LAkshitha I get the same error, were you able to fix it?

  • Anonymous
    February 11, 2013
    The comment has been removed

  • Anonymous
    February 25, 2013
    Hi Vicky, You need to configure out bound email settings.

  • Anonymous
    May 16, 2013
    Could you please show how to implement looping through all items and sending the item urls through an e-mail of the custom timer job? Pls! Pls!

  • Anonymous
    July 18, 2013
    thx very useful

  • Anonymous
    December 30, 2013
    excellent post

  • Anonymous
    March 12, 2014
    Hey LAkshitha and Guru I got this error class "$SharePoint.Type.ab8160cd-5f1d-4021-8636-64008c6b0c8b.FullName$" for feature "NotificationCustomTimerJob_NotificationTimerJobFeature" (ID: f4c6159e-d292-403c-b5fc-fab3c39508b9).: System.ArgumentNullException: Value cannot be null. Parameter name: type  at System.Activator.CreateInstance(Type type, Boolean nonPublic)  at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject() 0 0 NotificationCustomTimerJob *************could you tell me ... how to resolve this error pls ?

  • Anonymous
    March 18, 2014
    Thanks, nice tutorial :))

  • Anonymous
    September 05, 2014
    This is working well, but I'm having a problem where, if I make a change to the class NotificationTimerJob.cs, and redeploy, the job on SharePoint keeps running with the old version of the class. This happens if retract the solution in VS or SharePoint, or if reset IIS. How can I fix that?

  • Anonymous
    September 05, 2014
    Never mind. I figured it out: you have to restart the SharePoint timer service every time you redeploy it.

  • Anonymous
    February 02, 2015
    Hi I couldnot find the timerjob under jobdefination location, can anybody please help me?

  • Anonymous
    February 04, 2015
    The comment has been removed

  • Anonymous
    August 19, 2015
    Error 1 Error occurred in deployment step 'Add Solution': Failed to create receiver object from assembly "NotificationCustomTimerjob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=69905e0c452e3fa8", class "$SharePoint.Type.d4ce3f92-a1f4-412d-8726-074963e5521c.FullName$" for feature "NotificationCustomTimerjob_NotificationTimerJobFeature" (ID: 4859ce7e-8d19-4f25-a2ec-66ef20f35d52).: System.ArgumentNullException: Value cannot be null. Parameter name: type   at System.Activator.CreateInstance(Type type, Boolean nonPublic)   at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject() 0 0 NotificationCustomTimerjob I got this error. can you please tell me how to fix this?

  • Anonymous
    January 22, 2016
    Error 1 Error occurred in deployment step 'Add Solution': Failed to create receiver object from assembly "NotificationCustomTimerJob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4b2d4f410c722ce9", class "$SharePoint.Type.b4691825-aea1-477b-a02e-a3bcc1afb334.FullName$" for feature "NotificationCustomTimerJob_NotificationTimerJobFeature" (ID: 11b9f856-d878-421a-b89b-3f8d0aac9027).: System.ArgumentNullException: Value cannot be null. Parameter name: type   at System.Activator.CreateInstance(Type type, Boolean nonPublic)   at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject() 0 0 NotificationCustomTimerJob Please help me to fix this error.

  • Anonymous
    January 22, 2016
    The comment has been removed