The internal web application at my company tends to send out a lot of email notifications. Some of them are reminders about various deadlines. Recently I got a feature request to allow people to add these reminders as events to their Outlook calendar.
Outlook supports two calendaring formats vCalendar and iCalendar. I opted to go with the later one because it is an open standard and at least in theory should work with other calendaring applications. The apps which support iCalendar standard can export their events as .ics files which can be seamlessly exchanged between the applications. So my task was to generate such a file on the fly and either link to it, or attach it to the reminder emails.
You can actually serve the ics file directly from a php page by telling the browser you are sending it a text/Calendar mimetype. You do this by sending appropriate headers:
header("Content-Type: text/Calendar");
header("Content-Disposition: inline; filename=calendar.ics");
This will force the browser to interpret the input as a ics file and will show the user the dialog asking him to open the file in an external application. Then you simply need to output the appropriate data in the iCalendar format, which is relatively simple. Here is a very simple event you can copy and paste into your PHP file:
header("Content-Type: text/Calendar");
header("Content-Disposition: inline; filename=calendar.ics");
echo "BEGIN:VCALENDAR\n";
echo "VERSION:2.0\n";
echo "PRODID:-//Foobar Corporation//NONSGML Foobar//EN\n";
echo "METHOD:REQUEST\n"; // requied by Outlook
echo "BEGIN:VEVENT\n";
echo "UID:".date('Ymd').'T'.date('His')."-".rand()."-example.com\n"; // required by Outlok
echo "DTSTAMP:".date('Ymd').'T'.date('His')."\n"; // required by Outlook
echo "DTSTART:20080413T000000\n";
echo "SUMMARY:TEST\n";
echo "DESCRIPTION: this is just a test\n";
echo "END:VEVENT\n";
echo "END:VCALENDAR\n";
This will generate an event called TEST to happen on April 13 2008. Note the fields which I marked as required by Outlook. This is important. They are not required by the iCalendar spec so some examples out there skip them. If you do however you will get this lovely error message when you open the file in Outlook:
Microsoft Office Outlook cannot import vCalendar file. This error can appear if you have attempted to save a recurring Lunar appointment in iCalendar format. To avoid this error, set the appointment option to Gregorian instead of Lunar.
Gotta love Microsoft and their through, meaningful error messages. In this case the message is absolutely meaningless and the problem has nothing to do with “Lunar appointments” whatever the hell those are. You are simply missing the METHOD, DTSTAMP and UID fields.
I used REQUEST for the METHOD field but you can also try PUBLISH and few others. As far as I can tell the difference here is how the calendaring application will present the opened file to the user. If you use REQUEST it will give them a button to Accept or Reject the event. If you use PUBLISH they will be asked to save or cancel. Either way is acceptable by me.
The DTSTAMP field is, as the name suggest the date stamp when this event request was generated. As you can see I’m generating it on the fly.
The UID is supposed to be a unique identifier for this event, for some internal use. It is recommend that the right hand side of the UID be the host name or some unique identifier for the domain. I’m not exactly sure what the significance of this field is – I suspect it may be meaningful in certain situations, where the calendaring app is internally sorting the data. As you can see I use the date stamp on the right, followed by a randomly generated number, followed by host name which is pretty much what they advocate in the spec. It should yield UID’s that are sufficiently unique for each event. Some examples out there just use 0 or 1 here which doesn’t seem to be following the specification, but nevertheless it works just fine when you test it. However I figured it’s better to do it right, rather than run into weird issues much, much later.
I think the rest of the fields are pretty much self explanatory, with exception of PRODID. That’s the funny one. It is supposed to uniquely identify the product which has generated this event. In other words it is the place to pimp out your company and your software. And yet, all the online examples use the same 2 or 3 strings, showing blatantly that most people just copy and paste a working example into their production code and then blog about it without ever actually bothering to read the spec itself.
This is how I did it. I’m sure there are more elegant ways to accomplish this, but my email reminders will simply link to an appropriate php page which will fetch relevant data from the database and build appropriate ics file. I hope someone out there will find this writeup useful. And if I see “Foobar Corporation” in the future writeups, I will know you copied from me, and didn’t even bother reading the rest of the post. ;)
[tags]ics, icalendar, php, ical, calendar, calendar events, outlook events[/tags]
Clever – nicely done. I know you don’t get as many comments on these more specific technical implementations, but I love reading them, please don’t stop posting them.
Thanks! Glad to hear someone is reading them. :)
Sometimes the more technical things get comments after a while – once they get indexed by Google and they gravitate towards first page for specific query strings. People are then just stumbling in from Google looking for a particular solution or answer to a problem and they sometimes leave a comment then.
Many thanks. That is exactly what I am looking for.
I changed this line “Foobar Corporation”. LOL~~~
UID problem
I’m trying to send a new meeting invite via email from PHP, similar to the post, and things nearly work. When I open the ics attachment, Outlook tells me “This meeting is not in the Calendar; it may have been moved or deleted.”
If I were to eliminate the UID, the attachment doesn’t work. If I use the post’s example, a random string, MS formatted random GUID, 0, or other shots in the dark, I get that “not in Calendar” problem.
Sounds to me like my message is attempting to reference a meeting that does not yet exist – but I want this to create a new Outlook appointment.
Any thoughts on how to accomplish that?
(and sure enough, Google indexing of a specific tech problem led me here)
I am working on the same problem – sending email invites to Outlook via our java application. I came across the same solution that you have (the format and required fields for Outlook). My problem is with recurring events, I can’t seem to get Outlook to pick up the fact that my application send a request for a recurring meeting. It will still just show the first meeting with an accept/reject button, no information about the recurrence. Have you tried this or come up with a solution?
@Nancy – I haven’t tried implementing it, but have you tried using the RRULE field? Also read up on SEQUENCE and RECURRENCE-ID fields – I suspect that Outlook needs a way to create unique references for each recurring instance and the key is in these fields.
But, again I haven’t tested it. If you figure it out, please let us know the solution!
@Gene Z
Can you post your mail function out here..
I’m looking for this MS Outlook hack for few weeks.
finaly google gave me back some result.
I need to send out meeting request to persons. one at a time.
Perfect Post :)
@Wolf
Sure, for what it’s worth. The code below indeed sent a meeting invite, but it was not linked to an actual appointment in Outlook. As fate would have it, I had to switch to Java anyway, so never advanced the PHP code any further. What I needed was to send invites for an appointment on our Exchange server, so to do that I need a package to interface with Exchange (no way I’m tackling a MS API directly).
Hope this helps in some way:
hm, some characters were dropped when the code sample got posted. When you see a stray “r” or “n”, assume it should have a backslash in front of it. Also, the value of “from” should have an email address in angle brackets after the text name.
Thanks for the info, does anyone know how to create these ics files so that they can be assigned to another user?
I have developed a PHP app and we use Outlook with the shared calendar system. We book in appointments for our staff but was wondering whether it would be possible to automatically load the appointments into the users calendar rather than my own.
I need an answer to this fairly quickly, please please help!!!
No clue. What happens when you specify these users as attendees for your event? Does it show up on their calendars?
If not then I have no clue. Also I have no shared calendar setup to test it with so good luck with that.
is there a way you can push this to receiver’s calendar?
I think further testing on my side needs to be done!
Hi ,
I need to send meeting requests(outlook) to different people through PHP.
I figure sending a .ics file as attachment to an email will do the job.
i am stuck, my implementation will send a mail, with the contents of the .ics file as part of the body of the mail. If somebody has got this working, can you please help out?
Hi Kris
I managed to get my php app working with a downloadable ics file. I am only struggling with assigning this to a person.
I would suggest you read the rfc2445 and the wikipedia on icalendar files. Which part are you struggling with exactly? I will try my best to point you in the right direction.
The ics file directly, not like attach !!!
Hi
I have been creating vcal .vcs files. the one problem I have is that the users use outlook. when i create a weblink to the vcs file and they use ie to browse to it it opens in outlook and creates the entry, BUT if they use ff then it opens the vcs in a seperate browser window. Is there anyway I can force it that when they browse to the vcs file that it opens outlook and create the cal entry and not open ff?
Thanks in advance.
Kobus
hi,
I am trying to add more then 2 Events in the same posted example. But unfortunately getting only one Event in the result.
I think we can add multiple Event in it and can view it by clicking on the “Next Item” and “Prev Item”.
Can any one please help me
Hi to All,
I have successfully created the iCal file, now I want to insert the event timings to the user’s outlook calendar, please let me know is there any way in programmatically?
Expecting your reply
Same posting, but new problem.
I’m sending an invite to a normal person and a non-person Outlook user that has an auto-accept agent in place. This is a communal calendar that is referenced by many, but nobody logs on as that user.
The appointment to the person shows up just fine, but the appointment for the non-person has no reminder or description, and the subject looks like this:
{4961A22F-E29C-4EC4-AE8F-9A1239C3AE72}.EML
Another oddity is that the organizer appears twice in the list of attendees that the non-person sees.
The auto-accept agent itself seems functional, because the event organizer is also an auto-accepting non-person, and the event shows up correctly there. So it’s the vcalendar content that is suspect. The content of the invitation attachment is below.
Any ideas out there as to what is going wrong?
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
TRANSP:TRANSPARENT
BEGIN:VEVENT
DTSTAMP:20090707T183855Z
UID:056ef96f-aecd-474a-b82f-745c11850f30
DESCRIPTION:My description\n
LOCATION:
DTSTART:20090710T090000
ORGANIZER;CN=My Organizer:MAILTO:organizer@domain.com
X-MICROSOFT-CDO-BUSYSTATUS:FREE
X-MICROSOFT-CDO-INTENDEDSTATUS:FREE
X-MICROSOFT-CDO-IMPORTANCE:1
BEGIN:VALARM
TRIGGER:-PT1M
ACTION:DISPLAY
DESCRIPTION:REMINDER
END:VALARM
DTEND:20090710T093000
ORGANIZER;CN=My Organizer:mailto:organizer@domain.com
ATTENDEE;CN=Non person user;ROLE=REQ-PARTICIPANT;RSVP=FALSE:mailto:nonperson@domain.com
ATTENDEE;CN=Normal User;ROLE=REQ-PARTICIPANT;RSVP=FALSE:mailto:user@domain.com
END:VEVENT
END:VCALENDAR
I’m going to give this a try in a bit, but I stumbled in from google and just wanted to thanks for the article.
Thank you very much! I have tested it with Google Calendar and works great! Also since it is meant for Outlook I’m sure it will work there too
I’m going a little crazy with Outlook and time zones, and even though it’s only tangentially related to your post I thought I’d comment in case you can point me in the right direction to look for help. (Maybe you know of an appropriate forum.)
I have a little script that outputs .ics files, and I serve it from the web as you do. It references the Olson time zone and has every event in the local time, which works great with calendaring applications other than Outlook. Outlook seems not to recognize that I’ve taken daylight savings time into account for all the event times, and so during DST pushes each event forward an hour, which of course makes them wrong by one hour.
This is because I am in blatant disregard for the standard, which requires lines about DAYLIGHT START in the beginning of the ICS file. But surely I don’t have to put lines in the beginning of the file that specify exactly when daylight savings time is. Can’t I specify somewhere that I’ve taken it all into account, and each time should just be recognized as local, and no further adjustments for daylight savings time are necessary?
Anyway thanks for your great post (and the next one on women, which I’m about to read), and if you know of a forum where I should ask this please let me know.
I realize this is an older post, but I found some other information that states the timestamps should be in the format: YYYMMDDxHHMMSSz format (x being a T, z being Z). These can be formatted by simply using:
echo "DTSTAMP:".date('Ymd\THis\Z')."\n";
which uses only one date() function rather than 2 along with other concatenations.
echo "DTSTAMP:".date('Ymd').'T'.date('His')."Z\n";
I have not fully tested this yet, but this may cause some issues with exchange servers.
This is very useful detail. now I am facing one issue. In the description , I have some content which need new line. I was trying \n as well tag. but both are not working. I am using PHP as a programming language.
Any help will be appreciated.
Hi All, This is the best place where i found good info about iCal.
I will be very thankful, if you can resolve my issue.
I am creating .iCal (/.ics) file using C#. and sending the same to the attendee as a mail attachment and the mediatype of attachment as “text/calendar”. because of this the attachment is shown as direct invitation to the meeting rather as an attachment. But here i am loosing the decsription data. Everything else is good. What could be going wrong? Below is the basic iCal File.
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20110817T083000Z
DTEND:20110817T093000Z
TRANSP:OPAQUE
DTSTAMP:20110822T094701Z
SEQUENCE:0
CLASS:PUBLIC
DESCRIPTION:You are scheduled to interview a candidate.\n\nCandidate: KV P\nOffice: Hyderabad\nPosition: Product Developer\nHiring Manager: \n\nYou can view the schedule and other candidate information by visiting http://iswebdeva01/Recruiting/Interview/InterviewView.aspx?InterviewID =33547\n\nIf you’re not available to interview the candidate, please contact Vamsi Praveen Karanam.
SUMMARY:Interview – KV P
UID:8e4211f0-fa83-4a6a-a600-007dcc613d46
END:VEVENT
END:VCALENDAR
Thanks in advance
@ Vamsi Praveen K:
Please skip “:” after “candiadate”, office” by “\:”
Great discussion here. I realize this is an older post, but hopefully someone has seen the issue I am experiencing. I am sending an ICS file as an email attachment from our java web app. Everything works fine if I send the email to an Outlook user that is not on an Exchange server. Their email has the correct “Accept/Reject” buttons and their calendar gets updated accordingly.
If the user is on an Exchange server, however, this does not happen. They get a meeting invite, but it lists them as the organizer and they cannot change the meeting details. Then they are unable to save the meeting to their calendar.
Has anyone else experienced this? Any ideas or suggestions are appreciated.
@ Jeff:
Jeff –
I have this exact same issue. Did you ever find a solution?
Thanks,
Ben
Someone asked about line breaks.
The correct format is:
BACKSLASH (US-ASCII decimal 92) followed by a LATIN CAPITAL LETTER N (US-ASCII decimal 78)
as noted in this documentation: http://www.kanzaki.com/docs/ical/text.html
It also says that small “n” works, but it doesn’t (at least not with the code here presented), I tried it with capital N and it works nicely.
Thanks by the way to the author, this was really helpful, I hope I can give back something with this reply.
The script gave me inspiration for the outlook calendar I need to create for my sailing club (http://www.shirehamptonsailingclub.co.uk). Keep the good work.
Thanks to all of you.
I’ve been searching for that for a while.
Thank you very much, your post was really helpful, I missed the “METHOD:REQUEST” parameter and the event wasn’t correctly displayed as an invitation in IE
Image 23. Fire. For many reasons this group are the ones that eat of
out boxes and bags.
Thanks for this. Here I found another example of sending meeting request to multiple participants in Outlook: http://arturito.net/2014/01/27/creat…g-request-php/ and for more options VCalendar has a reference on wiki : http://en.wikipedia.org/wiki/ICalendar
I am trying to create calender event for outlook to achieve the same I am using
with Yii, PHPMailer and above code but, in reply in oulook inbox I am getting reply like this and it is not showing attached file as well.
OUTPUT
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Foobar Corporation//NONSGML Foobar//EN METHOD:REQUEST BEGIN:VEVENT UID:20150701T163528-439844097-example.com DTSTAMP:20150701T163528 DTSTART:20080413T000000 SUMMARY:TEST DESCRIPTION: this is just a test END:VEVENT END:VCALENDAR
Code
$header = ‘MIME-Version: 1.0’ . “\n”;
$header .= ‘Content-type: text/html; charset=utf-8’ . “\n”;
$header .= “Content-Type: text/Calendar”;
$header .= “Content-Disposition: inline; filename=calender.ics”;
$message = “BEGIN:VCALENDAR\n”;
$message .= “VERSION:2.0\n”;
$message .= “PRODID:-//Foobar Corporation//NONSGML Foobar//EN\n”;
$message .= “METHOD:REQUEST\n”; // requied by Outlook
$message .= “BEGIN:VEVENT\n”;
$message .= “UID:”.date(‘Ymd’).’T’.date(‘His’).”-“.rand().”-example.com\n”; // required by Outlok
$message .= “DTSTAMP:”.date(‘Ymd’).’T’.date(‘His’).”\n”; // required by Outlook
$message .= “DTSTART:20080413T000000\n”;
$message .= “SUMMARY:TEST\n”;
$message .= “DESCRIPTION: this is just a test\n”;
$message .= “END:VEVENT\n”;
$message .= “END:VCALENDAR\n”;
Please help me to resolve this issue