6

I'm looking for the best way to implement sending invitations from a SharePoint list of events.

Scenarios:

  • Create an Event
  • Creation of a repeating event
  • Exception recurrences
  • Delete an event

I was exploring options:

  • Create an event handler to send the mail, but I have trouble generating the ICS format
  • Use the option to export out of the box with some programming to make it more friendly

What approach would you recommend? Thanks in advance.


Possible solution

One possible solution I've been evaluating is the proposal in this blog.

Deliver meeting request from Sharepoint Calendar programmatically

Here they have developed a library (iCal.cs) that takes an item from a Events SharePoint list and creates the ical file. It is a good starting point, but there are points that still require further development:

  • Managing the list of attendees. In particular the addition or removal.
  • How to handle cancellations.

It should also be noted that this solution is based on a full calendar export and not the individual appointment.

Note: I do not say that this is the ideal solution. But it is a very good example of the problem being solved.


Sample exporting a complete SharePoint Calendar

The file "iCal Exporter 1.0 Source.zip" from The Community Kit for SharePoint helps to undestand de complexity of SharePoint Event List.


Understanding the SharePoint calendar

A must-o-read article accessing SharePoint calendars via the object model with so many different types of events – normal events, all-day events, recurring events, recurrence exceptions, and deleted instances

Understanding the SharePoint calendar and how to export it to iCal format


Functional description

Functional Description of requirement


More information

  • I know how to write event receiver
  • I know how to send the email
  • What are looking for is some code to translate events from calendar list to ical because this list has some complexity and diferents types of events
  • If you look in this blog you can see iCal.cs. This library take the complexity of the translation, but I think for a complete calendar translation. I am looking someting like this but to add in same event receivers. This library shows the complexity behind. And my intention is not to develop it from scratch.
  • Event receivers in sharepoint calendar list are not "natural". For instance: when you modify an exception of a recurring appointment, an item for the exception is created. And the recurring item changes. Two events are triggered. And you must decide in which event send the iCal file. There are a lot of combinations. Because of event type, exceptions, and more things
  • It is very strange here are not something out of the box. Because MS seems to have a way to generate Ical. Since there is a tab "custom action" in the event screen. Look here: Export (.ical) Individual Events from SharePoint Calendar
0

In the past, I was able to do it with Nintex Workflow, building the ICS file with the event properties and attaching it to an email.

You should be able to do it in an event receiver, generate the ICS with the item properties and attach it to an email and send it. ICS is a standard format so it shouldn't be too difficult to do.

  • Do you have any sample code? There are a lot of possible combinations. I think I am not the first trying to do this. Thanks for your answer. – Juan Pablo Pussacq Laborde Sep 12 '15 at 13:19
  • Unfortunately that was 2 jobs and 4 years ago, I don't have it anymore – Eric Alexander Sep 12 '15 at 16:32
  • Thank you. Too bad not having Nintex. In my experience with this tool, I have seen that works out fine features that SharePoint does not solve out of the box. – Juan Pablo Pussacq Laborde Sep 15 '15 at 12:05
  • I added more information to clarify the question. I hope it will be useful! – Juan Pablo Pussacq Laborde Sep 15 '15 at 14:48
  • The process I had was a bit different, these were people signing up for an event and that would generate the iCal based off that instance, not necessarily the creation of a new event. – Eric Alexander Sep 15 '15 at 14:52
0

Our dev team generate the attachment on the fly like this:

public class MyData
{
  ....
  public Dictionary<string, Stream> Attachments { get; set; }
  ...
  private void CreateAttachment(int priority)
    {
        string[] lines = { "BEGIN:VCALENDAR", "PRODID:-//Flo Inc.//FloSoft//EN", "BEGIN:VEVENT", "DTSTART:" + this.BeginDate.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"), "DTEND:" + this.EndDate.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"), "LOCATION:" + this.Location, "DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" + this.Description, "SUMMARY:" + this.Title, "PRIORITY:" + priority, "END:VEVENT", "END:VCALENDAR" };
        var memoryStream = new MemoryStream();
        var writer = new StreamWriter(memoryStream);
        foreach (var line in lines)
        {
            writer.WriteLine(line);
        }

        writer.Flush();
        memoryStream.Seek(0, SeekOrigin.Begin);
        this.Attachments = new Dictionary<string, Stream> { { AttachmentName, memoryStream } };
    }
...
}

Later we use the class:

...
var mailData = new MyData(...);
mailData. ... // Assignments and provoke MyData.CreateAttachment() call.
...
var mailMessage = new System.Net.Mail.MailMessage { From = new MailAddress(outboundMailSenderAddress), IsBodyHtml = asHtml, Subject = subject, Body = body };
mailMessage.Attachments.Add(mailData);
...
var smtpClient = new SmtpClient(smtpServerAddress);
smtpClient.Send(mailMessage);

And the attachments arrives. But is a ics attachment of the mail in our case, not an invitation per se, that's our specific requirement in my case. Hope it helps.

  • By the way, we use it on the context of an event handler, like you declare are exploring. – nilsandrey Sep 14 '15 at 14:39
  • Thank you very much for the answer. Do you have the code to break SharePoint events? I mean the management of recurrences and exceptions. – Juan Pablo Pussacq Laborde Sep 14 '15 at 17:15
  • I'm not sure to follow. This code was used on event receivers for a list of type calendar. Do you want the code for the event receiver class? That kind of event receiver always fire with a subscription for the specific situations of creation, modification and deletion. On the code the calendar-event data can be analyzed and response consequently. – nilsandrey Sep 14 '15 at 22:25
  • Yes if you have. Because I don't understand how you are managing recurrent events. Thanks. – Juan Pablo Pussacq Laborde Sep 14 '15 at 22:27
  • So I'm analyzing, complexity in SharePoint is given in the management of recurrences, cancellations (delete event) and adding or removing participants. – Juan Pablo Pussacq Laborde Sep 15 '15 at 12:06
0

For generating ICS, you can use following code. It worked for me.

 class MailInvitation
    {
        public string Attendee { set; get; }
        public string To { set; get; }
        public string Location { set; get; }
        public string StartDate { set; get; }
        public string EndDate { set; get; }
        public string Subject { set; get; }
        public string Body { set; get; }
        string smtpServer = SPAdministrationWebApplication.Local.OutboundMailServiceInstance.Server.Address;
        string smtpFrom = SPAdministrationWebApplication.Local.OutboundMailSenderAddress;

        public void SendInvitation(MailInvitation message)
        {
            MailMessage mailMessage = new MailMessage("From mail address", message.To);
            MailAddress bcc = new MailAddress("bcc address");
            mailMessage.Bcc.Add(bcc);
            mailMessage.Subject = message.Subject;
            mailMessage.Body = message.Body;
            ContentType contentType = new System.Net.Mime.ContentType("text/calendar");
            contentType.Parameters.Add("method", "REQUEST");
            contentType.Parameters.Add("name", "MeetingAppointment.ics");
            AlternateView avCal = AlternateView.CreateAlternateViewFromString(IcsBuilder(message, mailMessage), contentType);
            mailMessage.AlternateViews.Add(avCal);
            SmtpClient smtpClient = new SmtpClient(smtpServer);
            smtpClient.Send(mailMessage);
        }

        private string IcsBuilder(MailInvitation message, MailMessage messageContent)
        {
            StringBuilder icsBuilder = new StringBuilder();
            var utcStartTime = Convert.ToDateTime(message.StartDate);
            var utcEndTime = Convert.ToDateTime(message.EndDate);
            var organizer = "Listen To Customer Site Admin";
            var attendee = message.Attendee;
            icsBuilder.AppendLine("BEGIN:VCALENDAR");
            icsBuilder.AppendLine("VERSION:2.0");
            icsBuilder.AppendLine("PRODID:-//Schedule a Meeting");
            icsBuilder.AppendLine("METHOD:REQUEST");
            icsBuilder.AppendLine("BEGIN:VEVENT");
            icsBuilder.AppendLine(string.Format("ORGANIZER;CN=\"{0}\":MAILTO:{1}", organizer, messageContent.From.Address));
            icsBuilder.AppendLine(string.Format("ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"{0}\":MAILTO:{1}", attendee,
                 message.To, message.To));
            // icsBuilder.AppendLine(string.Format("DTSAMP:{0:yyyyMMddTHHmmssZ}", utcStartTime));
            icsBuilder.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmss}", utcStartTime));
            icsBuilder.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmss}", utcEndTime));
            icsBuilder.AppendLine(string.Format("LOCATION:{0}", message.Location));
            icsBuilder.AppendLine(string.Format("UID:{0}", Guid.NewGuid()));
            icsBuilder.AppendLine(string.Format("DESCRIPTION", messageContent.Bcc));
            icsBuilder.AppendLine(string.Format("SUMMARY: {0}", messageContent.Subject));
            icsBuilder.AppendLine(string.Format("ORANIZER:MAILTO:{0}", messageContent.From.Address));
            // icsBuilder.AppendLine(string.Format("ATTENDEE;CN=\"{0}\";RSVP=TRUE:mailto:{1}", messageContent.To[0].DisplayName, messageContent.To[0].Address));
            icsBuilder.AppendLine(string.Format("X-ALT-DESC:FMTTYPE=text/html:{0}", messageContent.Body));
            return icsBuilder.ToString();
        }
    }
  • Thank you very much for the code is very useful. Do you have the code for decoding of the events listed type "events" in SharePoint. A way of detecting single, recurring appointment cancellations, and selection of participants? Thank you! – Juan Pablo Pussacq Laborde Sep 15 '15 at 12:04
  • I did not get. what do you mean by events listed type "events" in SharePoint? You can try event receiver for handling list events like add items, edit items and delete items – Atish Dipongkor - MVP Sep 15 '15 at 14:10
  • I'm using the word "event" for both. First, I create a list of "events" in SharePoint. This is the kind of list where calendar appointments can be loaded. SharePoint handles the logic of recurring appointments, exceptions, participants, etc. From there you can create an event handler in C # to send a mail with an attached iCal. But the complexity lies in transforming events of the SharePoint list to iCal format. This is due to the internal format used to store exceptions and recurring appointments. – Juan Pablo Pussacq Laborde Sep 15 '15 at 14:39
  • I added more information to clarify the question. I hope it will be useful! – Juan Pablo Pussacq Laborde Sep 15 '15 at 14:48
  • 1
    May we chat over here or skype? My skype id: du.atish@outlook.com – Atish Dipongkor - MVP Sep 15 '15 at 17:39
0

Please, let us know what is the problem you are trying to solve. Probably, there is a less complicated way for that than generating iCal.

In my case I created a solution for booking meeting rooms from SharePoint and used Exchange Web Services for sending invitations and suggesting time when all the attendees are free. Probably this way can work for you.

Using EWS you can do all the changes like adding/removing an attendee or changing the meeting rooms from the code and Exchange does all the necessary actions for that.

If it can work for you, I can share my experience in more detail.

Update 1. The first version of the solution used standard SharePoint calendar list and event receivers for transfering changes to Outlook. However this way was not great, because some users wanted to use Outlook for booking and we stumbled into synchronization issues.

V2 is a SharePoint hosted app and uses FullCalendar for displaying. This version has back-end which caches Meetings data from Exchange and proxies requests to it. This way allows our users book meeting rooms and invite users either from intranet or from Outlook. So, it doesn't make any difference whether the meeting was created from one system or from another; it is visible and managable in both systems.

  • Thanks for your answer. Question. Your solution use the standard calendar list of sharepoint? – Juan Pablo Pussacq Laborde Sep 17 '15 at 12:10
  • Added update1 with the answer – MikhailSP Sep 17 '15 at 12:45
  • Mikhail thanks for the update. Not sure if your solution serves. In our case this is the requirement: 1) You must use the SharePoint calendar list 2) must schedule appointments in SharePoint 3) should be sent to those attending appointments as iCal. Based on your experience, you think you can use EWS to serve this requirement? I really do not know that API. – Juan Pablo Pussacq Laborde Sep 17 '15 at 18:02
0

Maybe not a direct answer to your question, but maybe this will help you anyway and it might suffice in your scenario.

If you have an event in a calendar list, you can simply call this URL (example with SPO, should work in other versions too):

https://XXX.sharepoint.com/_vti_bin/owssvr.dll?CS=109&Cmd=Display&List={[GUID of your calendar List]}&CacheControl=1&ID=[ID OF YOU CALENDAR EVENT]&Using=event.ics

It would open a dialog in your mail client. The data of the event is extracted from the calendar element the URL is referencing. It does convert information about reoccurring events, but there are some limitations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.