iCal (ICS) is a file format which describes calendar events, including appointments (meeting requests), ordinary events, recurring events, reminders, etc. To exchange events over e-mail, iCal entries can be added to an e-mail. Outlook and many other e-mail systems can automatically extract iCal entries from e-mails to update their calendars, allow the user to accept or decline meeting request, and so on. iCal files usually have .ics extension.
MailBee.NET allows you to perform all kinds of operations defined for iCal, so that you can create meeting requests and send them to attendees, respond to meeting requests from other persons, analyze responses from attendees, create ordinary and recurring events, use reminders, etc.
vCard (VCF) is a file format for exchanging contact information (where contact can be any person or organization). With MailBee.NET, you can create or parse vCard data, including contacts' photos. vCard files usually have .vcf extension.
In MailBee.NET, iCal and vCard functionality is not the part of MailBee.NET.dll. Instead, it resides in a separate .DLL. It's called ICalVCard.dll, and installed in "C:\Program Files (x86)\MailBee.NET Objects". Thus, you need to add a reference to this .DLL (in addition to MailBee.NET.dll reference) if you plan to use iCal or vCard feature. Like MailBee.NET.dll, ICalVCard.dll is also installed in GAC by MailBee.NET Objects installer, and can be found in Add Reference dialog of Visual Studio.
To install via NuGet:
Install-Package ICalVCard
ICalVCard is only available for classic .NET Framework v2.0-4.8 and not yet compatible with .NET Core and UWP.
ICalVCard.dll has separate documentation, and the source code is publicly available. You can read more at: https://afterlogic.com/mailbee-net/icalvcard. The functionality of this .DLL is free, no license key required for any classes.
As for class reference, you can use online documentation or download .CHM file.
Please note that the support of ICalVCard.dll from AfterLogic is limited. This is a community project, based on other open source projects, and provided as-is. Still, the samples below should provide a good starting point as the highlight most of typical cases of iCal and vCard usage.
For iCal, you may find the ical.NET library from https://github.com/rianjs/ical.net more stable and flexible. It's based on the same project as ICalVCard.dll so porting your code to ical.NET shouldn't be a big deal.
ICalVCard.dll uses streams for data input and output and does not use any classes of MailBee.NET. Thus, you can even use it without MailBee.NET at all (although this case has never been tested).
This sample loads the message from an .EML file (it's assumed the message has a vCard attachment) and displays several fields from the vCard user profile:
using System; using MailBee.Mime; using vCards; class Sample { static void Main(string[] args) { MailMessage msg = new MailMessage(); msg.LoadMessage(@"C:\Docs\vcard.eml"); foreach (Attachment attach in msg.Attachments) { if (attach.IsVCard) { vCard crd = new vCard(attach.GetData()); Console.WriteLine("Name: " + crd.FormattedName); Console.WriteLine("Title: " + crd.Title); Console.WriteLine("BirthDate: " + crd.BirthDate); Console.WriteLine("Organization: " + crd.Organization); foreach (vCardPhone phone in crd.Phones) { if (phone.IsCellular) { Console.WriteLine("Cellular phone number: " + phone.FullNumber); } else if (phone.IsHome) { Console.WriteLine("Home phone number: " + phone.FullNumber); } else if (phone.IsWork) { Console.WriteLine("Work phone number: " + phone.FullNumber); } else if (phone.IsFax) { Console.WriteLine("Fax number: " + phone.FullNumber); } } } } } }
Imports System Imports MailBee.Mime Imports vCards Class Sample Shared Sub Main(ByVal args() As String) Dim msg As MailMessage = New MailMessage msg.LoadMessage("C:\Docs\vcard.eml") Dim attach As Attachment For Each attach In msg.Attachments If attach.IsVCard Then Dim crd As vCard = New vCard(attach.GetData()) Console.WriteLine("Name: " & crd.FormattedName) Console.WriteLine("Title: " & crd.Title) Console.WriteLine("BirthDate: " & crd.BirthDate) Console.WriteLine("Organization: " & crd.Organization) Dim phone As vCardPhone For Each phone In crd.Phones If phone.IsCellular Then Console.WriteLine("Cellular phone number: " & phone.FullNumber) ElseIf phone.IsHome Then Console.WriteLine("Home phone number: " & phone.FullNumber) ElseIf phone.IsWork Then Console.WriteLine("Work phone number: " & phone.FullNumber) ElseIf phone.IsFax Then Console.WriteLine("Fax number: " & phone.FullNumber) End If Next End If Next End Sub End Class
We assume you've added references to MailBee.NET.dll and ICalVCard.dll (MailBee.NET.4.dll and ICalVCard.4.dll if you target .NET Framework 4.0 or higher). The sample loads the e-mail from a file but you can download it from a POP3 or IMAP server or get it from any other source (like in the next sample).
This sample shows how to display Name and Surname with photo from vCard in a simple Windows Forms application. You should add two Label controls on the form for text output and a PictureBox control to display the image.
// Add to the beginning of your code file. using System.IO; using MailBee.Mime; using MailBee.ImapMail; using vCards; // The actual code snippet. MailMessage msg = Imap.QuickDownloadMessage("mail.domain.com", "jdoe", "secret", "Inbox", -1); foreach (Attachment attach in msg.Attachments) { if (attach.IsVCard) { vCard crd = new vCard(attach.GetData()); label1.Text = crd.GivenName; label2.Text = crd.FamilyName; pictureBox1.Image = Image.FromStream( new MemoryStream(crd.Photos[0].GetBytes())); } }
' Add to the beginning of your code file. Imports System.IO Imports MailBee.Mime Imports MailBee.ImapMail Imports vCards ' The actual code snippet. Dim msg As MailMessage = _ Imap.QuickDownloadMessage("mail.domain.com", "jdoe", "secret", "Inbox", -1) Dim attach As Attachment For Each attach In msg.Attachments If attach.IsVCard Then Dim crd As vCard = New vCard(attach.GetData()) label1.Text = crd.GivenName label2.Text = crd.FamilyName pictureBox1.Image = Image.FromStream( _ New MemoryStream(crd.Photos(0).GetBytes())) End If Next
We assume MailBee.Global.LicenseKey is already set in app.config, registry, etc. If not, you can set it in the code.
Note that vCard photos can be of different formats (.BMP, .JPG) but PictureBox control can handle both of them.
This sample creates a vCard user profile with a photo and sends it to a recipient. The sample does not set any body in the message but you can add it if you need to.
using System; using System.IO; using System.Text; using MailBee.Mime; using MailBee.SmtpMail; using vCards; class Sample { static void Main(string[] args) { // Create a new contact. vCard crd = new vCard(); crd.GivenName = "John"; crd.FamilyName = "Smith"; crd.Gender = vCardGender.Male; crd.BirthDate = new DateTime(1980, 3, 2); crd.Phones.Add(new vCardPhone("123-456-789", vCardPhoneTypes.Cellular)); crd.Phones.Add(new vCardPhone("893-111-789", vCardPhoneTypes.Home)); crd.Phones.Add(new vCardPhone("222-555-333", vCardPhoneTypes.Work)); // We assume this file exists and contains the contact photo. vCardPhoto photo = new vCardPhoto(@"C:\Docs\john_smith.jpg"); crd.Photos.Add(photo); MailMessage msg = new MailMessage(); msg.From.AsString = "Me <from@domain.com>"; msg.To.AddFromString("You <to@company.com>"); msg.Subject = "See attached vCard"; vCardStandardWriter wrt = new vCardStandardWriter(); StringWriter sw = new StringWriter(); // Specify charset to encode non-ascii strings. Use Western-European // encoding in this sample (you can also use UTF-8 or whatever). wrt.Write(crd, sw, "windows-1252"); // Add vCard as attachment. msg.Attachments.Add( Encoding.GetEncoding("windows-1252").GetBytes(sw.ToString()), "John Smith.vcf", null, "application/octet-stream", null, NewAttachmentOptions.None, MailTransferEncoding.QuotedPrintable); // Send resulting e-mail in "direct send" mode. You can also send it via // SMTP relay (see Smtp.Send for details). Smtp.QuickSend(msg); } }
Imports System.IO Imports System.Text Imports MailBee.Mime Imports MailBee.SmtpMail Imports vCards Class Sample Shared Sub Main(ByVal args As String()) ' Create a new contact. Dim crd As New vCard() crd.GivenName = "John" crd.FamilyName = "Smith" crd.Gender = vCardGender.Male crd.BirthDate = New DateTime(1980, 3, 2) crd.Phones.Add(New vCardPhone("123-456-789", vCardPhoneTypes.Cellular)) crd.Phones.Add(New vCardPhone("893-111-789", vCardPhoneTypes.Home)) crd.Phones.Add(New vCardPhone("222-555-333", vCardPhoneTypes.Work)) ' We assume this file exists and contains the contact photo. Dim photo As New vCardPhoto("C:\Docs\john_smith.jpg") crd.Photos.Add(photo) Dim msg As New MailMessage() msg.From.AsString = "Me <from@domain.com>" msg.[To].AddFromString("You <to@company.com>") msg.Subject = "See attached vCard" Dim wrt As New vCardStandardWriter() Dim sw As New StringWriter() ' Specify charset to encode non-ascii strings. Use Western-European ' encoding in this sample (you can also use UTF-8 or whatever). wrt.Write(crd, sw, "windows-1252") ' Add vCard as attachment. msg.Attachments.Add(Encoding.GetEncoding("windows-1252").GetBytes(sw.ToString()), _ "John Smith.vcf", Nothing, "application/octet-stream", Nothing, _ NewAttachmentOptions.None, MailTransferEncoding.QuotedPrintable) ' Send resulting e-mail in "direct send" mode. You can also send it via ' SMTP relay (see Smtp.Send for details). Smtp.QuickSend(msg) End Sub End Class
We assume MailBee.Global.LicenseKey is already set in app.config, registry, etc. If not, you can set it in the code.
This sample sends two e-mails containing a meeting request (appointment) each. Attendees to which these meeting requests are sent to can then use their iCal-capable e-mail clients (like Outlook) to respond with Accept, Decline, or Tentative status.
The first meeting request is sent to two people (which demonstrates that you don't need to send individual e-mail to each attendee, you can list all attendees in the same e-mail).
The second meeting request is sent to demonstrate how to track multiple meeting requests. If we send multiple meeting requests for which we then get responses from their respective attendees, we need somehow match these responses and the original meeting requests to determine which response corresponds to which request.
For every meeting request, Unique-ID is generated. This Unique-ID has nothing to do with Unique-ID (UID) or Message-ID of e-mails, this is iCal Unique-ID. In this sample, we save all the generated iCal Unique-IDs in a file. We'll use the stored values in Analyze responses to appointment request sample to match meeting requests and responses.
using System; using System.IO; using System.Collections; using MailBee.Mime; using MailBee.SmtpMail; using iCal; using iCal.Serialization.iCalendar; // This sample sends meeting requests to some persons and saves the unique-id // assigned to that appointments into a file. These unique-ids are used to match // appointments and replies to them. ShowAcceptanceStatus sample can then read // this file to determine for which appointment the confirmation was received. class SendAppointment { static void Main(string[] args) { EmailAddress emailFrom = EmailAddress.Parse("Event Creator <jdoe@domain.com>"); // Attendees of meeting #1. EmailAddress meeting1attendee1 = EmailAddress.Parse("Person1 <alice@company.com>"); EmailAddress meeting1attendee2 = EmailAddress.Parse("Person2 <john@domain.com>"); // Attendee of meeting #2. EmailAddress meeting2attendee1 = EmailAddress.Parse("Person3 <bob@company.com>"); // SMTP settings. string smtpServer = "smtp.domain.com"; int smtpPort = 25; // Specify 465 for SSL. string username = "jdoe"; string password = "secret"; Smtp mailer = new Smtp(); SmtpServer srv = new SmtpServer(smtpServer, username, password); srv.Port = smtpPort; mailer.SmtpServers.Add(srv); // First meeting request e-mail, two recipients. MailMessage msg = mailer.Message; msg.From = emailFrom; msg.To.Add(meeting1attendee1); msg.To.Add(meeting1attendee2); msg.Subject = "iCal appointment with 2 recipients"; // Create event part. iCalendar iCal1 = new iCalendar(); iCal1.Method = "REQUEST"; Event evt1 = iCal1.Create<Event>(); evt1.Start = new iCalDateTime(DateTime.Today.AddDays(1)); evt1.End = evt1.Start.AddHours(1); evt1.IsAllDay = false; evt1.Summary = "Project meeting"; evt1.Location = "Conference room"; // Add recipients for appointment. Attendee att1 = new Attendee("mailto:" + meeting1attendee1.Email); att1.RSVP = true; att1.CommonName = meeting1attendee1.DisplayName; evt1.Attendees.Add(att1); Attendee att2 = new Attendee("mailto:" + meeting1attendee2.Email); att2.RSVP = true; att2.CommonName = meeting1attendee2.DisplayName; evt1.Attendees.Add(att2); iCalendarSerializer serializer1 = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer1.SerializeToString(iCal1); // Send first meeting request to 2 recipients. mailer.Send(); ArrayList eventList = new ArrayList(); // Save event's Unique-ID and recipients' e-mail addresses to our database. eventList.Add(iCal1.UniqueComponents[0].UID + ";" + meeting1attendee1.Email + ";"); eventList.Add(iCal1.UniqueComponents[0].UID + ";" + meeting1attendee2.Email + ";"); // Second meeting request e-mail, one recipient. msg.Reset(); msg.From = emailFrom; msg.To.Add(meeting2attendee1); msg.Subject = "iCal appointment with 1 recipient"; // Create event part. iCalendar iCal2 = new iCalendar(); iCal2.Method = "REQUEST"; Event evt2 = iCal2.Create<Event>(); evt2.Start = new iCalDateTime(DateTime.Today.AddDays(2)); evt2.End = evt2.Start.AddHours(1); evt2.IsAllDay = false; evt2.Summary = "Lunch"; evt2.Location = "Dinner room"; // Add recipients for appointment. Attendee att3 = new Attendee("mailto:" + meeting2attendee1.Email); att3.RSVP = true; att3.CommonName = meeting2attendee1.DisplayName; evt2.Attendees.Add(att3); iCalendarSerializer serializer2 = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer2.SerializeToString(iCal2); // Send second meeting request to 1 recipient. mailer.Send(); // Save event's Unique-ID and recipient's e-mail address to our database. eventList.Add(iCal2.UniqueComponents[0].UID + ";" + meeting2attendee1.Email + ";"); // Write database to disk. File.WriteAllLines(@"C:\Temp\eventUid.txt", (string[])eventList.ToArray(typeof(string))); } }
Imports System.IO Imports System.Collections Imports MailBee.Mime Imports MailBee.SmtpMail Imports iCal Imports iCal.Serialization.iCalendar ' This sample sends meeting requests to some persons and saves the unique-id ' assigned to that appointments into a file. These unique-ids are used to match ' appointments and replies to them. ShowAcceptanceStatus sample can then read ' this file to determine for which appointment the confirmation was received. Module SendAppointment Sub Main(ByVal args As String()) Dim emailFrom As EmailAddress = EmailAddress.Parse("Event Creator <jdoe@domain.com>") ' Attendees of meeting #1. Dim meeting1attendee1 As EmailAddress = EmailAddress.Parse("Person1 <alice@company.com>") Dim meeting1attendee2 As EmailAddress = EmailAddress.Parse("Person2 <john@domain.com>") ' Attendee of meeting #2. Dim meeting2attendee1 As EmailAddress = EmailAddress.Parse("Person3 <bob@company.com>") ' SMTP settings. Dim smtpServer As String = "smtp.domain.com" Dim smtpPort As Integer = 25 ' Specify 465 for SSL. Dim username As String = "jdoe" Dim password As String = "secret" Dim mailer As New Smtp() Dim srv As New SmtpServer(smtpServer, username, password) srv.Port = smtpPort mailer.SmtpServers.Add(srv) ' First meeting request e-mail, two recipients. Dim msg As MailMessage = mailer.Message msg.From = emailFrom msg.[To].Add(meeting1attendee1) msg.[To].Add(meeting1attendee2) msg.Subject = "iCal appointment with 2 recipients" ' Create event part. Dim iCal1 As New iCalendar() iCal1.Method = "REQUEST" Dim evt1 As [Event] = iCal1.Create(Of [Event])() evt1.Start = New iCalDateTime(DateTime.Today.AddDays(1)) evt1.End = evt1.Start.AddHours(1) evt1.IsAllDay = False evt1.Summary = "Project meeting" evt1.Location = "Conference room" ' Add recipients for appointment. Dim att1 As New Attendee("mailto:" & meeting1attendee1.Email) att1.RSVP = True att1.CommonName = meeting1attendee1.Email evt1.Attendees.Add(att1) Dim att2 As New Attendee("mailto:" & meeting1attendee2.Email) att2.RSVP = True att2.CommonName = meeting1attendee2.Email evt1.Attendees.Add(att2) Dim serializer1 As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer1.SerializeToString(iCal1) ' Send first meeting request to 2 recipients. mailer.Send() Dim eventList As New ArrayList() ' Save event's Unique-ID and recipients' e-mail addresses to our database. eventList.Add(iCal1.UniqueComponents(0).UID & ";" & meeting1attendee1.Email & ";") eventList.Add(iCal1.UniqueComponents(0).UID & ";" & meeting1attendee2.Email & ";") ' Second meeting request e-mail, one recipient. msg.Reset() msg.From = emailFrom msg.[To].Add(meeting2attendee1) msg.Subject = "iCal appointment with 1 recipient" ' Create event part. Dim iCal2 As New iCalendar() iCal2.Method = "REQUEST" Dim evt2 As [Event] = iCal2.Create(Of [Event])() evt2.Start = New iCalDateTime(DateTime.Today.AddDays(2)) evt2.End = evt2.Start.AddHours(1) evt2.IsAllDay = False evt2.Summary = "Lunch" evt2.Location = "Dinner room" ' Add recipients for appointment. Dim att3 As New Attendee("mailto:" & meeting2attendee1.Email) att3.RSVP = True att3.CommonName = meeting2attendee1.Email evt2.Attendees.Add(att3) Dim serializer2 As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer2.SerializeToString(iCal2) ' Send second meeting request to 1 recipient. mailer.Send() ' Save event's Unique-ID and recipient's e-mail address to our database. eventList.Add(iCal2.UniqueComponents(0).UID + ";" & meeting2attendee1.Email & ";") ' Write database to disk. File.WriteAllLines("C:\Temp\eventUid.txt", DirectCast(eventList.ToArray(GetType(String)), String())) End Sub End Module
As before, we assume MailBee.Global.LicenseKey is already set in app.config, registry, etc. If not, you can set it in the code.
In real code, you'll probably use SQL database (rather than a text file like it's done in this sample) to store and update meeting request details.
This sample creates an iCal event which does not assume a response from anybody is required. The e-mail program of the person which receives the e-mail with this event will just add this event into the local calendar, no question "Will you participate in this?" will be asked.
using System; using System.IO; using MailBee.Mime; using MailBee.SmtpMail; using iCal; using iCal.Serialization.iCalendar; class SendEvent { static void Main(string[] args) { EmailAddress emailFrom = EmailAddress.Parse("John Doe <jdoe@domain.com>"); // Attendee of meeting. EmailAddress meeting1attendee1 = EmailAddress.Parse("Alice <alice@company.com>"); MailMessage msg = new MailMessage(); msg.From = emailFrom; msg.To.Add(meeting1attendee1); msg.Subject = "Server backup"; // Create new event. iCalendar iCal = new iCalendar(); Event evt = iCal.Create<Event>(); evt.Start = new iCalDateTime(DateTime.Today.AddDays(1)); evt.End = evt.Start.AddHours(1); evt.IsAllDay = false; evt.Summary = "Server backup"; evt.Location = "Server room"; iCalendarSerializer serializer = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer.SerializeToString(iCal); // And send it (we use direct send here, you can send it via SMTP relay as well). Smtp.QuickSend(msg); } }
Imports System.IO Imports MailBee.Mime Imports MailBee.SmtpMail Imports iCal Imports iCal.Serialization.iCalendar Module SendEvent Sub Main(ByVal args As String()) Dim emailFrom As EmailAddress = EmailAddress.Parse("John Doe <jdoe@domain.com>") ' Attendee of meeting. Dim meeting1attendee1 As EmailAddress = EmailAddress.Parse("Alice <alice@company.com>") Dim msg As New MailMessage() msg.From = emailFrom msg.[To].Add(meeting1attendee1) msg.Subject = "Server backup" ' Create new event. Dim iCal As New iCalendar() Dim evt As [Event] = iCal.Create(Of [Event])() evt.Start = New iCalDateTime(DateTime.Today.AddDays(1)) evt.End = evt.Start.AddHours(1) evt.IsAllDay = False evt.Summary = "Server backup" evt.Location = "Server room" Dim serializer As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer.SerializeToString(iCal) ' And send it (we use direct send here, you can send it via SMTP relay as well). Smtp.QuickSend(msg) End Sub End Module
As you can see, the only difference from the previous sample is that it does not set attendees and iCalendar.Method = "REQUEST"
.
This sample creates an event which will occur daily within 5 days period, once added to the calendar of the person which receives this e-mail:
using System; using MailBee.Mime; using MailBee.SmtpMail; using iCal; using iCal.Serialization.iCalendar; class SendRecurring { static void Main(string[] args) { string emailFrom = "John Doe <jdoe@domain.com>"; string emailTo = "Alice <alice@company.com>"; MailMessage msg = new MailMessage(); msg.From.AsString = emailFrom; msg.To.AddFromString(emailTo); msg.Subject = "iCal repeated event"; // Create new event. iCalendar iCal = new iCalendar(); Event evt = iCal.Create<Event>(); evt.Start = new iCalDateTime(DateTime.Today.AddDays(1)); evt.IsAllDay = false; // Repeat every day, 5 days total. RecurrencePattern rp = new RecurrencePattern(FrequencyType.Daily, 1); rp.Count = 5; evt.RecurrenceRules.Add(rp); evt.Summary = "Server maintenance"; evt.Location = "Room 814"; iCalendarSerializer serializer = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer.SerializeToString(iCal); // Send this iCal event. We use direct send, you can modify it to use // SMTP relay server (see Smtp.Send method for details). Smtp.QuickSend(msg); } }
Imports MailBee.Mime Imports MailBee.SmtpMail Imports iCal Imports iCal.Serialization.iCalendar Module SendRecurring Sub Main(ByVal args As String()) Dim emailFrom As String = "John Doe <jdoe@domain.com>" Dim emailTo As String = "Alice <alice@company.com>" Dim msg As New MailMessage() msg.From.AsString = emailFrom msg.[To].AddFromString(emailTo) msg.Subject = "iCal repeated event" ' Create new event. Dim iCal As New iCalendar() Dim evt As [Event] = iCal.Create(Of [Event])() evt.Start = New iCalDateTime(DateTime.Today.AddDays(1)) evt.IsAllDay = False ' Repeat every day, 5 days total. Dim rp As New RecurrencePattern(FrequencyType.Daily, 1) rp.Count = 5 evt.RecurrenceRules.Add(rp) evt.Summary = "Server maintenance" evt.Location = "Room 814" Dim serializer As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = _ serializer.SerializeToString(iCal) ' Send this iCal event. We use direct send, you can modify it to use ' SMTP relay server (see Smtp.Send method for details). Smtp.QuickSend(msg) End Sub End Module
You can also make events which occur with another recurring pattern (e.g. weekly or repeat without ending date).
For instance, to repeat the event every day (without ending date), just do not set RecurrencePattern.Count property:
RecurrencePattern rp = new RecurrencePattern(FrequencyType.Daily, 1);
Dim rp As New RecurrencePattern(FrequencyType.Daily, 1)
The below shows RecurrencePattern setting to make event trigger every working day (from Mon to Fri):
RecurrencePattern rp = new RecurrencePattern(); rp.Frequency = FrequencyType.Daily; rp.ByDay.Add(new WeekDay(DayOfWeek.Monday)); rp.ByDay.Add(new WeekDay(DayOfWeek.Tuesday)); rp.ByDay.Add(new WeekDay(DayOfWeek.Wednesday)); rp.ByDay.Add(new WeekDay(DayOfWeek.Thursday)); rp.ByDay.Add(new WeekDay(DayOfWeek.Friday));
Dim rp As New RecurrencePattern() rp.Frequency = FrequencyType.Daily rp.ByDay.Add(New WeekDay(DayOfWeek.Monday)) rp.ByDay.Add(New WeekDay(DayOfWeek.Tuesday)) rp.ByDay.Add(New WeekDay(DayOfWeek.Wednesday)) rp.ByDay.Add(New WeekDay(DayOfWeek.Thursday)) rp.ByDay.Add(New WeekDay(DayOfWeek.Friday))
This one triggers on first Monday of every month:
RecurrencePattern rp = new RecurrencePattern(); rp.Frequency = FrequencyType.Monthly; rp.ByDay.Add(new WeekDay(DayOfWeek.Monday, FrequencyOccurrence.First));
Dim rp As New RecurrencePattern() rp.Frequency = FrequencyType.Monthly rp.ByDay.Add(New WeekDay(DayOfWeek.Monday, FrequencyOccurrence.First))
Using this approach, you can create any complex recurrence patterns.
You can create appointments and normal events with reminders. The e-mail program of the person which received the e-mail with such event will remind this person about upcoming event beforehand. This code can create both meeting request (appointment) and regular event. Set isAppointment
to true or false to control this.
using System; using MailBee.Mime; using MailBee.SmtpMail; using iCal; using iCal.Serialization.iCalendar; class AppointmentWithReminder { static void Main(string[] args) { EmailAddress emailFrom = EmailAddress.Parse("Event Creator <jdoe@domain.com>"); // Attendees of meeting. EmailAddress meeting1attendee1 = EmailAddress.Parse("Person1 <alice@company.com>"); EmailAddress meeting1attendee2 = EmailAddress.Parse("Person2 <john@domain.com>"); // SMTP settings. string smtpServer = "smtp.domain.com"; int smtpPort = 25; // Specify 465 for SSL. string username = "jdoe"; string password = "secret"; Smtp mailer = new Smtp(); SmtpServer srv = new SmtpServer(smtpServer, username, password); srv.Port = smtpPort; mailer.SmtpServers.Add(srv); bool isAppointment = false; // Set to true to make it appointment. MailMessage msg = mailer.Message; msg.From = emailFrom; msg.To.Add(meeting1attendee1); msg.To.Add(meeting1attendee2); msg.Subject = "iCal event with reminder"; // Create new event. iCalendar iCal = new iCalendar(); if (isAppointment) { iCal.Method = "REQUEST"; } Event evt1 = iCal.Create<Event>(); evt1.Start = new iCalDateTime(DateTime.Now.AddMinutes(10)); evt1.End = evt1.Start.AddHours(1); evt1.IsAllDay = false; evt1.Summary = "Project meeting"; evt1.Location = "Conference room"; // Configure reminder, triggers 15 minutes before the event. Alarm alrm1 = new Alarm(); alrm1.Trigger = new Trigger(new TimeSpan(-15 * 10000000)); alrm1.Action = AlarmAction.Display; alrm1.Description = "Project meeting Reminder"; evt1.Alarms.Add(alrm1); if (isAppointment) { // Add recipients for appointment. Attendee att1 = new Attendee("mailto:" + meeting1attendee1.Email); att1.RSVP = true; att1.CommonName = meeting1attendee1.Email; evt1.Attendees.Add(att1); Attendee att2 = new Attendee("mailto:" + meeting1attendee1.Email); att2.RSVP = true; att2.CommonName = meeting1attendee2.Email; evt1.Attendees.Add(att2); } iCalendarSerializer serializer = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = serializer.SerializeToString(iCal); // And send it. mailer.Send(); // This sample does not save Unique-ID of the appointment. // See "Create iCal appointment" sample for this. } }
Imports MailBee.Mime Imports MailBee.SmtpMail Imports iCal Imports iCal.Serialization.iCalendar Module AppointmentWithReminder Sub Main(ByVal args As String()) Dim emailFrom As EmailAddress = _ EmailAddress.Parse("Event Creator <jdoe@domain.com>") ' Attendees of meeting. Dim meeting1attendee1 As EmailAddress = _ EmailAddress.Parse("Person1 <alice@company.com>") Dim meeting1attendee2 As EmailAddress = _ EmailAddress.Parse("Person2 <john@domain.com>") ' SMTP settings. Dim smtpServer As String = "smtp.domain.com" Dim smtpPort As Integer = 25 ' Specify 465 for SSL. Dim username As String = "jdoe" Dim password As String = "secret" Dim mailer As New Smtp() Dim srv As New SmtpServer(smtpServer, username, password) srv.Port = smtpPort mailer.SmtpServers.Add(srv) Dim isAppointment As Boolean = False ' Set to true to make it appointment. Dim msg As MailMessage = mailer.Message msg.From = emailFrom msg.[To].Add(meeting1attendee1) msg.[To].Add(meeting1attendee2) msg.Subject = "iCal event with reminder" ' Create new event. Dim iCal As New iCalendar() If isAppointment Then iCal.Method = "REQUEST" End If Dim evt1 As [Event] = iCal.Create(Of [Event])() evt1.Start = New iCalDateTime(DateTime.Now.AddMinutes(10)) evt1.End = evt1.Start.AddHours(1) evt1.IsAllDay = False evt1.Summary = "Project meeting" evt1.Location = "Conference room" ' Configure reminder, triggers 15 minutes before the event. Dim alrm1 As New Alarm() alrm1.Trigger = New Trigger(New TimeSpan(-15 * 10000000)) alrm1.Action = AlarmAction.Display alrm1.Description = "Project meeting Reminder" evt1.Alarms.Add(alrm1) If isAppointment Then ' Add recipients for appointment. Dim att1 As New Attendee("mailto:" & meeting1attendee1.Email) att1.RSVP = True att1.CommonName = meeting1attendee1.Email evt1.Attendees.Add(att1) Dim att2 As New Attendee("mailto:" & meeting1attendee1.Email) att2.RSVP = True att2.CommonName = meeting1attendee2.Email evt1.Attendees.Add(att2) End If Dim serializer As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method = REQUEST").Text = _ serializer.SerializeToString(iCal) ' And send it. mailer.Send() ' This sample does not save Unique-ID of the appointment. ' See "Create iCal appointment" sample for this. End Sub End Module
You can also set what action will take place when an alarm triggers. Usually (like in this sample), a message dialog will be displayed. However, you can use other values for Alarm.Action property to send a notification e-mail, for example.
This console sample gets the last e-mail from a POP3 inbox and, if it's a meeting request, let's the user accept or decline this request by sending iCal response to the original sender.
In other words, this sample allows your application do what Outlook does when it receives an e-mail containing a meeting request.
using System; using System.IO; using System.Collections.Generic; using MailBee.Mime; using MailBee.SmtpMail; using MailBee.Pop3Mail; using iCal; using iCal.Serialization.iCalendar; class AcceptMeetingRequest { static void Main(string[] args) { // E-mail address of attendee. It's assumed you as attendee receive a meeting request // to this e-mail address, and will send your reply (which denotes whether you accept // or decline the request) from this address. string myEmail = "jdoe@domain.com"; // SMTP settings. string smtpServer = "smtp.domain.com"; int smtpPort = 25; // Specify 465 for SSL. string username = "jdoe"; string password = "secret"; Smtp mailer = new Smtp(); SmtpServer srv = new SmtpServer(smtpServer, username, password); srv.Port = smtpPort; mailer.SmtpServers.Add(srv); // Download last e-mail from POP3 account. MailMessage appointmentMsg = Pop3.QuickDownloadMessage("pop.domain.com", "jdoe", "secret", -1); Console.WriteLine("Email From: " + appointmentMsg.From.ToString()); Console.WriteLine("Email To: " + appointmentMsg.To.ToString()); Console.WriteLine("Subject: " + appointmentMsg.Subject); // For each part of the message, examine if it contains a meeting request, // and let the user know if it does. foreach (TextBodyPart part in appointmentMsg.BodyParts) { if (part.IsICalendar) { IICalendarCollection iiCal = iCalendar.LoadFromStream(new StringReader(part.Text)); for (int i = 0; i < iiCal.Count; i++) { if (iiCal[i].Method.ToUpper() == "REQUEST") { for (int j = 0; j < iiCal[i].Events.Count; j++) { IList<IAttendee> att = iiCal[i].Events[j].Attendees; for (int k = 0; k < att.Count; k++) { if (att[k].AssociatedObject.Name.ToUpper() == "ATTENDEE" && att[k].Value.AbsoluteUri.ToLower() == "mailto:" + myEmail.ToLower() && att[k].RSVP) { Console.WriteLine(); Console.WriteLine("Summary: " + iiCal[i].Events[j].Summary); Console.WriteLine("Location: " + iiCal[i].Events[j].Location); MailMessage msg = mailer.Message; msg.Reset(); msg.From.AsString = myEmail; if (appointmentMsg.From.Email != string.Empty) { msg.To.Add(appointmentMsg.From.Email); } else { msg.To.AddFromString(appointmentMsg.Headers["Sender"]); } Console.WriteLine(); Console.WriteLine("Press 'y' to Accept, 'n' to Decline, 't' to Tentative,"); Console.WriteLine("or any other key to skip responding to this request,"); Console.WriteLine("and press Enter"); string respond = Console.ReadLine().ToLower(); if (respond == "y" || respond == "n" || respond == "t") { // Create new event with meeting response. iCalendar iCalResp = new iCalendar(); iCalResp.Method = "REPLY"; Event evtResp = iCalResp.Create<Event>(); evtResp.Class = "PUBLIC"; evtResp.UID = iiCal[i].UniqueComponents[0].UID; evtResp.Location = iiCal[i].Events[j].Location; evtResp.Summary = iiCal[i].Events[j].Summary; // Add recipient for appointment (the sender of the meeting request). Attendee attResp = new Attendee("mailto:" + appointmentMsg.From.Email); switch (respond) { case "y": msg.Subject = "Accepted: " + iiCal[i].Events[j].Summary; attResp.ParticipationStatus = "ACCEPTED"; break; case "n": msg.Subject = "Declined: " + iiCal[i].Events[j].Summary; attResp.ParticipationStatus = "DECLINED"; break; case "t": msg.Subject = "Tentative: " + iiCal[i].Events[j].Summary; attResp.ParticipationStatus = "TENTATIVE"; break; } evtResp.Attendees.Add(attResp); iCalendarSerializer serializer = new iCalendarSerializer(); // Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method=REPLY").Text = serializer.SerializeToString(iCalResp); // Send confirmation. mailer.Send(); } } } } } } } } } }
Imports System.IO Imports System.Collections.Generic Imports MailBee.Mime Imports MailBee.SmtpMail Imports MailBee.Pop3Mail Imports iCal Imports iCal.Serialization.iCalendar Module AcceptMeetingRequest Sub Main(ByVal args As String()) ' E-mail address of attendee. It's assumed you as attendee receive a meeting request ' to this e-mail address, and will send your reply (which denotes whether you accept ' or decline the request) from this address. Dim myEmail As String = "jdoe@domain.com" ' SMTP settings. Dim smtpServer As String = "smtp.domain.com" Dim smtpPort As Integer = 25 ' Specify 465 for SSL. Dim username As String = "jdoe" Dim password As String = "secret" Dim mailer As New Smtp() Dim srv As New SmtpServer(smtpServer, username, password) srv.Port = smtpPort mailer.SmtpServers.Add(srv) ' Download last e-mail from POP3 account. Dim appointmentMsg As MailMessage = Pop3.QuickDownloadMessage("pop.domain.com", "jdoe", "secret", -1) Console.WriteLine("Email From: " & appointmentMsg.From.ToString()) Console.WriteLine("Email To: " & appointmentMsg.[To].ToString()) Console.WriteLine("Subject: " & appointmentMsg.Subject) ' For each part of the message, examine if it contains a meeting request, ' and let the user know if it does. For Each part As TextBodyPart In appointmentMsg.BodyParts If part.IsICalendar Then Dim iiCal As IICalendarCollection = iCalendar.LoadFromStream(New StringReader(part.Text)) For i As Integer = 0 To iiCal.Count - 1 If iiCal(i).Method.ToUpper() = "REQUEST" Then For j As Integer = 0 To iiCal(i).Events.Count - 1 Dim att As IList(Of IAttendee) = iiCal(i).Events(j).Attendees For k As Integer = 0 To att.Count - 1 If att(k).AssociatedObject.Name.ToUpper() = "ATTENDEE" AndAlso _ att(k).Value.AbsoluteUri.ToLower() = "mailto:" & myEmail.ToLower() AndAlso _ att(k).RSVP Then Console.WriteLine() Console.WriteLine("Summary: " & iiCal(i).Events(j).Summary) Console.WriteLine("Location: " & iiCal(i).Events(j).Location) Dim msg As MailMessage = mailer.Message msg.Reset() msg.From.AsString = myEmail If appointmentMsg.From.Email <> String.Empty Then msg.[To].Add(appointmentMsg.From.Email) Else msg.[To].AddFromString(appointmentMsg.Headers("Sender")) End If Console.WriteLine() Console.WriteLine("Press 'y' to Accept, 'n' to Decline, 't' to Tentative,") Console.WriteLine("or any other key to skip responding to this request,") Console.WriteLine("and press Enter") Dim respond As String = Console.ReadLine().ToLower() If respond = "y" OrElse respond = "n" OrElse respond = "t" Then ' Create new event with meeting response. Dim iCalResp As New iCalendar() iCalResp.Method = "REPLY" Dim evtResp As [Event] = iCalResp.Create(Of [Event])() evtResp.[Class] = "PUBLIC" evtResp.UID = iiCal(i).UniqueComponents(0).UID evtResp.Location = iiCal(i).Events(j).Location evtResp.Summary = iiCal(i).Events(j).Summary ' Add recipient for appointment (the sender of the meeting request). Dim attResp As New Attendee("mailto:" & appointmentMsg.From.Email) Select Case respond Case "y" msg.Subject = "Accepted: " & iiCal(i).Events(j).Summary attResp.ParticipationStatus = "ACCEPTED" Exit Select Case "n" msg.Subject = "Declined: " & iiCal(i).Events(j).Summary attResp.ParticipationStatus = "DECLINED" Exit Select Case "t" msg.Subject = "Tentative: " & iiCal(i).Events(j).Summary attResp.ParticipationStatus = "TENTATIVE" Exit Select End Select evtResp.Attendees.Add(attResp) Dim serializer As New iCalendarSerializer() ' Add iCal as BodyPart. msg.BodyParts.Add("text/calendar; method=REPLY").Text = _ serializer.SerializeToString(iCalResp) ' Send confirmation. mailer.Send() End If End If Next Next End If Next End If Next End Sub End Module
We assume MailBee.Global.LicenseKey is already set in app.config, registry, etc. If not, you can set it in the code.
This sample shows how to find out if the incoming e-mail is a response to a meeting request and then match this response and the originating meeting request. For a change, we use IMAP as incoming e-mail protocol.
To check if we got a match, we lookup of the iCal Unique-ID of the incoming response in the list of stored meeting request attendees and assigned iCal Unique-IDs (which we created in Create iCal appointment sample).
Once we got a match, we update the list of stored meeting request information with the participation status we extracted from the response.
using System; using System.IO; using System.Collections; using System.Text; using MailBee.Mime; using MailBee.ImapMail; using iCal; // This sample gets the last e-mail from an IMAP inbox. Then, it checks if // this e-mail is a meeting response to a meeting request we previously sent in // "Create iCal appointment" sample. If it is, we update our database with the // new information (whether the attendee has accepted or declined the request). class AnalyzeMeetingResponse { static void Main(string[] args) { // Load last e-mail from IMAP inbox. MailMessage appointmentMsg = Imap.QuickDownloadMessage("mail.domain.com", "jdoe", "secret", "Inbox", -1); string[] lines = null; bool updated = false; // Check all parts of the e-mail if they contain meeting response from attendees. foreach (TextBodyPart part in appointmentMsg.BodyParts) { if (part.IsICalendar) { IICalendarCollection iiCal = iCalendar.LoadFromStream(new StringReader(part.Text)); for (int i = 0; i < iiCal.Count; i++) { if (iiCal[i].Method.ToUpper() == "REPLY") { if (lines == null) { // We assume the file exists and user has read/write access. // The file is in the following format: // appointment's iCal Unique-ID;attendee e-mail address;status or empty lines = File.ReadAllLines(@"C:\Temp\eventUid.txt"); } for (int j = 0; j < lines.Length; j++) { string[] parts = lines[j].Split(new char[] { ';' }); // Look up for the iCal Unique-ID and e-mail address from the // meeting response in our database (where we saved them earler when // created the original meeting request). if (iiCal[i].UniqueComponents[0].UID.ToLower() == parts[0] && appointmentMsg.From.Email.ToLower() == parts[1]) { Console.WriteLine("From: " + appointmentMsg.From.ToString()); Console.WriteLine("Subject: " + appointmentMsg.Subject); Console.WriteLine(); Console.WriteLine("Event: " + iiCal[i].Events[0].Summary); Console.WriteLine("Status: " + iiCal[i].Events[0].Attendees[0].ParticipationStatus); // Update our database with the participation status which we extracted // from the meeting response e-mail. lines[j] = parts[0] + ';' + parts[1] + ';' + iiCal[i].Events[0].Attendees[0].ParticipationStatus; updated = true; } } } } } } if (updated) { // Write acceptance status to database. We use text file here for simplicity, // real-world apps will probably use SQL database. File.WriteAllLines(@"C:\Temp\eventUid.txt", lines); } } }
Imports System.IO Imports System.Collections Imports System.Text Imports MailBee.Mime Imports MailBee.ImapMail Imports iCal ' This sample gets the last e-mail from an IMAP inbox. Then, it checks if ' this e-mail is a meeting response to a meeting request we previously sent in ' "Create iCal appointment" sample. If it is, we update our database with the ' new information (whether the attendee has accepted or declined the request). Module AnalyzeMeetingResponse Sub Main(ByVal args As String()) ' Load last e-mail from IMAP inbox. Dim appointmentMsg As MailMessage = _ Imap.QuickDownloadMessage("mail.domain.com", "jdoe", "secret", "Inbox", -1) Dim lines As String() = Nothing Dim updated As Boolean = False ' Check all parts of the e-mail if they contain meeting response from attendees. For Each part As TextBodyPart In appointmentMsg.BodyParts If part.IsICalendar Then Dim iiCal As IICalendarCollection = _ iCalendar.LoadFromStream(New StringReader(part.Text)) For i As Integer = 0 To iiCal.Count - 1 If iiCal(i).Method.ToUpper() = "REPLY" Then If lines Is Nothing Then ' We assume the file exists and user has read/write access. ' The file is in the following format: ' appointment's iCal Unique-ID;attendee e-mail address;status or empty lines = File.ReadAllLines("C:\Temp\eventUid.txt") End If For j As Integer = 0 To lines.Length - 1 Dim parts As String() = lines(j).Split(New Char() {";"c}) ' Look up for the iCal Unique-ID and e-mail address from the ' meeting response in our database (where we saved them earler when ' created the original meeting request). If iiCal(i).UniqueComponents(0).UID.ToLower() = parts(0) AndAlso _ appointmentMsg.From.Email.ToLower() = parts(1) Then Console.WriteLine("From: " & appointmentMsg.From.ToString()) Console.WriteLine("Subject: " & appointmentMsg.Subject) Console.WriteLine() Console.WriteLine("Event: " & iiCal(i).Events(0).Summary) Console.WriteLine("Status: " & _ iiCal(i).Events(0).Attendees(0).ParticipationStatus) ' Update our database with the participation status ' which we extracted from the meeting response e-mail. lines(j) = parts(0) & ";" & parts(1) & ";" & _ iiCal(i).Events(0).Attendees(0).ParticipationStatus updated = True End If Next End If Next End If Next If updated Then ' Write acceptance status to database. We use text file here for simplicity, ' real-world apps will probably use SQL database. File.WriteAllLines("C:\Temp\eventUid.txt", lines) End If End Sub End Module
We assume MailBee.Global.LicenseKey is already set in app.config, registry, etc. If not, you can set it in the code.
Copyright © 2006-2024 AfterLogic Corporation. All rights reserved.