Custom Alert Handlers: Part 1 of 2
Have you ever wanted to modify the contents of an Alert Email from SharePoint 2007. We had a requirement recently, from a client, to modify the contents of alert emails in a very specific way. They wanted to change not the layout but the contents, and they wanted the contents to be different based on the content type.
I started by looking at what I could achieve using CAML and updating the alerttemplate.xml file. I quickly came to the decision that this approach was not viable and so switched to building an Alert Event Handler. Alert Handlers are called just before an alert email is to be sent. The handler has the ability to modify the email contents as well as decide not to send it.
There are a few steps to creating an Alert Handler, these break down into three broad steps:
- Create and register the handler
- Create an alert template that requires the handler
- Attach the template and handler to a list or lists
It is best if the alert template can be attached to a new list, prior to any users creating alerts. The reason for this is that the alert points to the alert template that the list was using at the time the alert was created. So if you update the template a list is using, you will need to update all the existing alerts . For my client they had a large number of existing alerts, so I needed to update them. This is outside the scope of this posting, but I will follow up with a part 2 that details how to do that, I created an STSASDM command for it.
Creating an Alert Handler
To create an Alert Handler, you need to first create a strong named assembly and then create a class that implements IAlertNotifyHandler. The assembly will be deployed to the Global Assembly Cache as part of a SharePoint Solution Package. The IAlertNotifyHandler interface contains only one method:
public bool OnNotification(SPAlertHandlerParams ahp)
This method is called just before the email is to be sent. The SPAlertHandlerParams object contains all the information about the alert, including the header and body which has already been created using the XML template. The handler method can then inspect the information and decide if the existing email should be sent, or a new one created. To send an email use the SendEmail function:
SPUtility.SendEmail(web, ahp.headers, ahp.body);
Alert emails come in two forms, Immediate and Digest, in my case I only needed to modify the immediate email and so I check the ahp.a.AlertFrequency to see if it was SPAlertFrequency.Immediate if it was not then I send the existing email. The alert email could also be for one of several event types:
In my case I only wanted to modify the alert emails for add and modify events.
Once the assembly has been created you will need its public key token to add to the alert template, the easiest way to find it is to add the assembly to the GAC and then display its properties - the public key token is displayed there.
When debugging the code one thing to remember is that even "immediate" alerts are not immediate - they are sent every 5 minutes by and OWSTimer job. So you will need to attach to the OWSTimer process in the debugger. Andrew Connell has some useful VStudio macros that can save you a lot of key strokes and mouse clicks for attaching to the OWSTimer process (See http://andrewconnell.com/blog/archive/2007/01/25/5855.aspx). Another thing you will likely want to do is decrease the time interval for the immediate email from 5 minutes to 1 minute - this will save you lots of waiting time. Use stsadm to chnage the timer job:
stsadm -o setproperty -propertyname job-immediate-alerts -url http://moss/ -propertyvalue "every 1 minutes between 0 and 59"
Having created your assembly you can move onto step 2 - creating the template.
Creating an Alert Template
The first thing to do here is copy the alerttemplates.xml file, if you modify this file directly you run the risk of breaking alerts. The alert templates file can be found in the 12 hive under, TEMPLATE\XML. Once you open this file you will find its huge, around 13K lines, but if you collapse the sections it will become easier to understand. The file contains 14 templates, each one for a different list type, as shown below.
Since my clients needs were for a Document Library, I copied the SPAlertTemplateType.DocumentLibrary template. To add an Alert Handler to the template, you need to modify the <Properties> section and add 3 additional nodes which identify the class and the assembly that is to be called, and any properties which are to be passed to the class. For example:
<NotificationHandlerAssembly>Syrinx.Alerts.AlertHandler, Version=18.104.22.168, Culture=neutral, PublicKeyToken=6c60c18cb10a8f1c</NotificationHandlerAssembly>
The NotificationHandlerProperties can be used to pass a string property to your alert handler class. It can be accessed in the class using ahp.handlerProperties property. In my case I made this an XML string I could more readily parse.
Attaching the Template
Having created the template you now need to update the list of templates in the site collection, this can be done using an stsadm command:
stsadm -o updatealerttemplates -url http://moss -filename "syrinx-alerttemplates.xml“
Having updated the list of templates the next step is to attach the template to the specific list you want to use it. The only way to do this is through code:
SPAlertTemplateCollection ats = new SPAlertTemplateCollection((SPWebService)_siteCollection.WebApplication.Parent);
_newTemplate = ats[_alertTemplateName];
if (_newTemplate == null)
// We did not find the specified Template.
throw new Exception("Failed to find template " + _alertTemplateName + "in the template collection.");
_list.AlertTemplate = _newTemplate;
You could add this code as part of a feature receiver, however this would require you to hard code the list name. I chose to create a custom stsadm command that would allow me to attach templates to lists, providing more flexibility.
Once you executed the above code (or similar) to attach the template, new alerts created on the list will use the new template. In my case, the client had a large number of existing alerts configured. These alerts retain the name of the template they were created with and so do not go through the alert handler. To chnage them you need to update the alert definitions; I will cover that in Part 2 along with creating custom STSADM commands.