Синхронизация календаря Sharepoint Foundation и Mozilla Thunderbird
Ожидает приглашения
К сожалению, календарь Thunderbird (точнее расширение Lightnini) не очень дружат с Sharepoint, попытки подвязать календарь ни к чему хорошему не привели.
Пришлось воспользоваться механизмом рассылки мероприятий по электронной почте. Для этого создаем приемник событий, подписываем его на тип Календарь и делаем уведомления по событиям:
Элемент добавлен
Элемент изменен
Элемент удаляется
Для события обновления код будет такой же, единственная разница, при вызове процедуры генерации письма-календаря нужно указать признак что это удаление — вторым параметром передать true.
При разработке использовалась статья за что автору большое спасибо.
Пришлось воспользоваться механизмом рассылки мероприятий по электронной почте. Для этого создаем приемник событий, подписываем его на тип Календарь и делаем уведомления по событиям:
Элемент добавлен
Элемент изменен
Элемент удаляется
public override void ItemAdded(SPItemEventProperties properties)
{ MailMessage mmMessage;
SPListItem item = properties.ListItem;
try
{
mmMessage = CreateMeetingRequest(item,false);
}
catch (Exception E)
{ //При ошибке отправляет письмо
mmMessage = new MailMessage();
mmMessage.From = new MailAddress("от кого");
mmMessage.To.Add("кому");
mmMessage.Body = "Добавление события в календарь "+item.ParentList.ParentWeb.Title+" "+item.ParentList.Title+" "+item.ID + E.Message;
}
SmtpClient smtp = new SmtpClient("Почтовый сервер", 25);
smtp.Send(mmMessage);
base.ItemAdded(properties);
}
public static MailMessage CreateMeetingRequest(SPListItem item,bool delete)
{
DateTime dtStart=(DateTime)item["EventDate"];
DateTime dtEnd=(DateTime)item["EndDate"];
string strSummary = @"" + item["Description"] + " < " + item.ParentList.ParentWeb.Site.RootWeb.Url + item.ParentList.DefaultDisplayFormUrl + @"?ID=" + item.ID + @" >";
string strSubject=""+item["Title"];
string strLocation=""+item["Location"];
SPFieldUserValue userValue = new SPFieldUserValue(item.ParentList.ParentWeb, item["Author"].ToString());
SPUser author = userValue.User;
string strOrganizerName = author.Name;
string strOrganizerEmail = author.Email;
Guid itemid = item.UniqueId;
MailAddressCollection macAttendeeList = new MailAddressCollection();
SPFieldUserValueCollection ParticipantsPicker;
ParticipantsPicker = (SPFieldUserValueCollection)(item["ParticipantsPicker"]);
foreach (SPFieldUserValue par in ParticipantsPicker)
{
macAttendeeList.Add(new MailAddress(par.User.Email));
}
//Create an instance of mail message
MailMessage mmMessage = new MailMessage();
// Set up the different mime types contained in the message
System.Net.Mime.ContentType typeText = new System.Net.Mime.ContentType("text/plain");
System.Net.Mime.ContentType typeHTML = new System.Net.Mime.ContentType("text/html");
System.Net.Mime.ContentType typeCalendar = new System.Net.Mime.ContentType("text/calendar");
// Add parameters to the calendar header
typeCalendar.Parameters.Add("method", "REQUEST");
typeCalendar.Parameters.Add("name", "meeting.ics");
// Create message body parts in text format
string strBodyText = "Type:Single Meeting\r\nOrganizer: {0}\r\nStart Time:{1}\r\nEnd Time:{2}\r\nTime Zone:{3}\r\nLocation: {4}\r\n\r\n*~*~*~*~*~*~*~*~*~*\r\n\r\n{5}";
strBodyText = string.Format(strBodyText, strOrganizerName, dtStart.ToLongDateString() + " " + dtStart.ToLongTimeString(),
dtEnd.ToLongDateString() + " " + dtEnd.ToLongTimeString(), System.TimeZone.CurrentTimeZone.StandardName,
strLocation, strSummary);
AlternateView viewText = AlternateView.CreateAlternateViewFromString(strBodyText, typeText);
mmMessage.AlternateViews.Add(viewText);
//Create the Body in HTML format
string strBodyHTML = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\r\n<HTML>\r\n<HEAD>\r\n<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=utf-8\">\r\n<META NAME=\"Generator\" CONTENT=\"MS Exchange Server version 6.5.7652.24\">\r\n<TITLE>{0}</TITLE>\r\n</HEAD>\r\n<BODY>\r\n<!-- Converted from text/plain format -->\r\n<P><FONT SIZE=2>Type:Single Meeting
\r\nOrganizer:{1}
\r\nStart Time:{2}
\r\nEnd Time:{3}
\r\nTime Zone:{4}
\r\nLocation:{5}
\r\n
\r\n*~*~*~*~*~*~*~*~*~*
\r\n
\r\n{6}
\r\n</FONT>\r\n</P>\r\n\r\n</BODY>\r\n</HTML>";
strBodyHTML = string.Format(strBodyHTML, strSummary, strOrganizerName, dtStart.ToLongDateString() + " " + dtStart.ToLongTimeString(),
dtEnd.ToLongDateString() + " " + dtEnd.ToLongTimeString(), System.TimeZone.CurrentTimeZone.StandardName,
strLocation, strSummary);
AlternateView viewHTML = AlternateView.CreateAlternateViewFromString(strBodyHTML, typeHTML);
mmMessage.AlternateViews.Add(viewHTML);
//Create the Body in VCALENDAR format
string status="CONFIRMED";
if (delete) status = "CANCELLED";
string strCalDateFormat = "yyyyMMddTHHmmssZ";
string strBodyCalendar = "BEGIN:VCALENDAR\r\nMETHOD:REQUEST\r\nPRODID:Microsoft CDO for Microsoft Exchange\r\nVERSION:2.0\r\nBEGIN:VTIMEZONE\r\nTZID:(GMT-06.00) Central Time (US & Canada)\r\nX-MICROSOFT-CDO-TZID:11\r\nBEGIN:STANDARD\r\nDTSTART:16010101T020000\r\nTZOFFSETFROM:-0500\r\nTZOFFSETTO:-0600\r\nRRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU\r\nEND:STANDARD\r\nBEGIN:DAYLIGHT\r\nDTSTART:16010101T020000\r\nTZOFFSETFROM:-0600\r\nTZOFFSETTO:-0500\r\nRRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU\r\nEND:DAYLIGHT\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTAMP:{8}\r\nDTSTART:{0}\r\nSUMMARY:{7}\r\nUID:{5}\r\nATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"{9}\":MAILTO:{9}\r\nACTION;RSVP=TRUE;CN=\"{4}\":MAILTO:{4}\r\nORGANIZER;CN=\"{3}\":mailto:{4}\r\nLOCATION:{2}\r\nDTEND:{1}\r\nDESCRIPTION:{6}\\N\r\nSEQUENCE:1\r\nPRIORITY:5\r\nCLASS:\r\nCREATED:{8}\r\nLAST-MODIFIED:{8}\r\nSTATUS:"+status+"\r\nTRANSP:OPAQUE\r\nX-MICROSOFT-CDO-BUSYSTATUS:BUSY\r\nX-MICROSOFT-CDO-INSTTYPE:0\r\nX-MICROSOFT-CDO-INTENDEDSTATUS:BUSY\r\nX-MICROSOFT-CDO-ALLDAYEVENT:FALSE\r\nX-MICROSOFT-CDO-IMPORTANCE:1\r\nX-MICROSOFT-CDO-OWNERAPPTID:-1\r\nX-MICROSOFT-CDO-ATTENDEE-CRITICAL-CHANGE:{8}\r\nX-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE:{8}\r\nBEGIN:VALARM\r\nACTION:DISPLAY\r\nDESCRIPTION:REMINDER\r\nTRIGGER;RELATED=START:-PT00H15M00S\r\nEND:VALARM\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n";
strBodyCalendar = string.Format(strBodyCalendar, dtStart.ToUniversalTime().ToString(strCalDateFormat), dtEnd.ToUniversalTime().ToString(strCalDateFormat),
strLocation, strOrganizerName, strOrganizerEmail, itemid.ToString("B"), strSummary, strSubject,
DateTime.Now.ToUniversalTime().ToString(strCalDateFormat), macAttendeeList.ToString());
AlternateView viewCalendar = AlternateView.CreateAlternateViewFromString(strBodyCalendar, typeCalendar);
viewCalendar.TransferEncoding = TransferEncoding.SevenBit;
mmMessage.AlternateViews.Add(viewCalendar);
//Adress the message
mmMessage.From = new MailAddress(strOrganizerEmail);
foreach (MailAddress attendee in macAttendeeList)
{
mmMessage.To.Add(attendee);
}
mmMessage.Subject = strSubject;
return mmMessage;
}
Для события обновления код будет такой же, единственная разница, при вызове процедуры генерации письма-календаря нужно указать признак что это удаление — вторым параметром передать true.
При разработке использовалась статья за что автору большое спасибо.