2005-05-28

Passing MS Outlook meeting requests from Mail to iCal

Mail's supposed to be able to do this itself. There's an option "Add invitations to iCal" in the preferences, and I have it set to "automatically". Yet it does nothing.

Mail shows me the text/plain or text/html alternate, and there isn't even an attachment icon for the text/calendar form.

I had hoped that this would be my first opportunity to make real use of mdfind(1), but mdls(1) shows that there's nothing useful stored about a message containing a meeting request:

kMDItemAttributeChangeDate = 2005-05-25 09:42:11 -0700
kMDItemAuthorEmailAddresses = ("user@mail.server")
kMDItemAuthors = ("Martin Dorey")
kMDItemContentCreationDate = 2005-05-24 13:12:22 -0700
kMDItemContentModificationDate = 2005-05-25 09:42:07 -0700
kMDItemContentType = "com.apple.mail.emlx"
kMDItemContentTypeTree = ("com.apple.mail.emlx", "public.data",
"public.item", "public.message")
kMDItemDisplayName = "Buy FogBugz"
kMDItemFSContentChangeDate = 2005-05-25 09:42:07 -0700
kMDItemFSCreationDate = 2005-05-24 13:13:14 -0700
kMDItemFSCreatorCode = 0
kMDItemFSFinderFlags = 0
kMDItemFSInvisible = 0
kMDItemFSLabel = 0
kMDItemFSName = "14660.emlx"
kMDItemFSNodeCount = 0
kMDItemFSOwnerGroupID = 501
kMDItemFSOwnerUserID = 501
kMDItemFSSize = 6195
kMDItemFSTypeCode = 0
kMDItemID = 3638978
kMDItemKind = "emlx"
kMDItemLastUsedDate = 2005-05-24 13:12:22 -0700
kMDItemRecipientEmailAddresses = ("user@mail.server")
kMDItemRecipients = ("Elliott Hughes")
kMDItemTitle = "Buy FogBugz"

So traditional Unix tools will have to do. Fine by me...

#!/usr/bin/ruby -w

require 'tempfile.rb'

inbox_roots = "~/Library/Mail/*/INBOX.imapmbox/Messages"

filenames=`find #{inbox_roots} -name "*.emlx" -print0 | xargs -0 grep -wl text/calendar`.split("\n")
filenames.each() {
|filename|
puts("Extracting meeting request from '#{filename}'...")
filename =~ /\/(\d+).emlx$/
message_id = $1

# Pull just the .ics data out of the message.
message = File.new(filename).read()
message =~ /\btext\/calendar\b.*\n\n(.*)\n\n/m
meeting_request = $1

# iCal is clever enough (it seems) to recognize the identical
# UID, so we don't have to bother.
ics_filename = "/tmp/meeting_request.#{message_id}.ics"
ics_file = File.new(ics_filename, "w")
ics_file.puts(meeting_request)
system("open #{ics_filename}")
}
exit(0)

It took me less time to write that than I've spent complaining about the lack/brokennesss of this functionality.

I'd rather things just worked, as they're supposed to on Mac OS, but this will do in the meantime. (I don't know what was supposed to happen under 10.3, but there I used to find that meeting requests wouldn't appear in Mail at all. I could connect to the IMAP server myself and LIST and RETR them, but Mail either couldn't see them, or wouldn't show them.)