Last active
August 15, 2020 12:12
-
-
Save afragen/5177811 to your computer and use it in GitHub Desktop.
Script for automatically extracting calendar items from meeting requests in Mail.app and adding them into iCal. It will always extract into the first local calendar.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
Script for automatically extracting calendar items from meeting requests | |
and adding them into iCal. It will always extract into the first local calendar. | |
written by Andy Fragen <[email protected]> | |
modified to run from AppleScript menu | |
http://www.macosxhints.com/article.php?story=20060821073102694 | |
http://bbs.macscripter.net/viewtopic.php?id=17655 | |
Special thanks to Martin Herrera Soler for loads of exceptions. ;-) | |
Special thanks to Michael Bartz showing me replies. | |
Abstracted the grep and sed to work better with other Exchange invites. | |
05 Aug 2008 - Fixed to run as rule | |
07 Aug 2008 - Fixed for invites as attachments only | |
11 Aug 2008 - Cleaned up code and fixed for METHOD:PUBLISH | |
12 Aug 2008 - Fixed code to work with METHOD:CANCEL | |
14 Aug 2008 - Cleaned up code, user will still need to manually delete cancelled events | |
05 Sept 2008 - Fixed sed substitution to remove quotes from DTSTART;TZID and DTEND;TZID, more CalDAV compliant | |
29 Sept 2008 - Fixed for problem when attachment name identical then latest .ics attachment not saved, move /tmp/*.ics to Trash | |
03 Dec 2008 - Fixed to remove modal dialog from METHOD:PUBLISH invites by changing to METHOD:REQUEST, fixed a few things | |
28 Dec 2008 - Added ability to allow for multiple exchange servers with only one script | |
13 Jan 2009 - Removed need for defining calendar for cancelling events | |
08 Sept 2009 - Fixed for goofy Snow Leopard problem openning .ics file | |
29 Sept 2009 - Added ability to fix event replies, Simplified parts of the script and cleaned up code | |
30 Sept 2009 - Cleaned up code some more | |
*) | |
--The following 2 properties allow for use with multiple Exchange Servers. You must have the exchange_fragment in the same list position as its ical_tzid | |
-- Add or change these values to include a unique fragment of the Exchange Server's TZID | |
property exchange_fragment : {"Central", "GMT -0800", "Montevideo", "Perth"} | |
--Change these values to what your iCal time zone expects. This is *not* your local timezone. It is the timezone of the Exchange server in proper iCal format. No spaces allowed; but they will be fixed. | |
property ical_tzid : {"US/Central", "US/Pacific", "America/Buenos Aires", "Australia/Perth"} | |
using terms from application "Mail" | |
on perform mail action with messages theMessages for rule theRule | |
set thepath to ((path to startup disk) as string) & "tmp:temp_invite.ics" | |
my make_iCal_Event(thepath, theMessages) | |
end perform mail action with messages | |
end using terms from | |
on run {} | |
set thepath to ((path to startup disk) as string) & "tmp:temp_invite.ics" | |
tell application "Mail" to set theMessages to selected messages of message viewer 1 | |
my make_iCal_Event(thepath, theMessages) | |
end run | |
on make_iCal_Event(thepath, theMessages) | |
repeat with theMessage in theMessages | |
set flRequest to false | |
set flPublish to false | |
set flCancel to false | |
set flReply to false | |
set theInvite to "" | |
tell application "Mail" to set theSource to the source of theMessage | |
tell application "Mail" to set theSubject to the subject of theMessage | |
(* Get the ics data *) | |
if (the offset of "content-class: urn:content-classes:calendarmessage" in theSource) is not equal to 0 then | |
(* Find the range of the message source that is an ics message | |
Note: this works both on messages that detect the .ics attachement, | |
and on crappy Exchange invites that show up as an owa url. *) | |
set vcalBegin to the offset of "BEGIN:VCALENDAR" in theSource | |
set vcalEnd to (the offset of "END:VCALENDAR" in theSource) + (the length of "END:VCALENDAR") | |
set theInvite to the text vcalBegin thru vcalEnd of theSource | |
else | |
set theInvite to my icsAttachment(theMessage) | |
end if | |
(* Only deal with requests *) | |
if (the offset of "METHOD:REQUEST" in theInvite) is equal to 0 then | |
(* do nothing *) | |
else | |
set flRequest to true | |
end if | |
(* Only deal with publishes *) | |
if (the offset of "METHOD:PUBLISH" in theInvite) is equal to 0 then | |
(* do nothing *) | |
else | |
set flPublish to true | |
end if | |
(* Only deal with cancellations *) | |
if (the offset of "METHOD:CANCEL" in theInvite) is equal to 0 then | |
(* do nothing *) | |
else | |
set flCancel to true | |
end if | |
(* Only deal with replies *) | |
if (the offset of "METHOD:REPLY" in theInvite) is equal to 0 then | |
(* do nothing *) | |
else | |
set flReply to true | |
end if | |
set thepath to my writeEvent(thepath, theInvite) | |
my process_event(thepath, flRequest, flPublish, flCancel, flReply, theSubject) | |
end repeat | |
tell application "Mail" to set theSource to "" | |
tell application "Mail" to set theInvite to "" | |
(* delete the file *) | |
do shell script "mv /tmp/*.ics ~/.Trash/" | |
end make_iCal_Event | |
on writeEvent(thepath, theInvite) | |
(* write to a temp file *) | |
set fh to open for access thepath with write permission | |
set eof fh to 0 | |
write theInvite to fh as string | |
close access fh | |
return thepath | |
end writeEvent | |
on icsAttachment(theMessage) | |
tell application "Mail" | |
if theMessage's mail attachments is not {} then | |
repeat with theAttachment in theMessage's mail attachments | |
set attachmentName to the name of theAttachment | |
if attachmentName ends with ".ics" then | |
set attachmentName to do shell script "echo \"" & attachmentName & "\" | sed 's/ //g'" | |
set theFileName to ((path to startup disk) as string) & "tmp:" & attachmentName | |
try | |
save theAttachment in theFileName | |
on error errnum | |
end try | |
else | |
return | |
end if | |
end repeat | |
end if | |
end tell | |
return read file theFileName | |
end icsAttachment | |
on process_event(thepath, flRequest, flPublish, flCancel, flReply, theSubject) | |
set tPath to POSIX path of thepath | |
if flRequest then | |
my fix_TZID(thepath) | |
else if flPublish then | |
do shell script "sed 's|METHOD:PUBLISH|METHOD:REQUEST|g' " & tPath & " > " & tPath & "2" | |
do shell script "mv " & tPath & "2 " & tPath | |
else if flCancel then | |
my fix_TZID(thepath) | |
else if flReply then | |
if not my fix_TZID(thepath) then | |
ignoring case | |
if theSubject contains "accept" then | |
set theStatus to "ACCEPTED" | |
else if theSubject contains "declined" then | |
set theStatus to "DECLINED" | |
else | |
set theStatus to "TENTATIVE" | |
end if | |
end ignoring | |
do shell script "sed 's|ORGANIZER|ATTENDEE|g;s/:MAILTO/;PARTSTAT=" & theStatus & ":MAILTO/g' " & tPath & " > " & tPath & "2" | |
do shell script "mv " & tPath & "2 " & tPath | |
end if | |
end if | |
(* open in iCal *) | |
tell application "Calendar" to activate | |
try | |
tell application "Calendar" to open alias thepath | |
on error | |
--Snow Leopard kludge | |
set tPath to POSIX path of thepath | |
do shell script "open " & tPath | |
end try | |
end process_event | |
on fix_TZID(thepath) --fix for Outlook TZID weirdness | |
set tPath to POSIX path of thepath | |
repeat with i from 1 to the length of ical_tzid | |
--this should automatically grab the TZID that Exchange gives | |
set exchange_tzid to do shell script "grep -o ^TZID.*$ " & tPath & " | sed -e 's|TZID:\\(.*\\)|\\1|g'" | |
if exchange_tzid contains item i of exchange_fragment then | |
--make sure user input doesn't have spaces :-) | |
set item i of ical_tzid to do shell script "echo \"" & item i of ical_tzid & "\"| sed 's/ /_/g'" | |
--possible fix if TZID is on 2 lines (unable to test) | |
--set exchange_tzid to do shell script "sed -n '/TZID:/{N;p;}' " & tPath & " | sed 's/TZID://g' | tr -d '\\n'" | |
set quoted_ical_tzid to "\"" & item i of ical_tzid & "\"" | |
if exchange_tzid is not "" then | |
do shell script "sed 's|" & exchange_tzid & "|" & item i of ical_tzid & "|g;s|" & quoted_ical_tzid & "|" & item i of ical_tzid & "|g' " & tPath & " > " & tPath & "2" | |
do shell script "mv " & tPath & "2 " & tPath | |
end if | |
end if | |
end repeat | |
if exchange_tzid is "" then return false | |
return true | |
end fix_TZID |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That's an impressive amount of work. Kudos to you!! (and shame on Apple for making it necessary.)