Manually creating ICS files and sending from SharePoint

In a previous post I created Outlook appointments using Microsoft.Office.Interop, a limitation of using this method means MS Outlook is required to be installed on the server.

To avoid this limitation it’s possible to create an Outlook appointment manually and send as an attachment, you still have full control over the content and behaviour of the appointment file, known as a .ICS file.

There are various examples on the web of how to do this, but I struggled to find one that met my exact requirements, my requirements were:

  • Dynamically populate the ICS file with content from a custom webpart within SharePoint.
  • Send the email with attachment using the configuration stored within SharePoint (Outgoing SMTP Server, sender address).
  • Ability for the recipient to accept the invitation, to enable the employee calendar to be updated, with no meeting organiser.

What the code does… Creates a new instance of MailMessage, specifics the SMTP Server, Sender Address, and a couple of other properties.
P.S. I’m not managing garbage collection within this area of code..Also the variable ‘appointment’ is a class that I created to store the variables from the SharePoint webpart.

MailMessage messageContent = new MailMessage();
SPSite site = SPContext.Current.Site;
SPWeb web = site.OpenWeb();
string senderAddress = web.Site.WebApplication.OutboundMailSenderAddress;
string smtpServer = web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
messageContent.From = new MailAddress(web.Site.WebApplication.OutboundMailSenderAddress);
messageContent.To.Add(new MailAddress("appointment.recipient");
messageContent.Subject = appointment.Subject;
messageContent.Body = appointment.Body;

The next part builds the ICS file as a string. I found these properties by sending meeting invitations to my Gmail account and opening the appointment file in Notepad to understand what parameters I required.

StringBuilder icsBuilder = new StringBuilder();
            icsBuilder.AppendLine("PRODID:-//Schedule a Meeting");
            icsBuilder.AppendLine(string.Format("DTSAMP:{0:yyyyMMddTHHmmssZ}", DateTime.Now));
            icsBuilder.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", appointment.StartDateTime));
            icsBuilder.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmssZ}", appointment.EndDateTime));
            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("X-ALT-DESC:FMTTYPE=text/html:{0}", messageContent.Body));

I couldn’t use the send mail functionality available in SPUtility as I was unable to add attachments, there may be better ways of sending the actually email with the attachments.

Below, I’m using the standard System.Net.Mail functionality:

System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient();
smtpClient.Host = smtpServer;
smtpClient.UseDefaultCredentials = true;
System.Net.Mime.ContentType contentType = new System.Net.Mime.ContentType("text/calendar");
contentType.Parameters.Add("method", "REQUEST");
contentType.Parameters.Add("name", "MeetingAppointment.isc");
AlternateView view = AlternateView.CreateAlternateViewFromString(icsBuilder.ToString(), contentType);