Code for sending emails from SharePoint
A client needed to customize SharePoint email notifications in order to send some activity feeds, plus some alerts coming from a custom list that were targeted to audiences (through a custom Audiences field). Let’s see… what about adding a SPAlert to that list plus an alert handler, finally customize AlertTemplates.xml (better said, copying it to another file, setting that one as the template, etc – never change OOB files!)? Should do it, right?
Should. Such a powerful word.
First, SPAlert.Filter doesn’t seem to support CAML queries predicating over Multichoice fields, and that’s exactly what I needed. (I assume so because, tried to predicate on other fields and worked great.) Second issue, SPAlert.Filter seems to have a limitation on the length of the CAML string. Then, SPAlerts can be set to immediate, daily or weekly frequency. Guess what: client wanted daily, weekly and monthly updates.
Enough.
What about customizing the task? That’s what I ended up doing, and it simply worked like a charm. (Needless to say, it needs templating the body, avoiding hardcoding last run date, wrapping it into a job definition, etc etc, but the core is there.)
Here’s the code:
// build mail body
StringBuilder body = new StringBuilder();
// get items starting after last run of this job
DateTime lastRun = new DateTime(2011, 9, 8);
string lastRunForQuery = SPUtility.CreateISO8601DateTimeFromSystemDateTime(lastRun);
// get items from custom list
string siteUrl = "https://localhost/sites/blank";
using (SPSite site = new SPSite(siteUrl))
{
string query = @"<Where>
<And>
<Gt>
<FieldRef Name='Created' />
<Value IncludeTimeValue='TRUE' Type='DateTime'>" + lastRunForQuery + @"</Value>
</Gt>
<Or>
<Contains>
<FieldRef Name='Audiences' />
<Value Type='MultiChoice'>Audience1</Value>
</Contains>
<Contains>
<FieldRef Name='Audiences' />
<Value Type='MultiChoice'>Audience2</Value>
</Contains>
</Or>
</And>
</Where>";
SPQuery q = new SPQuery();
q.Query = query;
q.RowLimit = 50;// perf: limit # of items
// perf: set q.ViewFields in order to return only required fields
SPListItemCollection items = site.RootWeb.Lists["Test"].GetItems(q);
foreach (SPListItem i in items)
{
body.Append(i.Title);
}
// get items from user feed
SPServiceContext sc = SPServiceContext.GetContext(site);
UserProfileManager upm = new UserProfileManager(sc);
UserProfile up = upm.GetUserProfile(@"corp\user");
ActivityManager am = new ActivityManager(up, sc);
foreach (ActivityEvent e in am.GetActivitiesByUser(up, lastRun))
{
body.Append(e.TemplateVariable);
}
// send email
SPUtility.SendEmail(site.RootWeb, false, true, "user@corp.com", "Notifications", body.ToString(), false);
}