C#, Sharepoint – Send appointment without using Outlook Object

Two months ago I wrote a small blog about my new project on creating a  SharePoint Webpart for sending appointment. Today a reader asks me how I solve my task at sending appointment without using Outlook Object so I decide to publish my code for sharing with who needs it. In this project I should create a Webpart to send Outlook appointment without using the available Outlook Object. The using of Outlook Object will require that man must install Microsoft Outlook in server and this installation is not worth for supporting only a small Webpart. Therefore in my code I only use classes provided by .Net Framework and do not use any Outlook Object.

using System.Net;
using System.Net.Mail;
using System.Net.Mime;


private void btnSend_Click(object sender, EventArgs e)
{
//Declaration a list of attendees
MailAddressCollection macCollection = new MailAddressCollection();
//Add attendde. In this example, I send invite to only one
macCollection.Add(new MailAddress("attendee_email"));
//Create mail message
MailMessage mmMessage = CreateMeetingRequest(DateTime.Now.AddHours(1), DateTime.Now.AddHours(2), "Test", "Test", "Test", "yourname", "youremailaddress", macCollection);
//Create smtp client
SmtpClient smtp = new SmtpClient("yoursmtp", 25);
//Configure your smtp client
smtp.EnableSsl = false;
smtp.Credentials = new NetworkCredential("yourloginname", "password");
//Send it
smtp.Send(mmMessage);
}

public static MailMessage CreateMeetingRequest(DateTime dtStart, DateTime dtEnd, string strSubject, string strSummary,
string strLocation, string strOrganizerName, string strOrganizerEmail,
MailAddressCollection macAttendeeList)
{
//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<BR>\r\nOrganizer:{1}<BR>\r\nStart Time:{2}<BR>\r\nEnd Time:{3}<BR>\r\nTime Zone:{4}<BR>\r\nLocation:{5}<BR>\r\n<BR>\r\n*~*~*~*~*~*~*~*~*~*<BR>\r\n<BR>\r\n{6}<BR>\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 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 &amp; 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:{7}\\N\r\nSEQUENCE:1\r\nPRIORITY:5\r\nCLASS:\r\nCREATED:{8}\r\nLAST-MODIFIED:{8}\r\nSTATUS:CONFIRMED\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, Guid.NewGuid().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;
}

20 thoughts on “C#, Sharepoint – Send appointment without using Outlook Object”

  1. I tried with this above code
    its trows Failure Sending Mail
    Please guide me the fix

    Advance Thanks
    Jenkins

  2. @Jenkins: Post the complete error message here and I will help you. Maybe your username name,password are wrong or your smtp is wrong. I have no clue to help you until I have an error message from you.

  3. Hi guys,

    I used this example and it works fine, but this code create only a new appointment. I need to modify, to cancel or report an appointment that I created.

    did some one has any solution?

    thx.

  4. Hi, i believe that this is an outlook meeting request and not an appointment. Is it possible that we generate an appointment and NOT a meeting request?

    Thanks in advance
    Red

  5. Terrific article..

    I had issues earlier with Outlook Inter op but this works great in my server farm with no Outlook.

    Thanks for the post and I would really appreciate if you can let me know how do we update an existing meeting request (things such as adding/removing members, editing the description etc)

    Thanks

  6. Thank you for this post.
    But the real challenge of sending a meeting request outside outlook is the changes and updates that will be added later on into the request. As you know 90% of the meeting request will be reschedule and updated, which won’t be possible if you just sent it outside outlook. The only way you will end up sending a new request and asking the users to delete the old request manually.

  7. @Memo: I totally agreed with you. This source code is just a demo for sending appointment without helping from Microsoft Outlook. If you know about how to edit the meeting request later then share it with us. That is always appreciated.

  8. Great Post!!

    To edit the meeting is necessary to save the setting UID nUID:{5}). Outlook detects the UID and searches the database of the calendar if the meeting is that it may modify or cancel, adding the STATUS parameter. To cancel = STATUS: CANCELLED; To Edit only send the same data with the same UID meeting and the meeting will be rescheduled.

  9. Thanks!

    Your code saved me a lot of time and work like a gem. Great, Keep it Up!

  10. Well this code works fine if I use outlook 2007, but when I use Outlook 2003 it does not, can anyone help me to sort out this problem, please.

  11. Jayesh:
    Upgrade to Outlook 2007 atleast man… The latest version is 2010, so basically its been 7 years since that went obsolete.

  12. I searched all around and found this blog, used your code to implement the calendar function, it worked using my SMTP. Thanks a lot to share the technique and I should say you have a great coding practice.

  13. Thanks a lot, really it helped me lot. I need some smaller changes in this
    I want to add ‘more details » Going? Yes – Maybe – No’ instead of ‘Add to calendar »’. Can u please help me?

Leave a Reply

Your email address will not be published. Required fields are marked *