{"id":1446,"date":"2012-07-31T17:01:12","date_gmt":"2012-07-31T22:01:12","guid":{"rendered":"http:\/\/anvil-of-time.com\/wordpress\/?p=1446"},"modified":"2021-03-11T12:35:59","modified_gmt":"2021-03-11T17:35:59","slug":"sending-icalendar-events-via-a-net-assembly-and-sqlserver-stored-procedure","status":"publish","type":"post","link":"https:\/\/anvil-of-time.com\/ms-sql-server\/sending-icalendar-events-via-a-net-assembly-and-sqlserver-stored-procedure\/","title":{"rendered":"Sending iCalendar events via a .Net Assembly and SQLServer stored procedure"},"content":{"rendered":"<p>As I&#8217;ve mentioned in earlier posts, the iCalendar format is a standard way to send event information to a variety of email\/scheduling systems (Outlook, Google, etc.). Here is a way to set it up so that you can simply call a stored procedure to send the event. This assumes you have SQL Server set up with access to Exchange.<\/p>\n<p>In C# (I&#8217;m using Visual Studio 2008) create a class as indicated.<\/p>\n<pre name=\"code\" class=\"VB\">using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Data.SqlTypes;\nusing System.Data.SqlClient;\nusing Microsoft.SqlServer.Server;\nusing System.Net.Mail;\nusing System.Net.Mime;\n\nnamespace icalEmail\n{\n    public class StoredProcedures\n    {\n        [SqlProcedure]\n        public static void SendiCal(DateTime startDateTime, DateTime endDateTime, string emailSubject,\n           string userEmailAddress, string cnAttendee, string methodType, DateTime createdOn, string notes, string UID, string location, string seqNo, string smtpserver, int smtpport)\n        {\n            \/\/ create the iCal string in the proper format\n            string iCal = CreateiCalFormat(startDateTime, endDateTime, emailSubject, userEmailAddress,\n            cnAttendee, methodType, createdOn, UID, notes, location, seqNo);\n            \/\/ create the MIME protocol Content-Type \n            var calendarType = new ContentType(&quot;text\/calendar;method=REQUEST; charset=UTF-8&quot;);\n            calendarType.Parameters.Add(&quot;method&quot;, &quot;REQUEST&quot;);\n\n            AlternateView caledarView = AlternateView.CreateAlternateViewFromString(iCal, calendarType);\n            caledarView.TransferEncoding = TransferEncoding.SevenBit;\n            \/\/ connect to smtpserver\n            var client = new SmtpClient(smtpserver, smtpport);\n            \/\/ create the email\n            var mailMesage = new MailMessage();\n            mailMesage.From = new MailAddress(&quot;donotreply@email.com&quot;);\n            mailMesage.To.Add(new MailAddress(userEmailAddress));\n            mailMesage.Subject = emailSubject;\n            mailMesage.Body = iCal;\n            mailMesage.AlternateViews.Add(caledarView);\n            client.Send(mailMesage);\n        }\n\n        private static string _dateFormat = &quot;yyyyMMddTHHmmssZ&quot;;\n        private static string CreateiCalFormat(DateTime startDateTime, DateTime endDateTime,\n        string emailSubject, string userEmailAddress, string cnAttendee, string methodType, DateTime createdOn, string UID,\n        string notes, string location, string seqNo)\n        {\n            string iCal =\n\n            &quot;BEGIN:VCALENDAR&quot; +\n\n            &quot;\\nPRODID:-\/\/SampleApp\/\/AoT\/\/EN&quot; +\n\n            &quot;\\nVERSION:2.0&quot; +\n            \/\/\/ REQUEST for add or update, CANCEL for cancellation\n            &quot;\\nMETHOD:&quot; + methodType +\n\n            &quot;\\nBEGIN:VEVENT&quot; +\n\n            &quot;\\nORGANIZER:CN=&#039;Matt&#039;&quot; +\n\n            \/\/&quot;\\nORGANIZER:MAILTO:matt.balent@anvil-of-time.com&quot; +\n\n            &quot;\\nATTENDEE;CN=&#039;&quot; + cnAttendee + &quot;&#039;&quot; +\n\n            &quot;;ROLE=REQ-PARTICIPANT;RSVP=TRUE;CN=&quot; + userEmailAddress + \n\n            &quot;\\nDTSTART:&quot; + startDateTime.ToUniversalTime().ToString(_dateFormat) +\n\n            &quot;\\nDTEND:&quot; + endDateTime.ToUniversalTime().ToString(_dateFormat) +\n\n            &quot;\\nSTATUS:CONFIRMED&quot; +\n\n            &quot;\\nTRANSP:OPAQUE&quot; +\n            \/\/\/ 0 for add, 1 for update or cancellation\n            &quot;\\nSEQUENCE:&quot; + seqNo +\n\n            &quot;\\nUID:&quot; + Guid.NewGuid() +\n            \/\/\/ resend original UID for updates and cancellations\n            \/\/&quot;\\nUID:&quot; + UID +\n\n            &quot;\\nDTSTAMP:&quot; + createdOn.ToUniversalTime().ToString(_dateFormat) +\n\n            &quot;\\nLAST-MODIFIED:&quot; + createdOn.ToUniversalTime().ToString(_dateFormat) +\n\n            &quot;\\nLOCATION:&quot; + location +\n\n            &quot;\\nDESCRIPTION:&quot; + notes +\n\n            &quot;\\nSUMMARY:&quot; + emailSubject +\n\n            &quot;\\nPRIORITY:5&quot; +\n\n            &quot;\\nCLASS:PUBLIC&quot; +\n\n            &quot;\\nEND:VEVENT&quot; +\n\n            &quot;\\nEND:VCALENDAR&quot;;\n\n            return iCal;\n        }\n\n    }\n}<\/pre>\n<p>This would be compiled into a .dll which needs to be registered in SQL Server. This assembly is to be marked as UNSAFE so someone with sysadmin priviges needs to register it.<\/p>\n<pre name=\"code\" class=\"VB\">CREATE ASSEMBLY [eventEmail]\nAUTHORIZATION [dbo]\nFROM &#039;C:\\temp\\icalemail.dll&#039;\nWITH PERMISSION_SET = UNSAFE<\/pre>\n<p>There is an interesting discussion of &#8216;UNSAFE&#8217; assemblies on <a title=\"Stackoverflow\" href=\"http:\/\/stackoverflow.com\/questions\/8795498\/how-to-mark-a-net-assembly-as-safe\" target=\"_blank\" rel=\"noopener\">Stackoverflow.<\/a><\/p>\n<p>Now create the stored procedure which will call the assembly.<\/p>\n<pre name=\"code\" class=\"VB\">create procedure dbo.usp_mb_eventnotify(@startDateTime datetime\n\t\t\t\t, @endDateTime datetime\n\t\t\t\t, @emailSubject nvarchar(80)\n\t\t\t\t, @emailSummary nvarchar(1000)\n\t\t\t\t, @location nvarchar(255)\n\t\t\t\t, @attendeeName nvarchar(100)\n\t\t\t\t, @attendeeEmail nvarchar(255)\n\t\t\t\t, @organizerName nvarchar(100)\n\t\t\t\t, @organizerEmail nvarchar(255)\n\t\t\t\t, @UID nvarchar(255)\n\t\t\t\t, @status nvarchar(12)\n\t\t\t\t, @requestType nvarchar(12)\n\t\t\t\t, @smtpserver nvarchar (255)\n\t\t\t\t, @smtpport bigint)\nas external name [iCalEmail].[iCalEmail.Storedprocedures].[SendiCal];<\/pre>\n<p>Examples of use:<\/p>\n<p>Create the event<\/p>\n<pre name=\"code\" class=\"VB\">exec dbo.usp_mb_eventnotify  \n&#039;2012-08-08 13:00:00&#039;,\n&#039;2012-08-08 15:00:00&#039;,\n&#039;BigProj 2&#039;,\n&#039;New schedule of Event sent by Matt&#039;,\n&#039;CONF01&#039;,\n&#039;Balent, Matt&#039;,\n&#039;matt.balent@anvil-of-time.com&#039;,\n&#039;AoT&#039;,\n&#039;donotreply@email.com&#039;,\n&#039;AOT372711c&#039;,\n&#039;CONFIRMED&#039;,\n&#039;REQUEST&#039;,\n&#039;1234.na.corp.aot.com&#039;,\n25<\/pre>\n<p>Update the event<\/p>\n<pre name=\"code\" class=\"VB\">exec dbo.usp_mb_eventnotify\t\t\t\t\n&#039;2012-08-08 10:00:00&#039;,\n&#039;2012-08-08 12:00:00&#039;,\n&#039;BigProj 2&#039;,\n&#039;New schedule of Event sent by Matt&#039;,\n&#039;CONF01&#039;,\n&#039;Balent, Matt&#039;,\n&#039;matt.balent@anvil-of-time.com&#039;,\n&#039;AoT&#039;,\n&#039;donotreply@email.com&#039;,\n&#039;AOT372711c&#039;,\n&#039;CONFIRMED&#039;,\n&#039;REQUEST&#039;,\n&#039;1234.na.corp.aot.com&#039;,\n25<\/pre>\n<p>Cancel the event<\/p>\n<pre name=\"code\" class=\"VB\">exec dbo.usp_mb_eventnotify \n&#039;2012-08-08 10:00:00&#039;,\n&#039;2012-08-08 12:00:00&#039;,\n&#039;BigProj 2&#039;,\n&#039;New schedule of Event sent by Matt&#039;,\n&#039;CONF01&#039;,\n&#039;Balent, Matt&#039;,\n&#039;matt.balent@anvil-of-time.com&#039;,\n&#039;AoT&#039;,\n&#039;donotreply@email.com&#039;,\n&#039;AOT372711c&#039;,\n&#039;CANCELLED&#039;,\n&#039;CANCEL&#039;,\n&#039;1234.na.corp.aot.com&#039;,\n25<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>As I&#8217;ve mentioned in earlier posts, the iCalendar format is a standard way to send event information to a variety of email\/scheduling systems (Outlook, Google, etc.). Here is a way to set it up so that you can simply call a stored procedure to send the event. This assumes you have SQL Server set up&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[47,54,8,10],"tags":[55,84,49,56,16,15],"_links":{"self":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/1446"}],"collection":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/comments?post=1446"}],"version-history":[{"count":10,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/1446\/revisions"}],"predecessor-version":[{"id":2047,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/1446\/revisions\/2047"}],"wp:attachment":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/media?parent=1446"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/categories?post=1446"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/tags?post=1446"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}