CalSub reads an iCalendar (ics) source and writes the events into a CalDAV calendar. Use CalSub to add calendar subscriptions to CalDAV servers.

Using calsub

To get started with Miln CalSub, download and expand the executable file onto your computer.

CalSub is a single executable file. It does not need to be installed, can be run from any directory, and can be removed by deleting the file.

Let’s walk through an example use of calsub and then consider other options. Consider this command line call:

./calsub -ics https://localhost/work.ics -caldav https://example.com/caldav/you -cal work -netrc ~/.netrc

The flags for this call to calsub are:

-ics https://work.intranet/work.ics
The URI to read an ics formatted calendar from. In this example, the calendar is on another server.
-caldav https://example.com/caldav/you
The CalDAV destination server. This the CalDAV service that the events will be written to.
-cal work
The display name of an existing calendar on the CalDAV service specified with -caldav.
-netrc ~/.netrc
The path to a netrc formatted credentials file. This file contains any username and password needed to access the CalDAV service specified with -caldav.

What Happens

So what happens when this command is issued?

calsub does the following:

The interesting part is the comparison of the two sets of events. What determines if an event needs to be added, removed, or ignored as unchanged?

Comparing Events

CalSub uses two CalDAV properties to compare calendar events:

If an event with no matching Unique Identifier is read from the ics source, it is added.

If an event exists in the destination calendar with no matching Unique Identifier, the event is noted as removed. What happens to these events is controlled by CalSub’s removal behaviour.

If Last Modified is missing or differs between events with the same Unique Identifier, then the event is deemed as changed. The source event is added and the destination event is removed.

If Last Modified matches an existing events with the same Unique Identifier, then the event is noted as unchanged.

Removal Behaviour

How existing and removed events are treated depends on the -remove flag. The flag can be:

all
Remove all the existing events and write all the events. This behaviour makes no attempt to determine if an event already exists. All existing events are removed from the destination calendar, before attempting to write the source calendar’s events.
unknown
Remove only the unknown events. This behaviour removes events that do not appear in the source calendar. Unchanged events that exist in both the source and destination are skipped. This is best behaviour when you want to synchronise a calendar because it reduces the number of removals and writes.
error
Remove nothing but events that were created when calsub encountered an error. This behaviour accumulates events in the destination. This can be useful if you never want to remove old events but want to append new ones. Existing but unchanged events are left untouched.

The default behaviour is error. This is the default because non-CalSub events are left unchanged in destination calendar. This behaviour is the least risky.

Dry Run and Testing

CalSub includes a -dry-run flag. When the -dry-run flag is set, calsub will not make any changes to the destination calendar. Dry run is designed for checking settings and testing the expected behaviour.

./calsub -ics work.ics -caldav https://example.com/caldav/you -cal work -netrc ~/.netrc -dry-run

Intended Use

CalSub was written to overcome the lack of subscription calendar support in Synology Calendar. While Calendar supports importing one-time ics files, it does not support subscriptions to external calendars.

CalSub fulfils this missing feature by effectively managing a single calendar for us. This calendar is marked as read only in our client applications and is regularly updated by CalSub.

To run CalSub regularly and automatically, I added an entry to DiskStation Manager’s Task Scheduler:

I could have also used a tool like cron, launchd, or systemd.

Examples

Below are examples of common uses of CalSub.

Remote iCalendar to CalDAV

Read a web hosted ics file at https://example.com/work.ics and import the events in the work calendar on https://example.com/caldav. Authenticate with example.com using a netrc file.

./calsub -ics https://example.com/work.ics -caldav https://example.com/caldav/you -cal work -netrc ~/.netrc

Local File to CalDAV

Read a local work.ics file and import the events in the work calendar on https://example.com/caldav. Authenticate with example.com using a netrc file.

./calsub -ics ~/work.ics -caldav https://example.com/caldav/you -cal work -netrc ~/.netrc

Standard Input (piped) to CalDAV

Read a calendar file from standard input (stdin) and import the events in the work calendar on https://example.com/caldav. Authenticate with example.com using a netrc file.

./calsub -caldav https://example.com/caldav/you -cal work -netrc ~/.netrc

Flags

calsub accepts the following command line flags:

Usage of ./calsub:
  -cal string
        Name of CalDAV calendar to overwrite. (required)
  -caldav string
        URL to CalDAV server. (required)
  -config string
        File path to configuration.
  -dry-run
        Read and triage but make no changes.
  -h    Show this help message and exit. (shorthand)
  -help
        Show this help message and exit.
  -ics string
        Path or URL to iCalendar (.ics) file to import; stdin if empty.
  -l string
        Directory path to licence certificate files (PEM encoded) (shorthand) (default "~/.miln/")
  -legal
        Show legal notices and exit.
  -licence string
        Directory path to licence certificate files (PEM encoded) (default "~/.miln/")
  -netrc string
        Path to netrc file for CalDAV authentication.
  -quiet
        Quieten non-critical output.
  -remove string
        (all|unknown|error) events before writing. (default "error")
  -show-licence
        Show licence details and exit.
  -v    Show version details and exit. (shorthand)
  -version
        Show version details and exit.

Sample Output

calsub prints progress as it runs. Below is a sample output from a run of the tool. The output shows a calendar with a malformed event. calsub encounters a problem writing one of the events and falls back to writing an error event. Where possible, calsub reports problems through events in the destination calendar – where the impact of the error is most important.

2023/10/03 15:46:42 calsub: Reading netrc: "/Users/miln/.netrc"
2023/10/03 15:46:42 calsub: Reading source calendar (ics): "https://example.com/ical/"
2023/10/03 15:46:42 calsub: …read events: 40
2023/10/03 15:46:42 calsub: Connecting to destination CalDAV server: "https://localhost/caldav/miln"
2023/10/03 15:46:42 calsub: …finding user
2023/10/03 15:46:43 calsub: …finding home: "/caldav.php/miln/"
2023/10/03 15:46:43 calsub: …finding calendars: "/caldav.php/miln/"
2023/10/03 15:46:43 calsub: …finding named calendar: "Work"
2023/10/03 15:46:43 calsub: …found calendar: "Work"
2023/10/03 15:46:43 calsub: …getting existing events: "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/"
2023/10/03 15:46:43 calsub: …existing events: 49
2023/10/03 15:46:43 calsub: …triaged events: 1 to add, 10 to remove, 39 unchanged
2023/10/03 15:46:43 calsub: …removing events: 10 to remove from "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/"
2023/10/03 15:46:43 calsub: …removing: 1 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-03T15:30:02+02:00-10981-0-error"
2023/10/03 15:46:44 calsub: …removing: 2 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-5"
2023/10/03 15:46:44 calsub: …removing: 3 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T22:30:01+02:00-8945-0"
2023/10/03 15:46:44 calsub: …removing: 4 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-1"
2023/10/03 15:46:44 calsub: …removing: 5 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-6"
2023/10/03 15:46:45 calsub: …removing: 6 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-2"
2023/10/03 15:46:45 calsub: …removing: 7 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-4"
2023/10/03 15:46:45 calsub: …removing: 8 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-3"
2023/10/03 15:46:45 calsub: …removing: 9 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-20"
2023/10/03 15:46:46 calsub: …removing: 10 of 10 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-02T17:03:46+02:00-7710-0"
2023/10/03 15:46:46 calsub: …writing events: 1 to write to "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/"
2023/10/03 15:46:47 calsub: …wrote error event: 1 at "/caldav.php/miln/DE590F3B-1234-459E-EFEF-3A2655BD558F/eu.miln.calsub-2023-10-03T15:46:42+02:00-5596-0-error"
2023/10/03 15:46:47 calsub: Finished

Verbose progress helps explain what is happening and why but you can always silence it using the -quiet flag.

Download

Latest downloads for CalSub.

Legal

Legal notices associated with CalSub.