Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ExDAV – Exchange to CalDAV Syncer

ExDAV synchronizes the calendar of a Microsoft Exchange account to a CalDAV server such as Nextcloud, SOGo or Mailcow. Currently, only one-way synchronization from Exchange to CalDAV is supported. The synchronization covers single events, recurring series, modified occurrences and deletions.

Exchange is accessed read-only; existing non-ExDAV events in the target calendar are left untouched. A dry-run mode is available to preview changes before they are written.

Features

  • Strictly one-way synchronization with read-only access to Exchange
  • Creates, updates and removes CalDAV copies as Exchange events change
  • Supports single events, recurring series, modified occurrences and deletions
  • Works with Nextcloud, SOGo and Mailcow calendars
  • Leaves existing non-ExDAV events in the target calendar untouched
  • Offers a dry-run mode to preview changes before writing them
  • Stores synchronization state and operational logs in a local SQLite database

Supported Attributes

Exchange event attribute CalDAV/iCalendar property Behavior
Subject SUMMARY Copied as the event title
Plain-text body DESCRIPTION HTML-only bodies are not copied
Location LOCATION Copied as plain text
Categories CATEGORIES All categories are copied
Start DTSTART Timed single events are written in UTC
End DTEND Written as the event's end, not as a duration
All-day setting DTSTART, DTEND Written as dates with an exclusive end date
Start and end time zones DTSTART, DTEND, VTIMEZONE Recurring events retain their IANA time zone
Sensitivity CLASS Mapped to public, private or confidential
Free/busy state TRANSP Free events are transparent; others are busy
Tentative state STATUS Written as tentative when Exchange reports it
Cancellation state STATUS Cancelled events are marked as cancelled
Appointment sequence SEQUENCE Copied when available
Creation time CREATED Copied when available
Last modification time LAST-MODIFIED, DTSTAMP Used as the event's latest timestamp
Exchange UID X-EXDAV-SOURCE-UID Kept for reference; the CalDAV UID is generated by ExDAV
Recurrence rule RRULE Supports daily, weekly, monthly and yearly series
Additional recurrence dates RDATE Copied when supported by Exchange recurrence data
Deleted occurrences EXDATE Removed dates are excluded from the series
Modified occurrences RECURRENCE-ID Copies changed time, text, location, categories, privacy and status

ExDAV does not copy organizers, attendees, reminders, attachments, HTML bodies or unknown Exchange-specific properties.

Setup and Usage

Requirements

  • Linux or macOS operating system.
  • Conda or Miniconda package/environment management.
  • Read access to a Microsoft Exchange mailbox through EWS.
  • Read/write access to a Nextcloud, SOGo or Mailcow CalDAV calendar.

1. Set Up ExDAV

Place the ExDAV source files in ~/ExDAV. Then create a Python 3.12 conda environment and install its pinned dependencies:

cd ~/ExDAV

conda create --name exdav python=3.12 pip
conda activate exdav

python -m pip install -r ~/ExDAV/requirements.txt

2. Create the Configuration

Rename the example configuration and restrict it to the current user:

mv ~/ExDAV/config.example.toml ~/ExDAV/config.toml
chmod 600 ~/ExDAV/config.toml

Edit ~/ExDAV/config.toml and provide:

  • The Exchange server hostname, mailbox, credentials and IANA time zone.
  • The CalDAV server type, HTTPS URL, credentials and target calendar name.
  • The database saving location and operation timeout. Use an absolute database path.

ExDAV reads config.toml from the current working directory. Run all ExDAV commands from ~/ExDAV.

The Exchange server must be a hostname, not a URL. Common CalDAV root URLs are:

Server Example URL
Nextcloud https://cloud.example.com/remote.php/dav
SOGo https://sogo.example.com/SOGo/dav
Mailcow https://mail.example.com/SOGo/dav

3. Initialize the Sync

Initialize ExDAV once after the final Exchange and CalDAV settings are in place:

python -m exdav init

The state database links Exchange events to their CalDAV copies. Keep it in a durable location and back it up; deleting it can cause duplicate events.

4. Preview and Run

Preview the next synchronization without changing CalDAV:

python -m exdav sync --dry-run

To run a synchronization:

python -m exdav sync

If the conda environment is not active yet, use:

cd ~/ExDAV
conda run --name exdav python -m exdav sync

Commands

Command Purpose
python -m exdav init Discover both calendars and initialize the synchronization state
python -m exdav sync Run one synchronization from Exchange to CalDAV
python -m exdav sync --dry-run Preview creates, updates and deletions without changing CalDAV
python -m exdav retry-exhausted Reopen operations blocked after exhausting their bounded retry cycle
python -m exdav status Show state, recent activity and connection health
python -m exdav log Show stored operational logs without contacting either server

How It Works

ExDAV is built on three established Python libraries:

  • exchangelib reads calendar events and changes through Exchange Web Services (EWS).
  • icalendar converts and sanitizes events into standard iCalendar data.
  • python-caldav discovers the target calendar and creates, updates or removes CalDAV resources.

ExDAV assigns its own stable UID to every copied event and marks it with X-EXDAV-MANAGED. This lets it manage only the resources it created while leaving other events in the CalDAV calendar alone.

ExDAV was tested using live Microsoft Exchange 2016, Nextloud 34, Mailcow 2026-03b and SoGO 5.12.8 servers.

About

ExDAV is a one-way calendar synchronization tool that synchronizes Microsoft Exchange calendars to CalDAV servers such as Nextcloud, SOGo and Mailcow

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages