Search This Blog

Thursday, October 7, 2010

Develop a SharePoint 2007 Event Handler (Part 3)

This is part three of a multi-part article.

For Part 1 see this link - Part 1.
For Part 2 see this link - Part 2.
For Part 4 see this link - Part 4.

1. To begin our development we will add the following class level variables for our due date calculations:

a. We will use this variable to determine the date offset for Holidays and weekends:

DateTime dtgToday = DateTime.Today;

b. We will use this variable to hold the holidays date from the Holidays list:

string strHolidays = "";

2. In order to work properly the application needs to know which sites, lists, libraries, views etc. it is manipulating. To accomplish this we will add the following class level variables to our application:

a. We will use a variable to hold the Absolute URL of the site (we need to use a specific site URL rather than a more general contextual reference because we only want this event handler to run on one specific site).

string strUrl = "http://MySPServer/sites/solutions/ContactUs/default.aspx";

b. Next, we need to instantiate an SPSite object based on the Absolute URL string:

SPSite siteCollection = new SPSite(strUrl);

c. And then we open the specific site passed through the URL string using the OpenWeb method of the SPSite class:

SPWeb web = siteCollection.OpenWeb();

3. Now we will just need a few more class level variables for our Holiday list and All Items view, because the application needs to pull from this list to perform it’s due date calculations:

a. The first variable will instantiate is a SPList object for the Holiday list:

SPList listHolidays = web.Lists["Holidays"];

b. Then we need to set the SPView properties to the “All Items” view:

SPView viewHolidays = listHolidays.Views["All Items"];

c. Finally we instantiate a SPListItemCollection and populate it with the items from the Holidays list, All Items view by using the GetItems method:

SPListItemCollection itemsHolidays = listHolidays.GetItems(viewHolidays);

4. The next code group will involves calculating the change to the Due Date when a Holiday falls during the two business days. Essentially, if you receive an e-mail on Tuesday, and you have two business days to respond, but Thursday is Thanksgiving, this calculation will add one more day to the due date to compensate for the holiday. The code simply loops through the collection of holiday dates from the Holidays list, All Items view, and if the Holiday date is equal to today (the day you receive the e-mail) or today + 1 (1 business day from today) or today + 2 (2 business days from today) then it will add one day to the dtgToday variable, which effectively extends the due date 1 day.

foreach (SPListItem item in itemsHolidays)
{
strHolidays = (string)item.Fields.GetField("Holiday Date").GetFieldValue(item["Holiday Date"].ToString());
if(dtgToday.ToString() == strHolidays
dtgToday.AddDays(+1).ToString() == strHolidays
dtgToday.AddDays(+2).ToString() == strHolidays)
{
dtgToday = dtgToday.AddDays(+1);
}

5. Now we will extract the metadata from the incoming e-mail and add it to the Inbox list, below is the code we need to start with. This code is pretty self explanatory; to begin with, we create a SPListItem object and set its properties equal to the collection of items in the List object. Now, you may ask, where did we declare List object? In the parameters of the overridden EmailReceived method call (see the previous article). Next we set each list item value on the left equal to the e-mail message value on the right. The only exception is the value of the Date Received field which we set equal to the dtgToday variable.

SPListItem Item = List.Items.Add();
{
SPListItem ListItem = List.Items.Add();
ListItem["E-mail Sender"] = Message.Sender.ToString();
ListItem["E-mail From"] = Message.Headers["From"];
ListItem["E-mail To"] = Message.Headers["To"];
ListItem["E-mail Cc"] = Message.Headers["Cc"];
ListItem["E-mail Subject"] = Message.Headers["Subject"];
ListItem["Title"] = Message.Headers["Subject"];
ListItem["E-mail Body"] = Message.HtmlBody;
ListItem["Date Received"] = dtgToday.ToShortDateString();

6. Now we only have one list field value left to set, the all important Due Date field. For our Due Date field we need to account for weekends so that we only count 2 business days. The logic is simple, if the e-mail arrives on Monday, Tuesday or Wednesday, we just add 2 days to today’s date to equal the due date. If the e-mail arrives on Thursday, Friday, or Saturday we add 4 days to account for a full weekend. And finally, if the e-mail arrives on Sunday, we add three days to account for a half weekend.

if (dtgToday.DayOfWeek == DayOfWeek.Monday
dtgToday.DayOfWeek == DayOfWeek.Tuesday
dtgToday.DayOfWeek == DayOfWeek.Wednesday)
{
ListItem["Due Date"] = dtgToday.AddDays(+2).ToShortDateString();
}
else if (dtgToday.DayOfWeek == DayOfWeek.Thursday
dtgToday.DayOfWeek == DayOfWeek.Friday
dtgToday.DayOfWeek == DayOfWeek.Saturday)
{
ListItem["Due Date"] = dtgToday.AddDays(+4).ToShortDateString();
}
else if (dtgToday.DayOfWeek == DayOfWeek.Sunday)
{
ListItem["Due Date"] = dtgToday.AddDays(+3).ToShortDateString();
}

7. Now we only have to add logic to capture attachments. We will need to instantiate two related object types for this code, a SPAttachmentCollection object to add attachments in the list and a SPEmailAttachmentCollection to extract attachments from the e-mail. Essentially we will loop through the SPAttachmentCollection object collection and for each SPEmailAttachment item in the SPAttachmentCollection create a list attachment item. I also added some logic for capturing attachments sent from Outlook. Because Outlook saves it’s attachments in a proprietary format, these files cannot be added to SharePoint list – for more information see here.

SPAttachmentCollection itemAttachments = Item.Attachments;
SPEmailAttachmentCollection emailAttachments = Message.Attachments;
foreach (SPEmailAttachment emailAttachment in emailAttachments)
{
if (emailAttachment.FileName != "winmail.dat")
{
byte[] emailAttachmentbytes = new byte[emailAttachment.ContentStream.Length];
emailAttachment.ContentStream.Read(emailAttachmentbytes, 0, (int)emailAttachmentbytes.Length);
itemAttachments.Add(emailAttachment.FileName, emailAttachmentbytes);
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint added an attachement.";
}
else
{
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint cannot add these types of attachements.";
}
}

8. Finally, we just add the statement to update the list item, and we are done.

ListItem.Update();

9. In my next article I’ll provide the whole code listing as well as discuss how to deploy the event handler as a feature using WSPBuilder, and also some ways to debug the feature.


I hope that helps!

2 comments:

Jayu said...

Hi,

Can you please specify about list columns which need to added before installing this code?

Tom Molskow said...

Hey Jayu,

I have added the list column information to Part 1 of this series, paragraph 5 - see the link here.

Thanks for that suggestion!

Tom