Conquer your Microsoft Outlook agenda from the comfort of Emacs.
Disclaimer: org-outlook is currently in beta. Updates & responses to issues will be sporadic.
- Integrated with org-roam
- Find outlook events with
org-roam-node-find - Refile outlook events to any file within
org-roam-directory - Each recurring event instance has unique ID for individual refiling
- Find outlook events with
- Accept and Decline meeting requests from the agenda buffer
- Join Teams calls directly from the agenda buffer (launches Teams or web browser)
- At-a-glance overview of your appointments and fee timeslots when used with org-timeblock
- Org capture template to quickly plan meetings (needs testing).
Planned features & improvements:
- Reduce the number of dependencies
- More configurability
- Two-way sync of event body (owned events only).
Future:
- Org contacts integration
Upon first launch you will be asked to give org-outlook permission to read and write to
your Outlook calendar. Note: Some organisations will have disabled third-party
applications. In this case, unfortunately, you won’t be able to use org-outlook.
- gnupg: org-outlook requires you to have a public/private gpg keypair capable of encryption
- html2org
- org-ml
- org-roam
- org-msg
- emacs-request
- htmlize
A standard oauth client is provided with org-outlook, you are of course, free to use your
own Microsoft Entra App Registration instead. To do so you will need to create an App
Registration in Microsoft Entra (Formally Azure Active Directory) via
https://portal.azure.com. Optionally make a note of your tenant-id (you can provide
org-outlook-tenant-id to restrict the scope of your app to your Azure tenant). The app
will need the Calendars.Read, Calendars.ReadWrite, and offline_access API
permissions. Under “Authentication” click Add a platform and add http://localhost:9004 as
the redirect uri. At the bottom of the page ensure Allow public client flows is toggled to
“Yes”. From the “Overview” tab copy the Application (client) id and insert into your
config as specified below.
The package org-outlook is not currently available from MELPA, but can be installed
directly from github with Quelpa.
Installing with Quelpa is easy:
- Install quelpa-use-package (which can be installed directly from MELPA).
- Add this form to your init file:
(use-package org-outlook
:quelpa (org-outlook :fetcher github :repo "ifitzpat/org-outlook")
:config
;; Optional: Use your own Microsoft Entra App Registration
;(setq org-outlook-client-id "client-id-of-your-registered-app")
;(setq org-outlook-tenant-id "your-azure-tenant-id")
;; Required settings
(setq org-outlook-gpg-recipient "you@example.com")
(setq org-outlook-local-timezone "Europe/Berlin") ; Your local time zone
(setq org-outlook-file "/path/to/outlook.org")
;; Sync range (number of days)
(setq org-outlook-sync-start 14) ; days in the past to keep in sync
(setq org-outlook-sync-end 90) ; days in the future to keep in sync
;; Optional: Customize full sync frequency (default: 7 days)
(setq org-outlook-full-sync-interval-days 7) ; weekly validation
;(setq org-outlook-full-sync-interval-days 14) ; bi-weekly validation
;(setq org-outlook-full-sync-interval-days nil) ; disable automatic full syncs
)- Syncing Outlook events:
M-x org-outlook-sync- Intelligent sync (uses delta sync when possible, falls back to full sync as needed)C-u M-x org-outlook-sync- Force full sync (syncs all events regardless)M-x org-outlook-full-sync- Direct full sync
How sync works:
- First run: Automatically performs full sync and initializes delta tracking
- Daily use: Fast delta sync (only processes changes since last sync)
- Weekly: Automatic full sync for validation (configurable with
org-outlook-full-sync-interval-days) - Error recovery: Falls back to full sync if delta sync fails
- Deleted events: Automatically removed during delta sync
- Accepting a meeting request:
- With point on the entry in the agenda view or within the org entry body:
org-outlook-accept-event
- With point on the entry in the agenda view or within the org entry body:
- Declining a meeting request:
- With point on the entry in the agenda view or within the org entry body:
org-outlook-decline-event
- With point on the entry in the agenda view or within the org entry body:
- Joining a Teams meeting:
- With point on the entry in the agenda view or within the org entry body:
org-outlook-join-teams-call
- With point on the entry in the agenda view or within the org entry body:
- Calling
org-outlook-syncviaemacs --batchavoids blocking your main emacs session.
Note: Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases.
Major stability and reliability improvements:
- Issue #1 - DST Duplicates: Fixed duplicate events during daylight saving time transitions
- Event IDs now use Outlook ID directly (stable across DST changes)
- Fixed timestamp parsing to handle local timezone correctly
- Added error handling for stale org-id cache
- Each recurring event instance has unique, stable ID
- Issue #2 - Refresh Token: Fixed reversed logic that prevented automatic OAuth flow when refresh token expired
- Issue #3 - Auth Code Race Conditions: Removed blocking sleeps and race conditions from OAuth flow
- Non-blocking authentication with 5-minute timeout (up from 90 seconds)
- Proper async handling with state tracking
- Better user feedback and error messages
- Issue #4 - Deleted Meetings: Implemented intelligent hybrid sync
- Delta sync for fast daily syncs
- Automatic full sync for periodic validation
- Handles deleted and cancelled events properly
- Self-healing with automatic error recovery
- Intelligent hybrid sync system (
org-outlook-sync)- Fast delta sync by default
- Weekly full sync validation (configurable)
- Automatic fallback on errors
- New configuration variable:
org-outlook-full-sync-interval-days - Force full sync with prefix argument:
C-u M-x org-outlook-sync
org-outlook-syncbehavior changed: now uses delta sync by default (was full sync)- Old full sync is now
org-outlook-full-sync - Event IDs changed (will cause re-sync on first run)
Fix issue where request token times out
Fix hashing of PKCE code
Potential fix for duplicate event creation when going to/from DST
Switch to PKCE oauth flow & provide default auth client
Initial release
- Accepting an event doesn’t change the event status from
REQUESTtoMEETINGuntil the next sync.
- ✅ DST duplicate events (fixed in 0.1.0)
- ✅ Refresh token timeout handling (fixed in 0.1.0)
- ✅ OAuth authentication race conditions (fixed in 0.1.0)
- ✅ Deleted meetings not removed from org mode (fixed in 0.1.0)
GPLv3