Outlook Org-mode integration on MacOS
Motivation
So a lot of my notes and tasks will require me to reference outlook items, either emails or meetings.
There aren’t any real solutions for Achieving this on MacOS at the moment, and the Windows solutions are not too great.
So I decided to create this unholy abomination. I’m sorry.
Components
So there’s a few moving parts to this, but overall it’s mainly leverging AppleScript, Karabiner and Emacs to provide this functionality.
AppleScript
Let’s start with the MacOS Native automation tools, this is how we’ll get the ID of the Outlook item, which we will need later when searching for it.
There are two AppleScript files, one for inserting a link into the current buffer, and another for using a capture template. Both are almost identical, but one evals some Elisp to ensure we insert at the right point and file.
Insertion
tell application "Microsoft Outlook"
set theMessages to selected objects
repeat with theMessage in theMessages
set toOpen to id of theMessage
end repeat
end tell
tell application "Emacs" to activate
do shell script "/usr/local/bin/emacsclient --eval '(with-current-buffer (window-buffer) (org-insert-link nil \"outlook:" & toOpen & "\" (read-string \"Link Name:\")))'"
Capture
tell application "Microsoft Outlook"
set theMessages to selected objects
repeat with theMessage in theMessages
set toOpen to id of theMessage
end repeat
end tell
tell application "Emacs" to activate
do shell script "/usr/local/bin/emacsclient \"org-protocol://capture?template=o&url=" & toOpen & "\""
Karabiner
Karabiner provides a very nice way of running a shell script from a keybind, and even supports filtering to the correct window. Thus this keybind will only trigger when Outlook is focused.
Command+L will insert and Command+Shift+L will capture
{
"title": "Outlook-Emacs",
"rules": [
{
"description": "Meta-L to copy outlook item to orgmode",
"manipulators": [
{
"type": "basic",
"from": {
"key_code": "l",
"modifiers": {
"mandatory": ["left_command"],
"optional": ["caps_lock"]
}
},
"to": [
{
"shell_command": "osascript ~/Documents/Store_Selected_OutlookItem_As_Orgmode_Link.scpt"
}
],
"conditions": [
{
"type": "frontmost_application_if",
"bundle_identifiers": ["^com\\.microsoft\\.Outlook$"]
}
]
}
]
},
{
"description": "Meta-L to copy outlook item to orgmode",
"manipulators": [
{
"type": "basic",
"from": {
"key_code": "l",
"modifiers": {
"mandatory": ["left_command", "left_shift"],
"optional": ["caps_lock"]
}
},
"to": [
{
"shell_command": "osascript ~/Documents/Capture_Selected_OutlookItem_As_Orgmode_Link.scpt"
}
],
"conditions": [
{
"type": "frontmost_application_if",
"bundle_identifiers": ["^com\\.microsoft\\.Outlook$"]
}
]
}
]
}
]
}
Emacs
There are two parts of this for Emacs, the Capture template, and the custom hyperlink
Custom Link
I just dump this into my startup config, but you could make an ol-outlook.el
if you wanted to make it less platform specific.
This relies on MDFind which is the macos spotlight CLI, it will find it, then open it in outlook.
(require 'ol)
(org-add-link-type "outlook" 'org-outlook-open)
(defun org-outlook-open (id _)
"Open the outlook item matching that ID"
(shell-command (format "mdfind \"com_microsoft_outlook_recordID == '%s'\" -0 | xargs -0 open " id)))
Capture template
Ideally this should be customized more for your setup, but this is what I use.
(add-to-list 'org-capture-templates '("o" "Outlook item to capture" entry
(file+headline "~/Documents/Notes/inbox.org" "Tasks")
"* TODO [[outlook:%:link][%^{Item name|Email}]]" :clock-in t :clock-resume t))