Click here to Skip to main content
Click here to Skip to main content

Sending Tasks Programmatically

, 24 Jul 2005
Rate this:
Please Sign up or sign in to vote.
This article shows two different ways of sending tasks programmatically. One is using the Microsoft Outlook 11.0 Object Library and the other is using vCalendar.

Introduction

I’m going to show two different ways of sending tasks programmatically. One is using the Microsoft Outlook 11.0 Object Library and the other is using vCalendar.

Using Microsoft Outlook 11.0 Object Library

The simplest of these is using Microsoft 11.0 object library. This has a class called TaskItem. TaskItem represents a task (an assigned, delegated, or self-imposed task to be performed within a specified time frame) in a Tasks folder. Like appointments or meetings, tasks can be delegated. You can get this library from Add Reference and click on COM tab.

Create an alias as follows:

using Outlook = Microsoft.Office.Interop.Outlook;

Create objects of ApplicationClass and TaskItem as follows:

Outlook.ApplicationClass app = new Outlook.ApplicationClass();
Outlook.TaskItem tsk = (Outlook.TaskItem) 
             app.CreateItem(Outlook.OlItemType.olTaskItem);

Set the properties of task as needed:

tsk.StartDate = DateTime.Now;
tsk.DueDate = DateTime.Now;
tsk.Subject = "Test";
tsk.Body = "Testing Task";
tsk.Recipients.Add("abc@xyz.com");
tsk.Assign();
tsk.Send();

That’s it. This is the simplest way for creating and sending a task programmatically. One disadvantage of this is we get to click away the annoying security popups.

Using vCalendar

The next way is through the vCalendar object. vCalendar is the industry standard format for sending/receiving scheduling information electronically. vCalendar was developed by a consortium formed by IBM, AT&T, Siemens and Apple. Later, this specification was given to Internet Mail Consortium. Now, most of the Personal Information Manager (PIM) programs on all software support vCalendar as the standard exchange format.

Microsoft Outlook supports vCalendar (what more do we want Wink | ;) ). vCalendar files are not just used to exchange appointments and schedules within one organization. They can be used to schedule appointments with others, who use scheduling software incompatible with yours (all the more we want, right?). Let’s get on with how to create a vCalendar object programmatically.

vCalendar file would look something like the following:

BEGIN:VCALENDAR PRODID:-//Microsoft Corporation//Outlook MIMEDIR//EN 
     VERSION:1.0 BEGIN:VEVENT DTSTART:19980114T210000Z DTEND:19980114T230000Z 
     LOCATION:Team Room CATEGORIES:Business 
     DESCRIPTION;ENCODING=QUOTED-PRINTABLE:Testing 
     Task=0D=0A SUMMARY:Test PRIORITY:3 END:VEVENT END:VCALENDAR

To create the vCalendar object, we have the method given below:

string CreateTask(DateTime start, DateTime end, string sub, string msgBody)
{
    StringBuilder sbvCalendar = new StringBuilder();

    //Header
    sbvCalendar.Append("METHOD: REQUEST");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("BEGIN:VCALENDAR");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("PRODID:-//Microsoft Corporation//Outlook ");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("MIMEDIR//ENVERSION:1.0");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("BEGIN:VEVENT");
    sbvCalendar.Append("\n");
                
    //DTSTART 
    sbvCalendar.Append("DTSTART:");
    string hour = start.Hour.ToString();
    if(hour.Length<2){hour ="0"+ hour;}
            
    string min = start.Minute.ToString();
    if(min.Length<2){min = "0" + min;}
            
    string sec = start.Second.ToString();
    if(sec.Length<2){sec = "0" + sec;}

    string mon = start.Month.ToString();
    if(mon.Length<2){mon ="0" + mon;}
             
    string day = start.Day.ToString();
    if(day.Length<2){day ="0" + day;}

    sbvCalendar.Append(start.Year.ToString()+ mon + day 
                           +  "T" + hour + min + sec );
    sbvCalendar.Append("\n");

    //DTEND
    sbvCalendar.Append("DTEND:");
    hour = end.Hour.ToString();
    if(hour.Length<2){hour ="0"+ hour;}

    min = end.Minute.ToString();
    if(min.Length<2){min = "0" + min;}
                
    sec = end.Second.ToString();
    if(sec.Length<2){sec = "0" + sec;}

    mon = end.Month.ToString();
    if(mon.Length<2){mon ="0" + mon;}
             
    day = end.Day.ToString();
    if(day.Length<2){day ="0" + day;}

    sbvCalendar.Append(end.Year.ToString()+ mon + 
                 day +  "T" + hour + min + sec );
    sbvCalendar.Append("\n");

    //Location
    sbvCalendar.Append("LOCATION;ENCODING=QUOTED-PRINTABLE: " 
                                             + String.Empty);
    sbvCalendar.Append("\n");
        
    //Message body
    sbvCalendar.Append("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" 
                                                    + msgBody);
    sbvCalendar.Append("\n");

    //Subject
    sbvCalendar.Append("SUMMARY;ENCODING=QUOTED-PRINTABLE:" 
                                                    + sub);
    sbvCalendar.Append("\n");

    //Priority
    sbvCalendar.Append("PRIORITY:3");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("END:VEVENT");
    sbvCalendar.Append("\n");
    sbvCalendar.Append("END:VCALENDAR");
    sbvCalendar.Append("\n");
            
    return sbvCalendar.ToString();
}

We can use this method as:

string sub = "Test";
string body = "Testing Task";

//Create a message object
MailMessage msg = new MailMessage();
msg.From = "abc@xyz.com";
msg.To = "def@xyz.com";
msg.Subject = sub;
msg.BodyEncoding = System.Text.Encoding.UTF8;
msg.Body = body;
            
//Set the date/time
DateTime start = DateTime.Parse("Jan 1, 2005");
DateTime end = DateTime.Parse("Jan 2, 2005");
DateTime ex = DateTime.Now;

//Location where you want to save the vCalendar file
string attachUrl = 
   "C:\Inetpub\wwwroot\WebApplication3\bin\ Test.vcs";

//Create task
using(StreamWriter sw = new StreamWriter(attachUrl)
{
  sw.Write(CreateTask (start, end, sub, body));
}

//Attach the task
MailAttachment mAttachment = new MailAttachment(attachUrl);
msg.Attachments.Add(mAttachment);
            
//Send
SmtpMail.SmtpServer = "some-smtp-mail-server.com";
SmtpMail.Send(msg);

That’s it. Happy coding!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Mercy Ponnupandy
Architect
United States United States
Architect / Consultant on Content Management and Cloud Computing... Artist and Author by the weekends...
Follow on   Twitter

Comments and Discussions

 
GeneralNice Article PinmemberRajin Sayeed S Alam15-May-11 19:07 
GeneralMy vote of 3 Pinmemberfertansa2-Mar-11 11:21 
Newsbroken code - do not use as-is - please read the RFC and validate Pinmemberrlively6-Apr-10 8:16 
To create a proper iCalendar file, read up on the Internet Calendaring and Scheduling Core Object Specification (iCalendar). To help validate that you are correctly creating calendar file, use the iCalendar Validator, which "is used to validate calendaring data against the iCalendar (RFC 5545) standard." Also see http://icalvalid.wikidot.com/ to read and collaborate on creating calendar files.
 
This code produces an invalid calendar file for various reasons (missing required properties such as DTSTAMP and UID, not escaping special characters, etc). Also, there is an update to the vCalendar spec called iCalendar, which was put forth in 1998.
 
One of the biggest problems is "MIMEDIR" beginning on a line, which makes it appear as a property - there is no "MIMEDIR" property.
 
Thumbs Down | :thumbsdown:
sbvCalendar.Append("PRODID:-//Microsoft Corporation//Outlook ");
sbvCalendar.Append("\n");
sbvCalendar.Append("MIMEDIR//ENVERSION:1.0");
sbvCalendar.Append("\n");
 
If you save a calendar event from Outlook, you can see that MIMEDIR//EN is part of the previous line containing the PRODID property that identifies the program that created the iCalendar data (Outlook in this case). The end of the PRODID line and the beginning of the next property VERSION have been jammed together in this code to create MIMEDIR//ENVERSION:1.0.
 
VERSION:2.0 property should be included on a line by itself to identify the version.
 
Good example exported from Outlook:
 
Thumbs Up | :thumbsup:
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
 
This code appears to be based off an example such as this calendarswamp.blogspot.com posting that, due to the formatting of the post, makes lines appear to merge together. There's even a note stating that it should be one line and not multiple lines to try to eliminate confusion.
 
PRODID:-//Microsoft Corporation//Outlook 11.0
MIMEDIR//EN
(these previous 3 lines are all one line)
VERSION:2.0
 
Read the spec and make sure you understand what the code does and what it produces.
 
----------
 
Here are some relevant bits from the RFC that will help in creating a proper iCalendar file and will help with many of the issues people are facing such as failure to import into Outlook, being unable to get the "all day event" checkbox to be checked in Outlook, etc:
 
http://tools.ietf.org/html/rfc5545#section-3.7.4
The VERSION property is required by the RFC: Conformance: This property MUST be specified once in an iCalendar object.
 
http://msdn.microsoft.com/en-us/library/ee160562(EXCHG.80).aspx#id128
<128> Section 2.2.1.20.10: Exchange 2003, Exchange 2007, and Exchange 2010 require that X-MICROSOFT-CDO-ALLDAYEVENT be set to 'TRUE' if the Calendar object is to be imported as all day.
Outlook 2003 requires that a VALUE parameter be set to 'DATE' for both DTSTART and DTEND if the Calendar object is to be imported as all day.
<129> Section 2.2.1.20.10: Outlook 2003 does not import or export the X-MICROSOFT-CDO-ALLDAYEVENT or X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT properties.

http://tools.ietf.org/wg/calsify/draft-ietf-calsify-rfc2445bis/draft-ietf-calsify-rfc2445bis-03.html#DATE_TIME_START
Value Type: The default value type is DATE-TIME. The time value MUST be one of the forms defined for the DATE-TIME value type.
The value type can be set to a DATE value type. (";" "VALUE" "=" ("DATE-TIME" / "DATE")) / (";" tzidparam) /

http://tools.ietf.org/html/rfc5545#section-3.6.1
The following is an example of the "VEVENT" calendar component used to represent a multi-day event scheduled from June 28th, 2007 to July 8th, 2007 inclusively. Note that the "DTEND" property is set to July 9th, 2007, since the "DTEND" property specifies the non-inclusive end of the event.

 BEGIN:VEVENT
 UID:20070423T123432Z-541111@example.com
 DTSTAMP:20070423T123432Z
 DTSTART;VALUE=DATE:20070628
 DTEND;VALUE=DATE:20070709
 SUMMARY:Festival International de Jazz de Montreal
 TRANSP:TRANS
 
http://tools.ietf.org/html/rfc5545#section-3.6.1
The "DTEND" property for a "VEVENT" calendar component specifies the non-inclusive end of the event. For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE value type but no "DTEND" nor "DURATION" property, the event's duration is taken to be one day.
Exporting an day all day event from Outlook creates DTEND;VALUE=DATE: for the day after the appointment ends, even for 1 day events.
 
http://tools.ietf.org/html/rfc5545#section-3.8.2.7
Purpose: This property defines whether or not an event is transparent to busy time searches.
Description: Time Transparency is the characteristic of an event that determines whether it appears to consume time on a calendar.
Events that consume actual time for the individual or resource associated with the calendar SHOULD be recorded as OPAQUE, allowing them to be detected by free/busy time searches. Other events, which do not take up the individual's (or resource's) time SHOULD be recorded as TRANSPARENT, making them invisible to free/ busy time searches.
 
http://tools.ietf.org/html/rfc5545#section-3.6.1
The following are REQUIRED, but MUST NOT occur more than once. dtstamp / uid /
 
http://tools.ietf.org/html/rfc5545#section-3.8.4.7
3.8.4.7. Unique Identifier
Property Name: UID
Purpose: This property defines the persistent, globally unique identifier for the calendar component.
Description: The "UID" itself MUST be a globally unique identifier. The generator of the identifier MUST guarantee that the identifier is unique. There are several algorithms that can be used to accomplish this. A good method to assure uniqueness is to put the domain name or a domain literal IP address of the host on which the identifier was created on the right-hand side of an "@", and on the left-hand side, put a combination of the current calendar date and time of day (i.e., formatted in as a DATE-TIME value) along with some other currently unique (perhaps sequential) identifier available on the system (for example, a process id number). Using a DATE-TIME value on the left-hand side and a domain name or domain literal on the right-hand side makes it possible to guarantee uniqueness since no two hosts should be using the same domain name or IP address at the same time.
 
http://tools.ietf.org/html/rfc5545#section-3.8.1.5
Example: The following is an example of this property with formatted line breaks in the property value:
DESCRIPTION:Meeting to provide technical review for "Phoenix"
design.\nHappy Face Conference Room. Phoenix design team
MUST attend this meeting.\nRSVP to team leader.
 
http://tools.ietf.org/html/rfc5545#section-3.3.11
Value Name: TEXT
ESCAPED-CHAR = ("\\" / "\;" / "\," / "\N" / "\n")
\\ encodes \, \N or \n encodes newline, \; encodes ;, \, encodes ,
 
An intentional formatted text line break MUST only be included in a "TEXT" property value by representing the line break with the character sequence of BACKSLASH, followed by a LATIN SMALL LETTER N or a LATIN CAPITAL LETTER N, that is "\n" or "\N".
 
The "TEXT" property values may also contain special characters that are used to signify delimiters, such as a COMMA character for lists of values or a SEMICOLON character for structured values. In order to support the inclusion of these special characters in "TEXT" property values, they MUST be escaped with a BACKSLASH character. A BACKSLASH character in a "TEXT" property value MUST be escaped with another BACKSLASH character. A COMMA character in a "TEXT" property value MUST be escaped with a BACKSLASH character. A SEMICOLON character in a "TEXT" property value MUST be escaped with a BACKSLASH character. However, a COLON character in a "TEXT" property value SHALL NOT be escaped with a BACKSLASH character.
GeneralRe: broken code - do not use as-is - please read the RFC and validate PinmemberMember 1028103924-Feb-14 23:22 
Generalmsg.To cannot be assigned PinmemberJames_Lin11-May-09 10:12 
GeneralAppending strings to get vCalendar: wrong, Using MS API: right Pinmemberrlively10-Oct-08 5:40 
GeneralReminder & Busy Status PinmemberMember 44677752-Oct-08 3:56 
QuestionAppointment vs Task Pinmembercentric5-Mar-07 7:57 
GeneralHave a little problem Pinmemberuddesh14-Feb-07 18:37 
GeneralRe: Have a little problem PinmemberFilip C2-Apr-09 1:43 
GeneralOther people's tasks PinmemberKokas1-Nov-05 2:10 
GeneralRe: Other people's tasks Pinmemberstehlewm21-Jul-06 4:43 
QuestionAnd with no attachment? Pinsussjoujoukinder1-Sep-05 20:51 
QuestionOutlook neets to run in background ? Pinmembermvanschie27-Jul-05 22:12 
AnswerRe: Outlook neets to run in background ? Pinmemberstehlewm21-Jul-06 4:37 
GeneralNice, But... PinmemberFZelle25-Jul-05 4:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.141015.1 | Last Updated 25 Jul 2005
Article Copyright 2005 by Mercy Ponnupandy
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid