Как стать автором
Обновить

Синхронизация календаря Sharepoint Foundation и Mozilla Thunderbird

К сожалению, календарь Thunderbird (точнее расширение Lightnini) не очень дружат с Sharepoint, попытки подвязать календарь ни к чему хорошему не привели.
Пришлось воспользоваться механизмом рассылки мероприятий по электронной почте. Для этого создаем приемник событий, подписываем его на тип Календарь и делаем уведомления по событиям:

Элемент добавлен
Элемент изменен
Элемент удаляется

 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.

При разработке использовалась статья за что автору большое спасибо.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.