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 http://<<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 (24)
  1. Christos says:

    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?

  2. What error you are getting? Are you able to debug it?

  3. Liz says:

    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

  4. Liz says:

    Never mind. Wrong namespace.  How to deploy to another server? Thanks.

  5. It is a WSP package, SharePoint automatically propogates wsp deployment to all servers

  6. 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.

  7. LAkshitha says:

    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

  8. Ninel says:

    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?

  9. Maanikaraj says:

    hi,

    all are configured well,mail not send  

  10. LAkshitha

    I get the same error, were you able to fix it?

  11. Hi,

    I used your code to send email from timer job and made a few changed and ended up getting an error. its says "Object reference not set to an instance of an object. " in job history and when i try to debug the code it stops at this line " smtpAddress = web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;" and the error says "Object reference not set to an instance of an object."..can you help.  

    Also, i have not Configured outgoing e-mail settings in my farm, could this be the prob?  thanks

    regards,

    Vikram

  12. Hi Vicky, You need to configure out bound email settings.

  13. Hi says:

    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!

  14. smith says:

    thx very useful

  15. Perla says:

    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 ?

  16. Jhom Lopez says:

    Thanks, nice tutorial :))

  17. Robert Duncan says:

    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?

  18. Robert Duncan says:

    Never mind. I figured it out: you have to restart the SharePoint timer service every time you redeploy it.

  19. Rehman says:

    Hi

    I couldnot find the timerjob under jobdefination location, can anybody please help me?

  20. Steve says:

    Why is Visual Studio a prerequisite for doing this? Why is this not available in Sharepoint natively? Utterly lame.

  21. anitha says:

    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?

  22. Adi says:

    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.

  23. Adi says:

    Hi, I resolved my issue by doing

    1) add the below line to event receiver generated code

    using System.Linq;

    2) copy everything from after this line

    [Guid("e016fed4-1c68-4350-9b5d-1196557f569c")]

       public class NotificationTimerJobFeatureEventReceiver : SPFeatureReceiver

Comments are closed.

Skip to main content