Provided by: vdirsyncer_0.20.0-1_all bug

NAME

       vdirsyncer - vdirsyncer Documentation

       • Documentation <https://vdirsyncer.pimutils.org/en/stable/>

       • Source code <https://github.com/pimutils/vdirsyncer>

       Vdirsyncer  is  a  command-line  tool  for  synchronizing calendars and addressbooks between a variety of
       servers and the local filesystem. The most popular usecase is to synchronize a server with a local folder
       and use a set of other programs <> to  change  the  local  events  and  contacts.   Vdirsyncer  can  then
       synchronize those changes back to the server.

       However,  vdirsyncer  is not limited to synchronizing between clients and servers. It can also be used to
       synchronize calendars and/or addressbooks between two servers directly.

       It aims to be for calendars and contacts what OfflineIMAP <http://offlineimap.org/> is for emails.

WHEN DO I NEED VDIRSYNCER?

   Why not Dropbox + todo.txt?
       Projects like todo.txt <http://todotxt.com/> criticize the complexity of modern  productivity  apps,  and
       that  rightfully.  So  they  set  out to create a new, super-simple, human-readable format, such that vim
       suffices for viewing the raw data. However, when they're faced with the question how to synchronize  that
       data across multiple devices, they seemed to have reached the dead end with their novel idea: "Let's just
       use Dropbox".

       What  does file sync software do if both files have changed since the last sync?  The answer is to ignore
       the question, just sync as often as possible, and hope for the best.  Because  if  it  comes  to  a  sync
       conflict,  most  sync  services  are  not  daring  to merge files, and create two copies on each computer
       instead.  Merging the two task lists is left to the user.

       A better idea would've been to use git to synchronize the todo.txt  file,  which  is  at  least  able  to
       resolve some basic conflicts.

   Why not file sync (Dropbox, git, ...) + vdir?
       Since  vdirs  <>  are  just a bunch of files, it is obvious to try file synchronization for synchronizing
       your data between multiple computers, such as:

       • Syncthing <https://syncthing.net/>

       • Dropbox <https://dropbox.com/> or one of the gajillion services like it

       • unison <https://www.cis.upenn.edu/~bcpierce/unison/>

       • Just git with a sshd.

       The disadvantages of those solutions largely depend on the exact file sync program chosen:

       • Like with todo.txt, Dropbox and friends are obviously agnostic/unaware of the  files'  contents.  If  a
         file has changed on both sides, Dropbox just copies both versions to both sides.

         This  is  a  good  idea if the user is directly interfacing with the file system and is able to resolve
         conflicts themselves.  Here it might lead to erroneous behavior with e.g. khal, since there are now two
         events with the same UID.

         This point doesn't apply to git: It has very good merging capabilities,  better  than  what  vdirsyncer
         currently has.

       • Such  a  setup  doesn't  work at all with smartphones. Vdirsyncer, on the other hand, synchronizes with
         CardDAV/CalDAV servers, which can be accessed with e.g. DAVx⁵ <https://www.davx5.com/>  or  other  apps
         bundled with smartphones.

INSTALLATION

   OS/distro packages
       The following packages are community-contributed and were up-to-date at the time of writing:

       • Arch Linux <https://archlinux.org/packages/extra/any/vdirsyncer/>

       • Ubuntu  and  Debian,  x86_64-only <https://packagecloud.io/pimutils/vdirsyncer> (packages also exist in
         the official repositories but may be out of date)

       • GNU Guix <https://packages.guix.gnu.org/packages/vdirsyncer/>

       • macOS (homebrew) <https://formulae.brew.sh/formula/vdirsyncer>

       • NetBSD <https://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/time/py-vdirsyncer/index.html>

       • OpenBSD <http://ports.su/productivity/vdirsyncer>

       • Slackware (SlackBuild at Slackbuilds.org) <https://slackbuilds.org/repository/15.0/network/vdirsyncer/>

       We only support the latest version of vdirsyncer, which is at the time of this writing 0.20.0. Please  do
       not file bugs if you use an older version.

       Some  distributions have multiple release channels. Debian and Fedora for example have a "stable" release
       channel that ships an older version of vdirsyncer. Those versions aren't supported either.

       If there is no suitable package for your distribution, you'll need to install vdirsyncer manually.  There
       is an easy command to copy-and-paste for this as well, but you should be aware of its consequences.

   Manual installation
       If your distribution doesn't provide a package for vdirsyncer, you still can use Python's package manager
       "pip". First, you'll have to check that the following things are installed:

       • Python 3.8 to 3.13 and pip.

       • libxml and libxsltzlib

       • Linux  or  macOS.  Windows  is  not  supported, see issue #535 <https://github.com/pimutils/vdirsyncer/
         issues/535>.

       On Linux systems, using the distro's package manager is the best way  to  do  this,  for  example,  using
       Ubuntu:

          sudo apt-get install libxml2 libxslt1.1 zlib1g python3

       Then you have several options. The following text applies for most Python software by the way.

   pipx: The clean, easy way
       pipx  <https://github.com/pipxproject/pipx>  is  a  new  package  manager  for Python-based software that
       automatically sets up a virtual environment for each program it installs. Please note that installing via
       pipx will not include manual pages nor systemd services.

       pipx will install vdirsyncer into ~/.local/pipx/venvs/vdirsyncer

       Assuming that pipx is installed, vdirsyncer can be installed with:

          pipx install vdirsyncer

       It can later be updated to the latest version with:

          pipx upgrade vdirsyncer

       And can be uninstalled with:

          pipx uninstall vdirsyncer

       This last command will remove vdirsyncer and any dependencies installed into the above location.

   The dirty, easy way
       If pipx is not available on your distribution, the easiest way to install vdirsyncer at this point  would
       be to run:

          pip install --ignore-installed vdirsyncer

       • --ignore-installed  is  to  work  around  Debian's  potentially  broken  packages (see Requests-related
         ImportErrors <#debian-urllib3>).

       This method has a major flaw though: Pip doesn't keep track of the files it installs. Vdirsyncer's  files
       would  be  located  somewhere  in  ~/.local/lib/python*,  but you can't possibly know which packages were
       installed as dependencies of vdirsyncer and which ones were not, should you decide to  uninstall  it.  In
       other words, using pip that way would pollute your home directory.

   The clean, hard way
       There  is  a  way  to install Python software without scattering stuff across your filesystem: virtualenv
       <https://virtualenv.readthedocs.io/>. There are a lot of  resources  on  how  to  use  it,  the  simplest
       possible way would look something like:

          virtualenv ~/vdirsyncer_env
          ~/vdirsyncer_env/bin/pip install vdirsyncer
          alias vdirsyncer="~/vdirsyncer_env/bin/vdirsyncer"

       You'll have to put the last line into your .bashrc or .bash_profile.

       This method has two advantages:

       • It  separately  installs  all  Python  packages  into  ~/vdirsyncer_env/, without relying on the system
         packages. This works around OS- or distro-specific issues.

       • You can delete ~/vdirsyncer_env/ to uninstall vdirsyncer entirely.

TUTORIAL

       Before starting, consider if you actually need vdirsyncer <>. There are better alternatives available for
       particular usecases.

   Installation
       See Installation <#installation>.

   Configuration
       Note:

          • The  config.example  from  the  repository  <https://github.com/pimutils/vdirsyncer/blob/main/config
            .example> contains a very terse version of this.

          • In  this  example  we set up contacts synchronization, but calendar sync works almost the same. Just
            swap type = "carddav" for type = "caldav" and fileext = ".vcf" for fileext = ".ics".

          • Take a look at the Known Problems <> page if anything doesn't work like planned.

       By default, vdirsyncer looks for its configuration file in the following locations:

       • The file pointed to by the VDIRSYNCER_CONFIG environment variable.

       • ~/.vdirsyncer/config.

       • $XDG_CONFIG_HOME/vdirsyncer/config, which is normally ~/.config/vdirsyncer/config. See the  XDG-Basedir
         <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables> specification.

       The  config file should start with a general section <#general-config>, where the only required parameter
       is status_path. The following is a minimal example:

          [general]
          status_path = "~/.vdirsyncer/status/"

       After the general section, an arbitrary amount of pair and storage sections might come.

       In vdirsyncer, synchronization is always done between two storages. Such storages are defined in  storage
       sections  <#storage-config>,  and  which  pairs of storages should actually be synchronized is defined in
       pair section <#pair-config>.   This  format  is  copied  from  OfflineIMAP,  where  storages  are  called
       repositories and pairs are called accounts.

       The following example synchronizes ownCloud's addressbooks to ~/.contacts/:

          [pair my_contacts]
          a = "my_contacts_local"
          b = "my_contacts_remote"
          collections = ["from a", "from b"]

          [storage my_contacts_local]
          type = "filesystem"
          path = "~/.contacts/"
          fileext = ".vcf"

          [storage my_contacts_remote]
          type = "carddav"

          # We can simplify this URL here as well. In theory it shouldn't matter.
          url = "https://owncloud.example.com/remote.php/carddav/"
          username = "bob"
          password = "asdf"

       Note:
          Configuration for other servers can be found at Servers <#supported-servers>.

       After  running  vdirsyncer  discover  and  vdirsyncer sync, ~/.contacts/ will contain subfolders for each
       addressbook, which in turn will contain a bunch of .vcf files which all contain a contact in VCARD format
       each.  You can modify their contents, add new ones  and  delete  some  [1],  and  your  changes  will  be
       synchronized to the CalDAV server after you run vdirsyncer sync again. For further reference, it uses the
       storages filesystem <#storage-filesystem> and carddav <#storage-carddav>.

       However,  if  new  collections  are  created on the server, it will not automatically start synchronizing
       those [2]. You need to run vdirsyncer discover again to re-fetch this list instead.

       [1]  You'll want to use a helper program for this <>.

       [2]  Because collections are added rarely, and checking for this case before every synchronization  isn't
            worth the overhead.

   More Configuration
   Conflict resolution
       What  if  the  same item is changed on both sides? What should vdirsyncer do? Three options are currently
       provided:

       1. vdirsyncer displays an error message (the default);

       2. vdirsyncer chooses one alternative version over the other;

       3. vdirsyncer starts a command of your choice that is supposed to merge the two alternative versions.

       Options 2 and 3 require adding a "conflict_resolution" parameter to the pair section. Option  2  requires
       giving either "a wins" or "b wins" as value to the parameter:

          [pair my_contacts]
          ...
          conflict_resolution = "b wins"

       Earlier we wrote that b = "my_contacts_remote", so when vdirsyncer encounters the situation where an item
       changed on both sides, it will simply overwrite the local item with the one from the server.

       Option  3  requires  specifying  as  value  of "conflict_resolution" an array starting with "command" and
       containing paths and arguments to a command. For example:

          [pair my_contacts]
          ...
          conflict_resolution = ["command", "vimdiff"]

       In this example, vimdiff <a> <b> will be called with <a> and <b> being two temporary files containing the
       conflicting files. The files need to be exactly the same when the command returns. More arguments can  be
       passed to the command by adding more elements to the array.

       See Pair Section <#pair-config> for the reference documentation.

   Metadata synchronization
       Besides   items,   vdirsyncer  can  also  synchronize  metadata  like  the  addressbook's  or  calendar's
       "human-friendly" name (internally called "displayname") or the color associated with a calendar. For  the
       purpose of explaining this feature, let's switch to a different base example. This time we'll synchronize
       calendars:

          [pair my_calendars]
          a = "my_calendars_local"
          b = "my_calendars_remote"
          collections = ["from a", "from b"]
          metadata = ["color"]

          [storage my_calendars_local]
          type = "filesystem"
          path = "~/.calendars/"
          fileext = ".ics"

          [storage my_calendars_remote]
          type = "caldav"

          url = "https://owncloud.example.com/remote.php/caldav/"
          username = "bob"
          password = "asdf"

       Run  vdirsyncer  discover  for  discovery.  Then you can use vdirsyncer metasync to synchronize the color
       property between your local calendars in ~/.calendars/ and your  ownCloud.  Locally  the  color  is  just
       represented as a file called color within the calendar folder.

   More information about collections
       "Collection"  is a collective term for addressbooks and calendars. A Cardav or Caldav server can contains
       several "collections" which correspond to several addressbooks or calendar.

       Each collection from a storage has a "collection name", a unique identifier for each collection.  In  the
       case  of  filesystem <#storage-filesystem>-storage, this is the name of the directory that represents the
       collection, in the case of the DAV-storages this is the last segment of the URL. We use  this  identifier
       in the collections parameter in the pair-section.

       This  identifier  doesn't  change  even if you rename your calendar in whatever UI you have, because that
       only changes the so-called "displayname" property [3].  On some servers (iCloud, Google) this  identifier
       is randomly generated and has no correlation with the displayname you chose.

       [3]  Which you can also synchronize with metasync using metadata = ["displayname"].

            There are three collection names that have a special meaning:

       • "from  a",  "from  b":  A  placeholder  for  all collections that can be found on side A/B when running
         vdirsyncer discover.

       • null: The parameters give to the storage are exact and require no discovery.

       The last one requires a bit more explanation.  Assume this config which synchronizes two  directories  of
       addressbooks:

          [pair foobar]
          a = "foo"
          b = "bar"
          collections = ["from a", "from b"]

          [storage foo]
          type = "filesystem"
          fileext = ".vcf"
          path = "./contacts_foo/"

          [storage bar]
          type = "filesystem"
          fileext = ".vcf"
          path = "./contacts_bar/"

       As  we  saw  previously  this  will  synchronize  all collections in ./contacts_foo/ with each same-named
       collection in ./contacts_bar/. If there's a collection that  exists  on  one  side  but  not  the  other,
       vdirsyncer will ask whether to create that folder on the other side.

       If  we  set collections = null, ./contacts_foo/ and ./contacts_bar/ are no longer treated as folders with
       collections, but as collections themselves. This means  that  ./contacts_foo/  and  ./contacts_bar/  will
       contain .vcf-files, not subfolders that contain .vcf-files.

       This  is useful in situations where listing all collections fails because your DAV-server doesn't support
       it, for example. In this case, you  can  set  url  of  your  carddav  <#storage-carddav>-  or  caldav  <#
       storage-caldav>-storage to a URL that points to your CalDAV/CardDAV collection directly.

       Note   that   not   all   storages   support   the   null-collection,   for  example  google_contacts  <#
       storage-google_contacts> and google_calendar <#storage-google_calendar> don't.

   Advanced collection configuration (server-to-server sync)
       The examples above are good enough if you want to synchronize a remote server to a previously empty disk.
       However, even more trickery is required when you have two servers with already existing collections which
       you want to synchronize.

       The core problem in this situation is that vdirsyncer pairs collections by  collection  name  by  default
       (see definition in previous section, basically a foldername or a remote UUID). When you have two servers,
       those  collection  names  may  not  line up as nicely. Suppose you created two calendars "Test", one on a
       NextCloud server and one on iCloud, using their respective web interfaces. The URLs look  something  like
       this:

          NextCloud: https://example.com/remote.php/dav/calendars/user/test/
          iCloud:    https://p-XX.caldav.icloud.com/YYY/calendars/3b4c9995-5c67-4021-9fa0-be4633623e1c

       Those    are    two   DAV   calendar   collections.   Their   collection   names   will   be   test   and
       3b4c9995-5c67-4021-9fa0-be4633623e1c respectively, so you don't have a single name you can  address  them
       both with. You will need to manually "pair" (no pun intended) those collections up like this:

          [pair doublecloud]
          a = "my_nextcloud"
          b = "my_icloud"
          collections = [["mytest", "test", "3b4c9995-5c67-4021-9fa0-be4633623e1c"]]

       mytest  gives  that  combination of calendars a nice name you can use when talking about it, so you would
       use vdirsyncer sync doublecloud/mytest to say: "Only synchronize these two storages,  nothing  else  that
       may be configured".

       Note:
          Why not use displaynames?

          You  may  wonder  why vdirsyncer just couldn't figure this out by itself. After all, you did name both
          collections "Test" (which is called "the displayname"), so why not pair collections by that value?

          There are a few problems with this idea:

          • Two calendars may have the same exact displayname.

          • A calendar may not have a (non-empty) displayname.

          • The displayname might change. Either you rename the calendar, or the calendar renames itself because
            you change a language setting.

          In the end, that property was never designed to be parsed by machines.

SSL AND CERTIFICATE VALIDATION

       All SSL configuration is done per-storage.

   Pinning by fingerprint
       To pin the certificate by fingerprint:

          [storage foo]
          type = "caldav"
          ...
          verify_fingerprint = "6D:83:EA:32:6C:39:BA:08:ED:EB:C9:BC:BE:12:BB:BF:0F:D9:83:00:CC:89:7E:C7:32:05:94:96:CA:C5:59:5E"

       SHA256-Fingerprints must be used, MD5 and SHA-1  are  insecure  and  not  supported.   CA  validation  is
       disabled when pinning a fingerprint.

       You can use the following command for obtaining a SHA256 fingerprint:

          echo -n | openssl s_client -connect unterwaditzer.net:443 | openssl x509 -noout -fingerprint -sha256

       However,  please  consider  using Let's Encrypt <https://letsencrypt.org/> such that you can forget about
       all of that. It is easier to deploy a free certificate from them than configuring all of your clients  to
       accept the self-signed certificate.

   Custom root CAs
       To point vdirsyncer to a custom set of root CAs:

          [storage foo]
          type = "caldav"
          ...
          verify = "/path/to/cert.pem"

       Vdirsyncer  uses  the  aiohttp  <https://docs.aiohttp.org/en/stable/index.html>  library,  which uses the
       default
       `ssl.SSLContext
       https://docs.python.org/3/library/ssl.html#ssl.SSLContext`_
        by default.

       There are cases where certificate validation fails even though you can access  the  server  fine  through
       e.g.  your  browser. This usually indicates that your installation of python or the aiohttp or library is
       somehow broken. In such cases, it makes sense to explicitly set verify  or  verify_fingerprint  as  shown
       above.

   Client Certificates
       Client  certificates may be specified with the auth_cert parameter. If the key and certificate are stored
       in the same file, it may be a string:

          [storage foo]
          type = "caldav"
          ...
          auth_cert = "/path/to/certificate.pem"

       If the key and certificate are separate, a list may be used:

          [storage foo]
          type = "caldav"
          ...
          auth_cert = ["/path/to/certificate.crt", "/path/to/key.key"]

STORING PASSWORDS

       Changed in version 0.7.0: Password configuration got completely overhauled.

       Vdirsyncer can fetch passwords from several sources other than the config file.

   Command
       Say you have the following configuration:

          [storage foo]
          type = "caldav"
          url = ...
          username = "foo"
          password = "bar"

       But it bugs you that the password is stored in cleartext in the config file.  You can do this:

          [storage foo]
          type = "caldav"
          url = ...
          username = "foo"
          password.fetch = ["command", "~/get-password.sh", "more", "args"]

       You can fetch the username as well:

          [storage foo]
          type = "caldav"
          url = ...
          username.fetch = ["command", "~/get-username.sh"]
          password.fetch = ["command", "~/get-password.sh"]

       Or really any kind of parameter in a storage section.

       You can also pass the command as a string to be executed in a shell:

          [storage foo]
          ...
          password.fetch = ["shell", "~/.local/bin/get-my-password | head -n1"]

       With pass <https://www.passwordstore.org/> for example, you might find yourself  writing  something  like
       this in your configuration file:

          password.fetch = ["command", "pass", "caldav"]

   Accessing the system keyring
       As shown above, you can use the command strategy to fetch your credentials from arbitrary sources. A very
       common usecase is to fetch your password from the system keyring.

       The  keyring  <https://github.com/jaraco/keyring/>  Python  package  contains  a command-line utility for
       fetching passwords from the OS's password store. Installation:

          pip install keyring

       Basic usage:

          password.fetch = ["command", "keyring", "get", "example.com", "foouser"]

   Password Prompt
       You can also simply prompt for the password:

          [storage foo]
          type = "caldav"
          username = "myusername"
          password.fetch = ["prompt", "Password for CalDAV"]

   Environment variable
       To read the password from an environment variable:

          [storage foo]
          type = "caldav"
          username = "myusername"
          password.fetch = ["command", "printenv", "DAV_PW"]

       This is especially handy if you use the same password multiple times (say, for a  CardDAV  and  a  CalDAV
       storage).  On bash, you can read and export the password without printing:

          read -s DAV_PW "DAV Password: " && export DAV_PW

SYNCING WITH READ-ONLY STORAGES

       If  you  want  to subscribe to a public, read-only WebCAL <https://en.wikipedia.org/wiki/Webcal>-calendar
       but neither your server nor your calendar apps support that (or support  it  insufficiently),  vdirsyncer
       can be used to synchronize such a public calendar A with a new calendar B of your own and keep B updated.

   Step 1: Create the target calendar
       First you need to create the calendar you want to sync the WebCAL-calendar with. Most servers offer a web
       interface  for  this.  You  then  need to note the CalDAV URL of your calendar. Note that this URL should
       directly point to the calendar you just created, which means  you  would  have  one  such  URL  for  each
       calendar you have.

   Step 2: Creating the config
       Paste this into your vdirsyncer config:

          [pair holidays]
          a = "holidays_public"
          b = "holidays_private"
          collections = null

          [storage holidays_public]
          type = "http"
          # The URL to your iCalendar file.
          url = "..."

          [storage holidays_private]
          type = "caldav"
          # The direct URL to your calendar.
          url = "..."
          # The credentials to your CalDAV server
          username = "..."
          password = "..."

       Then  run vdirsyncer discover holidays and vdirsyncer sync holidays, and your previously created calendar
       should be filled with events.

   Step 3: The partial_sync parameter
       Added in version 0.14.

       You may get into a situation where you want to hide or modify some events from your holidays calendar. If
       you try to do that at this point, you'll notice that vdirsyncer will revert any changes you've made after
       a few times of running sync. This is because vdirsyncer wants to keep everything in sync,  and  it  can't
       synchronize changes to the public holidays-calendar because it doesn't have the rights to do so.

       For such purposes you can set the partial_sync parameter to ignore:

          [pair holidays]
          a = "holidays_public"
          b = "holidays_private"
          collections = null
          partial_sync = ignore

       See the config docs <#partial-sync-def> for more information.

FULL CONFIGURATION MANUAL

       Vdirsyncer  uses an ini-like format for storing its configuration. All values are JSON, invalid JSON will
       get interpreted as string:

          x = "foo"  # String
          x = foo  # Shorthand for same string

          x = 42  # Integer

          x = ["a", "b", "c"]  # List of strings

          x = true  # Boolean
          x = false

          x = null  # Also known as None

   General Section
          [general]
          status_path = ...

       • status_path: A directory where vdirsyncer will store some additional data for the next sync.

         The data is needed to determine whether a new item means it has been added on one side  or  deleted  on
         the other. Relative paths will be interpreted as relative to the configuration file's directory.

         See  A  simple  synchronization algorithm <https://unterwaditzer.net/2016/sync-algorithm.html> for what
         exactly is in there.

   Pair Section
          [pair pair_name]
          a = ...
          b = ...
          #collections = null
          #conflict_resolution = null

       • Pair names can consist of any alphanumeric characters and the underscore.

       • a and b reference the storages to sync by their names.

       • collections: A list of collections to synchronize when vdirsyncer  sync  is  executed.  See  also  More
         information about collections <#collections-tutorial>.

         The  special  values "from a" and "from b", tell vdirsyncer to try autodiscovery on a specific storage.
         It means all the collections on side A / side B.

         If the collection you want to sync doesn't have the same name on each side, you may also use a value of
         the form ["config_name", "name_a", "name_b"].  This will synchronize the collection name_a  on  side  A
         with  the collection name_b on side B. The config_name will be used for representation in CLI arguments
         and logging.

         Examples:

         • collections = ["from b", "foo", "bar"] makes vdirsyncer synchronize all the collections from side  B,
           and also the collections named "foo" and "bar".

         • collections  =  ["from  b", "from a"] makes vdirsyncer synchronize all existing collections on either
           side.

         • collections = [["bar", "bar_a", "bar_b"], "foo"] makes vdirsyncer synchronize bar_a from side A  with
           bar_b from side B, and also synchronize foo on both sides with each other.

       • conflict_resolution: Optional, define how conflicts should be handled.  A conflict occurs when one item
         (event,   task)  changed  on  both  sides  since  the  last  sync.  See  also  Conflict  resolution  <#
         conflict-resolution-tutorial>.

         Valid values are:

         • null, where an error is shown and no changes are done.

         • "a wins" and "b wins", where the whole item is taken from one side.

         • ["command", "vimdiff"]: vimdiff <a> <b> will be called where <a> and <b>  are  temporary  files  that
           contain  the  item  of each side respectively. The files need to be exactly the same when the command
           returns.

           • vimdiff can be replaced with any  other  command.  For  example,  in  POSIX  ["command",  "cp"]  is
             equivalent to "a wins".

           • Additional  list  items  will  be  forwarded  as  arguments.  For  example,  ["command", "vimdiff",
             "--noplugin"] runs vimdiff --noplugin.

         Vdirsyncer never attempts to "automatically merge" the two items.

       • partial_sync: Assume A is read-only, B not. If you change items on B, vdirsyncer can't sync the changes
         to A. What should happen instead?

         • error: An error is shown.

         • ignore: The change is ignored. However: Events deleted in B still reappear if they're updated in A.

         • revert (default): The change is reverted on next sync.

         See also Syncing with read-only storages <#partial-sync-tutorial>.

       • metadata: Metadata keys that should be synchronized when vdirsyncer metasync is executed. Example:

            metadata = ["color", "displayname", "description", "order"]

         This synchronizes the following properties:

         • color: http://apple.com/ns/ical/:calendar-color

         • displayname: DAV:displayname

         • description: CalDAV:calendar-description and CardDAV:addressbook-description

         • order: http://apple.com/ns/ical/:calendar-order

         The conflict_resolution parameter applies for these properties too.

   Storage Section
          [storage storage_name]
          type = ...

       • Storage names can consist of any alphanumeric characters and the underscore.

       • type defines which kind of storage is defined. See Supported Storages.

       • read_only defines whether the storage should be regarded as a read-only storage. The value  true  means
         synchronization  will  discard any changes made to the other side. The value false implies normal 2-way
         synchronization.

       • Any further parameters are passed on to the storage class.

   Supported Storages
   CalDAV and CardDAV
       Note:
          Please also see Servers <#supported-servers>, as some servers may not work well.

       caldav CalDAV.

                 [storage example_for_caldav]
                 type = "caldav"
                 #start_date = null
                 #end_date = null
                 #item_types = []
                 url = "..."
                 #username = ""
                 #password = ""
                 #verify = /path/to/custom_ca.pem
                 #auth = null
                 #useragent = "vdirsyncer/0.16.4"
                 #verify_fingerprint = null
                 #auth_cert = null

              You can set a timerange to synchronize with the parameters start_date and end_date.  Inside  those
              parameters,  you  can  use  any  Python expression to return a valid datetime.datetime object. For
              example, the following would synchronize the timerange from one year in the past to  one  year  in
              the future:

                 start_date = "datetime.now() - timedelta(days=365)"
                 end_date = "datetime.now() + timedelta(days=365)"

              Either both or none have to be specified. The default is to synchronize everything.

              You  can set item_types to restrict the kind of items you want to synchronize. For example, if you
              want to only synchronize events (but don't download any tasks from the server), set  item_types  =
              ["VEVENT"].  If  you  want  to  synchronize  events and tasks, but have some VJOURNAL items on the
              server you don't want to synchronize, use item_types = ["VEVENT", "VTODO"].

              Parametersstart_date -- Start date of timerange to show, default -inf.

                     • end_date -- End date of timerange to show, default +inf.

                     • item_types -- Kind of items to show. The default, the empty list, is to  show  all.  This
                       depends on particular features on the server, the results are not validated.

                     • url -- Base URL or an URL to a calendar.

                     • username -- Username for authentication.

                     • password -- Password for authentication.

                     • verify -- Optional. Local path to a self-signed SSL certificate.  See SSL and certificate
                       validation <#ssl-tutorial> for more information.

                     • verify_fingerprint  --  Optional.  SHA256 fingerprint of the expected server certificate.
                       See SSL and certificate validation <#ssl-tutorial> for more information.

                     • auth -- Optional. Either basic, digest or guess. The default is  preemptive  Basic  auth,
                       sending  credentials  even  if  server didn't request them. This saves from an additional
                       roundtrip per request. Consider setting guess if this causes issues with your server.

                     • auth_cert -- Optional. Either a path to a certificate with a client certificate  and  the
                       key or a list of paths to the files with them.

                     • useragent -- Default vdirsyncer.

       carddav
              CardDAV.

                 [storage example_for_carddav]
                 type = "carddav"
                 url = "..."
                 #username = ""
                 #password = ""
                 #verify = /path/to/custom_ca.pem
                 #auth = null
                 #useragent = "vdirsyncer/0.16.4"
                 #verify_fingerprint = null
                 #auth_cert = null
                 #use_vcard_4 = false

              Parametersurl -- Base URL or an URL to an addressbook.

                     • username -- Username for authentication.

                     • password -- Password for authentication.

                     • verify -- Optional. Local path to a self-signed SSL certificate.  See SSL and certificate
                       validation <#ssl-tutorial> for more information.

                     • verify_fingerprint  --  Optional.  SHA256 fingerprint of the expected server certificate.
                       See SSL and certificate validation <#ssl-tutorial> for more information.

                     • auth -- Optional. Either basic, digest or guess. The default is  preemptive  Basic  auth,
                       sending  credentials  even  if  server didn't request them. This saves from an additional
                       roundtrip per request. Consider setting guess if this causes issues with your server.

                     • auth_cert -- Optional. Either a path to a certificate with a client certificate  and  the
                       key or a list of paths to the files with them.

                     • useragent -- Default vdirsyncer.

                     • use_vcard_4 -- Whether the server use vCard 4.0.

   Google
       Vdirsyncer  supports  synchronization  with  Google  calendars  with the restriction that VTODO files are
       rejected by the server.

       Synchronization with Google contacts is less reliable due to negligence of Google's CardDAV API. Google's
       CardDAV implementation is allegedly a disaster in terms of data safety.  See  this  blog  post  <https://
       evertpot.com/google-carddav-issues/> for the details.  Always back up your data.

       Another caveat is that Google group labels are not synced with vCard's CATEGORIES <https://www.rfc-editor
       .org/rfc/rfc6350#section-6.7.1>  property  (also  see issue #814 <https://github.com/pimutils/vdirsyncer/
       issues/814> and upstream issue #36761530 <https://issuetracker.google.com/issues/36761530> for reference)
       and the BDAY <https://www.rfc-editor.org/rfc/rfc6350#section-6.2.5> property  is  not  synced  when  only
       partial date information is present (e.g. the year is missing).

       At first run you will be asked to authorize application for Google account access.

       To use this storage type, you need to install some additional dependencies:

          pip install vdirsyncer[google]

       Furthermore  you  need  to  register  vdirsyncer  as  an  application  yourself  to  obtain client_id and
       client_secret, as it is against Google's Terms of Service to  hardcode  those  into  opensource  software
       [googleterms] <#googleterms>:

       1. Go to the Google API Manager <https://console.developers.google.com>

       2. Create a new project under any name.

       2. Within that project, enable the "CalDAV" and "CardDAV" APIs (not the Calendar and Contacts APIs, those
          are different and won't work). There should be a search box where you can just enter those terms.

       3. In the sidebar, select "Credentials", then "Create Credentials" and create a new "OAuth Client ID".

          You'll be prompted to create a OAuth consent screen first. Fill out that form however you like.

          After  setting  up  the  consent  screen,  finish  creating  the  new  "OAuth  Client ID'. The correct
          application type is "Desktop application".

       4. Finally you should have a Client ID and a Client secret. Provide these in your storage config.

       The  token_file  parameter  should  be  a  path  to   a   file   where   vdirsyncer   can   later   store
       authentication-related data. You do not need to create the file itself or write anything to it.

       [googleterms]
            See ToS <https://developers.google.com/terms/?hl=th>, section "Confidential Matters".

            Note:
          You  need  to  configure  which  calendars Google should offer vdirsyncer using a secret settings page
          <https://calendar.google.com/calendar/syncselect>.

       google_calendar
              Google calendar.

                 [storage example_for_google_calendar]
                 type = "google_calendar"
                 token_file = "..."
                 client_id = "..."
                 client_secret = "..."
                 #start_date = null
                 #end_date = null
                 #item_types = []

              Please refer to caldav regarding the item_types and timerange parameters.

              Parameterstoken_file -- A filepath where access tokens are stored.

                     • client_id/client_secret -- OAuth credentials, obtained from the Google API Manager.

       google_contacts
              Google contacts.

                 [storage example_for_google_contacts]
                 type = "google_contacts"
                 token_file = "..."
                 client_id = "..."
                 client_secret = "..."

              Parameterstoken_file -- A filepath where access tokens are stored.

                     • client_id/client_secret -- OAuth credentials, obtained from the Google API Manager.

       The current flow is not ideal, but Google  has  deprecated  the  previous  APIs  used  for  this  without
       providing  a suitable replacement. See issue #975 <https://github.com/pimutils/vdirsyncer/issues/975> for
       discussion on the topic.

   Local
       filesystem
              Saves each item in its own file, given a directory.

                 [storage example_for_filesystem]
                 type = "filesystem"
                 path = "..."
                 fileext = "..."
                 #encoding = "utf-8"
                 #post_hook = null
                 #pre_deletion_hook = null
                 #fileignoreext = ".tmp"

              Can be used with khal <http://lostpackets.de/khal/>. See The Vdir Storage Format  <>  for  a  more
              formal description of the format.

              Directories with a leading dot are ignored to make usage of e.g. version control easier.

              Parameterspath  --  Absolute  path  to  a  vdir/collection. If this is used in combination with the
                       collections parameter in a pair-section, this  should  point  to  a  directory  of  vdirs
                       instead.

                     • fileext -- The file extension to use (e.g. .txt). Contained in the href, so if you change
                       the  file  extension  after  a  sync,  this will trigger a re-download of everything (but
                       should not cause data-loss of any kind). To be compatible with the vset format  you  have
                       to  either  use  .vcf  or  .ics. Note that metasync won't work if you use an empty string
                       here.

                     • encoding -- File encoding for items, both content and filename.

                     • post_hook -- A command to call for each item creation and modification. The command  will
                       be called with the path of the new/updated file.

                     • pre_deletion_hook  --  A  command  to  call  for each item deletion.  The command will be
                       called with the path of the deleted file.

                     • fileeignoreext -- The file extention to ignore. It is only useful if fileext  is  set  to
                       the empty string. The default is .tmp.

       singlefile
              Save data in single local .vcf or .ics file.

              The storage basically guesses how items should be joined in the file.

              Added in version 0.1.6.

              Note:
                 This storage is very slow, and that is unlikely to change. You should consider using filesystem
                 if it fits your usecase.

              Parameterspath  --  The filepath to the file to be written to. If collections are used, this should
                       contain %s as a placeholder for the collection name.

                     • encoding -- Which encoding the file should use. Defaults to UTF-8.

              Example for syncing with caldav:

                 [pair my_calendar]
                 a = my_calendar_local
                 b = my_calendar_remote
                 collections = ["from a", "from b"]

                 [storage my_calendar_local]
                 type = "singlefile"
                 path = ~/.calendars/%s.ics

                 [storage my_calendar_remote]
                 type = "caldav"
                 url = https://caldav.example.org/
                 #username =
                 #password =

              Example for syncing with caldav using a null collection:

                 [pair my_calendar]
                 a = my_calendar_local
                 b = my_calendar_remote

                 [storage my_calendar_local]
                 type = "singlefile"
                 path = ~/my_calendar.ics

                 [storage my_calendar_remote]
                 type = "caldav"
                 url = https://caldav.example.org/username/my_calendar/
                 #username =
                 #password =

   Read-only storages
       These storages don't support writing of their items, consequently read_only is set to  true  by  default.
       Changing read_only to false on them leads to an error.

       http   Use  a  simple  .ics  file (or similar) from the web.  webcal://-calendars are supposed to be used
              with this, but you have to replace webcal:// with http://, or better, https://.

                 [pair holidays]
                 a = holidays_local
                 b = holidays_remote
                 collections = null

                 [storage holidays_local]
                 type = "filesystem"
                 path = ~/.config/vdir/calendars/holidays/
                 fileext = .ics

                 [storage holidays_remote]
                 type = "http"
                 url = https://example.com/holidays_from_hicksville.ics
                 #filter_hook = null

              Too many WebCAL providers generate UIDs of all VEVENT-components on-the-fly, i.e. all UIDs  change
              every  time  the calendar is downloaded.  This leads many synchronization programs to believe that
              all events have been deleted and new ones created, and accordingly causes  a  lot  of  unnecessary
              uploads  and  deletions on the other side. Vdirsyncer completely ignores UIDs coming from http and
              will replace them with a hash of the normalized item content.

              Parametersurl -- URL to the .ics file.

                     • username -- Username for authentication.

                     • password -- Password for authentication.

                     • verify -- Optional. Local path to a self-signed SSL certificate.  See SSL and certificate
                       validation <#ssl-tutorial> for more information.

                     • verify_fingerprint -- Optional. SHA256 fingerprint of the  expected  server  certificate.
                       See SSL and certificate validation <#ssl-tutorial> for more information.

                     • auth  --  Optional.  Either basic, digest or guess. The default is preemptive Basic auth,
                       sending credentials even if server didn't request them. This  saves  from  an  additional
                       roundtrip per request. Consider setting guess if this causes issues with your server.

                     • auth_cert  --  Optional. Either a path to a certificate with a client certificate and the
                       key or a list of paths to the files with them.

                     • useragent -- Default vdirsyncer.

                     • filter_hook -- Optional. A filter command to call for each fetched item,  passed  in  raw
                       form to stdin and returned via stdout.  If nothing is returned by the filter command, the
                       item  is skipped.  This can be used to alter fields as needed when dealing with providers
                       generating malformed events.

OTHER TUTORIALS

       The following section contains tutorials not explicitly about any particular core function of vdirsyncer.
       They usually show how to integrate vdirsyncer with third-party software. Because of that, it may be  that
       the information regarding that other software only applies to specific versions of them.

       Note:
          Please  contribute  <>  your  own  tutorials  too!   Pages  are  often only stubs and are lacking full
          examples.

   Client applications
   Vdirsyncer with Claws Mail
       First of all, Claws-Mail only supports read-only functions for vCards. It can  only  read  contacts,  but
       there's no editor.

   Preparation
       We need to install vdirsyncer, for that look here <>.  Then we need to create some folders:

          mkdir ~/.vdirsyncer
          mkdir ~/.contacts

   Configuration
       Now  we create the configuration for vdirsyncer. Open ~/.vdirsyncer/config with a text editor. The config
       should look like this:

          [general]
          status_path = "~/.vdirsyncer/status/"

          [storage local]
          type = "singlefile"
          path = "~/.contacts/%s.vcf"

          [storage online]
          type = "carddav"
          url = "CARDDAV_LINK"
          username = "USERNAME"
          password = "PASSWORD"
          read_only = true

          [pair contacts]
          a = "local"
          b = "online"
          collections = ["from a", "from b"]
          conflict_resolution = "b wins"

       • In the general section, we define the status folder path,  for  discovered  collections  and  generally
         stuff that needs to persist between syncs.

       • In  the  local section we define that all contacts should be sync in a single file and the path for the
         contacts.

       • In the online section you must change the url, username and password to your setup.  We  also  set  the
         storage  to  read-only  such that no changes get synchronized back. Claws-Mail should not be able to do
         any changes anyway, but this is one extra safety step in case files get corrupted or vdirsyncer behaves
         erratically. You can leave that part out if you want to be able to edit those files locally.

       • In the last section we configure that online contacts win in a conflict situation. Configure this  part
         however you like. A correct value depends on which side is most likely to be up-to-date.

   Sync
       Now we discover and sync our contacts:

          vdirsyncer discover contacts
          vdirsyncer sync contacts

   Claws Mail
       Open Claws-Mail. Go to Tools => Addressbook.

       Click on Addressbook => New vCard. Choose a name for the book.

       Then  search  for  the  for  the  vCard  in  the  folder ~/.contacts/. Click ok, and you we will see your
       contacts.

       Note:
          Claws-Mail shows only contacts that have a mail address.

   Crontab
       On the end we create a crontab, so that vdirsyncer syncs automatically every 30 minutes our contacts:

          crontab -e

       On the end of that file enter this line:

          */30 * * * * /usr/local/bin/vdirsyncer sync > /dev/null

       And you're done!

   Running as a systemd.timer
       vdirsyncer includes unit files to run at an interval (by default every 15±5 minutes).

       Note:
          These are not installed when installing via pip, only via distribution packages. If you installed  via
          pip,  or your distribution doesn't ship systemd unit files, you'll need to download vdirsyncer.service
          <https://raw.githubusercontent.com/pimutils/vdirsyncer/main/contrib/vdirsyncer.service>            and
          vdirsyncer.timer <https://raw.githubusercontent.com/pimutils/vdirsyncer/main/contrib/vdirsyncer.timer>
          into either /etc/systemd/user/ or ~/.local/share/systemd/user.

   Activation
       To  activate the timer, just run systemctl --user enable vdirsyncer.timer.  To see logs of previous runs,
       use journalctl --user -u vdirsyncer.

   Configuration
       It's quite possible that the default "every fifteen minutes" interval isn't to your  liking.  No  default
       will suit everybody, but this is configurable by simply running:

          systemctl --user edit vdirsyncer.timer

       This will open a blank editor, where you can override the timer by including:

          OnBootSec=5m  # This is how long after boot the first run takes place.
          OnUnitActiveSec=15m  # This is how often subsequent runs take place.

   Todoman
       The iCalendar format also supports saving tasks in form of VTODO-entries, with the same file extension as
       normal events: .ics. Many CalDAV servers support synchronizing tasks, vdirsyncer does too.

       todoman  <http://todoman.readthedocs.io/>  is  a  CLI  task  manager supporting vdir <>. Its interface is
       similar to the ones of Taskwarrior or the todo.txt CLI app. You can use filesystem  <#storage-filesystem>
       with it.

   Setting up vdirsyncer
       For this tutorial we will use NextCloud.

       Assuming a config like this:

          [general]
          status_path = "~/.vdirsyncer/status/"

          [pair calendars]
          conflict_resolution = "b wins"
          a = "calendars_local"
          b = "calendars_dav"
          collections = ["from b"]
          metadata = ["color", "displayname"]

          [storage calendars_local]
          type = "filesystem"
          path = "~/.calendars/"
          fileext = ".ics"

          [storage calendars_dav]
          type = "caldav"
          url = "https://nextcloud.example.net/"
          username = "..."
          password = "..."

       vdirsyncer  sync  will then synchronize the calendars of your NextCloud <https://nextcloud.com/> instance
       to subfolders of ~/.calendar/.

   Setting up todoman
       Write this to ~/.config/todoman/config.py:

          path = "~/.calendars/*"

       The glob <https://en.wikipedia.org/wiki/Glob_(programming)> pattern in path will match all subfolders  in
       ~/.calendars/,  which  is  exactly  the  tasklists  we  want. Now you can use todoman as described in its
       documentation <http://todoman.readthedocs.io/> and run vdirsyncer sync  to  synchronize  the  changes  to
       NextCloud.

   Other clients
       The following client applications also synchronize over CalDAV:

       • The Tasks-app found on iOS

       • OpenTasks for Android <https://github.com/dmfs/opentasks>

       • The Tasks <https://apps.nextcloud.com/apps/tasks>-app for NextCloud's web UI

       Further applications, with missing pages:

       • khal  <http://lostpackets.de/khal/>,  a  CLI  calendar  application  supporting  vdir  <>.  You can use
         filesystem <#storage-filesystem> with it.

       • Many graphical calendar apps such as dayplanner  <http://www.day-planner.org/>,  Orage  <https://gitlab
         .xfce.org/apps/orage> or rainlendar <http://www.rainlendar.net/> save a calendar in a single .ics file.
         You can use singlefile <#storage-singlefile> with those.

       • khard <https://github.com/scheibler/khard/>, a commandline addressbook supporting vdir <>.  You can use
         filesystem <#storage-filesystem> with it.

       • contactquery.c    <https://github.com/t-8ch/snippets/blob/master/contactquery.c>,   a   small   program
         explicitly written for querying vdirs from mutt.

       • mates <https://github.com/pimutils/mates.rs>, a commandline addressbook supporting vdir <>.

       • vdirel <https://github.com/DamienCassou/vdirel>, access vdir <> contacts from Emacs.

   Servers
   Baikal
       Vdirsyncer is continuously tested against the latest version of Baikal <http://sabre.io/baikal/>.

       • Baikal up to 0.2.7 also uses an old version of SabreDAV, with the same issue  as  ownCloud,  see  issue
         #160 <https://github.com/pimutils/vdirsyncer/issues/160>. This issue is fixed in later versions.

   DavMail (Exchange, Outlook)
       DavMail  <http://davmail.sourceforge.net/>  is  a  proxy  program that allows you to use Card- and CalDAV
       clients with Outlook. That allows you to use vdirsyncer with Outlook.

       In practice your success with DavMail may wildly vary. Depending on your Exchange server  you  might  get
       confronted with weird errors of all sorts (including data-loss).

       Make absolutely sure you use the latest DavMail:

          [storage outlook]
          type = "caldav"
          url = "http://localhost:1080/users/user@example.com/calendar/"
          username = "user@example.com"
          password = "..."

       • Older  versions of DavMail handle URLs case-insensitively. See issue #144 <https://github.com/pimutils/
         vdirsyncer/issues/144>.

       • DavMail is handling malformed data on the Exchange server very  poorly.  In  such  cases  the  Calendar
         Checking Tool for Outlook <https://www.microsoft.com/en-us/download/details.aspx?id=28786> might help.

       • In some cases, you may see errors about duplicate events. It may look something like this:

            error: my_calendar/calendar: Storage "my_calendar_remote/calendar" contains multiple items with the same UID or even content. Vdirsyncer will now abort the synchronization of this collection, because the fix for this is not clear; It could be the result of a badly behaving server. You can try running:
            error:
            error:     vdirsyncer repair my_calendar_remote/calendar
            error:
            error: But make sure to have a backup of your data in some form. The offending hrefs are:
            [...]

         In  order  to  fix this, you can try the Remove-DuplicateAppointments.ps1 <https://blogs.msdn.microsoft
         .com/emeamsgdev/2015/02/12/powershell-remove-duplicate-calendar-appointments/> PowerShell  script  that
         Microsoft has come up with in order to remove duplicates.

   FastMail
       Vdirsyncer  is  continuously  tested  against  FastMail  <https://www.fastmail.com/>,  thanks to them for
       providing a free account for this purpose. There are no known issues with it.  FastMail's  support  pages
       <https://www.fastmail.com/help/technical/servernamesandports.html> provide the settings to use:

          [storage cal]
          type = "caldav"
          url = "https://caldav.fastmail.com/"
          username = "..."
          password = "..."

          [storage card]
          type = "carddav"
          url = "https://carddav.fastmail.com/"
          username = "..."
          password = "..."

   Google
       Using  vdirsyncer  with  Google Calendar is possible as of 0.10, but it is not tested frequently. You can
       use google_contacts <#storage-google_contacts> and google_calendar <#storage-google_calendar>.

       For more information see issue  #202  <https://github.com/pimutils/vdirsyncer/issues/202>  and  issue  #8
       <https://github.com/pimutils/vdirsyncer/issues/8>.

   iCloud
       Vdirsyncer is regularly tested against iCloud <https://www.icloud.com/>.

          [storage cal]
          type = "caldav"
          url = "https://caldav.icloud.com/"
          username = "..."
          password = "..."

          [storage card]
          type = "carddav"
          url = "https://contacts.icloud.com/"
          username = "..."
          password = "..."

       Problems:

       • Vdirsyncer  can't  do two-factor auth with iCloud (there doesn't seem to be a way to do two-factor auth
         over the DAV APIs) You'll need to use app-specific passwords <https://support.apple.com/en-us/HT204397>
         instead.

       • iCloud has a few special requirements when creating collections. In principle vdirsyncer can do it, but
         it is recommended to create them from an Apple client (or the iCloud web interface).

         • iCloud requires a minimum length of collection names.

         • Calendars created by vdirsyncer cannot be used as tasklists.

   nextCloud
       Vdirsyncer is continuously tested against the latest version of nextCloud <https://nextcloud.com/>:

          [storage cal]
          type = "caldav"
          url = "https://nextcloud.example.com/"
          username = "..."
          password = "..."

          [storage card]
          type = "carddav"
          url = "https://nextcloud.example.com/"

       • WebCAL-subscriptions can't be discovered by vdirsyncer. See this  relevant  issue  <https://github.com/
         nextcloud/calendar/issues/63>.

   ownCloud
       Vdirsyncer is continuously tested against the latest version of ownCloud <https://owncloud.org/>:

          [storage cal]
          type = "caldav"
          url = "https://example.com/remote.php/dav/"
          username = ...
          password = ...

          [storage card]
          type = "carddav"
          url = "https://example.com/remote.php/dav/"
          username = ...
          password = ...

       • Versions  older  than  7.0.0:  ownCloud  uses  SabreDAV,  which  had  problems detecting collisions and
         race-conditions. The problems were reported and are fixed in SabreDAV's repo, and the corresponding fix
         is also in ownCloud since 7.0.0. See issue #16  <https://github.com/pimutils/vdirsyncer/issues/16>  for
         more information.

   Radicale
       Radicale <http://radicale.org/> is a very lightweight server, however, it intentionally doesn't implement
       the  CalDAV  and  CardDAV  standards  completely,  which might lead to issues even with very well-written
       clients. Apart from its non-conformity with standards, there are multiple other problems  with  its  code
       quality and the way it is maintained. Consider using e.g. Xandikos <> instead.

       That  said,  vdirsyncer  is  continuously  tested  against the git version and the latest PyPI release of
       Radicale.

       • Vdirsyncer can't create collections on Radicale.

       • Radicale doesn't support  time  ranges  in  the  calendar-query  of  CalDAV  <https://github.com/Kozea/
         Radicale/issues/146>,  so  setting start_date and end_date for caldav <#storage-caldav> will have no or
         unpredicted consequences.

       • Versions of Radicale older than 0.9b1 choke on RFC-conform  queries  for  all  items  of  a  collection
         <https://github.com/Kozea/Radicale/issues/143>.

         You  have  to  set  item_types = ["VTODO", "VEVENT"] in caldav <#storage-caldav> for vdirsyncer to work
         with those versions.

   Xandikos
       Xandikos <https://github.com/jelmer/xandikos> is a lightweight, yet complete CalDAV and  CardDAV  server,
       backed by git. Vdirsyncer is continuously tested against its latest version.

       After  running ./bin/xandikos --defaults -d $HOME/dav, you should be able to point vdirsyncer against the
       root of Xandikos like this:

          [storage cal]
          type = "caldav"
          url = "https://xandikos.example.com/"
          username = "..."
          password = "..."

          [storage card]
          type = "carddav"
          url = "https://xandikos.example.com/"
          username = "..."
          password = "..."

KNOWN PROBLEMS

       For any unanswered questions or problems, see Support and Contact <>.

   Requests-related ImportErrors
          ImportError: No module named packages.urllib3.poolmanager

          ImportError: cannot import name iter_field_objects

       Debian and nowadays even other distros make modifications to the requests package that  don't  play  well
       with packages assuming a normal requests. This is due to stubbornness on both sides.

       See  issue  #82  <https://github.com/pimutils/vdirsyncer/issues/82>  and  issue #140 <https://github.com/
       pimutils/vdirsyncer/issues/140> for past discussions. You have one option to work around this,  that  is,
       to install vdirsyncer in a virtual environment, see Manual installation <#manual-installation>.

CONTRIBUTING TO THIS PROJECT

       Note:

          • Please read Support and Contact <> for questions and support requests.

          • All participants must follow the pimutils Code of Conduct <http://pimutils.org/coc>.

   The issue tracker
       We  use  GitHub  issues  <https://github.com/pimutils/vdirsyncer/issues>  for  organizing bug reports and
       feature requests.

       The following labels <https://github.com/pimutils/vdirsyncer/labels> are of interest:

       • "Planning" is for issues that are still undecided, but where at least some discussion exists.

       • "Blocked" is for issues that can't be worked on at the  moment  because  some  other  unsolved  problem
         exists. This problem may be a bug in some software dependency, for instance.

       • "Ready" contains issues that are ready to work on.

       If  you  just  want  to  get started with contributing, the "ready" issues are an option. Issues that are
       still in "Planning" are also an option, but require  more  upfront  thinking  and  may  turn  out  to  be
       impossible  to  solve,  or  at  least harder than anticipated. On the flip side those tend to be the more
       interesting issues as well, depending on how one looks at it.

       All of those labels are also available  as  a  kanban  board  on  waffle.io  <https://waffle.io/pimutils/
       vdirsyncer>.  It  is  really  just  an  alternative  overview  over  all  issues,  but might be easier to
       comprehend.

       Feel free to contact <> me or comment on the relevant issues for further information.

   Reporting bugs
       • Make sure your problem isn't already listed in Known Problems <>.

       • Make sure you have the absolutely latest version of vdirsyncer. For users of some  Linux  distributions
         such  as  Debian  or  Fedora this may not be the version that your distro offers. In those cases please
         file a bug against the distro package, not against upstream vdirsyncer.

       • Use --verbosity=DEBUG when including output from vdirsyncer.

   Suggesting features
       If you're suggesting a feature, keep in mind that vdirsyncer tries not to be a full calendar or  contacts
       client,  but  rather  just  the  piece  of  software  that  synchronizes all the data. Take a look at the
       documentation for software working with vdirsyncer <>.

   Submitting patches, pull requestsDiscuss everything in the issue tracker first (or contact me somehow else) before implementing it.

       • Make sure the tests pass. See below for running them.

       • But not because you wrote too few tests.

       • Add yourself to AUTHORS.rst, and add a note to CHANGELOG.rst too.

   Running tests, how to set up your development environment
       For many patches, it might suffice to just let CI run the tests. However, CI is slow, so you  might  want
       to  run  them locally too. For this, set up a virtualenv <http://virtualenv.readthedocs.io/> and run this
       inside of it:

          # Install development dependencies, including:
          #  - vdirsyncer from the repo into the virtualenv
          #  - style checks and formatting (ruff)
          make install-dev

          # Install git commit hook for some extra linting and checking
          pre-commit install

       Then you can run:

          pytest                # The normal testsuite
          pre-commit run --all  # Run all linters (which also run via pre-commit)
          make -C docs html     # Build the HTML docs, output is at docs/_build/html/
          make -C docs linkcheck  # Check docs for any broken links

       The Makefile has a lot of options that allow you to control which tests are run, and  which  servers  are
       tested. Take a look at its code where they are all initialized and documented.

       To tests against a specific DAV server, use DAV_SERVER:

          make DAV_SERVER=xandikos test

       The server will be initialised in a docker container and terminated at the end of the test suite.

       If you have any questions, feel free to open issues about it.

   Structure of the testsuite
       Within tests/, there are three main folders:

       • system  contains  system-  and  also integration tests. A rough rule is: If the test is using temporary
         files, put it here.

       • unit, where each testcase tests a single class or function.

       • storage runs a generic storage testsuite against all storages.

       The reason for this separation is: We are planning to generate separate  coverage  reports  for  each  of
       those  testsuites.  Ideally unit would generate palatable coverage of the entire codebase on its own, and
       the combination of system and storage as well.

THE VDIR STORAGE FORMAT

       This document describes a standard for storing calendars and contacts on a filesystem, with the main goal
       of being easy to implement.

       Vdirsyncer synchronizes to vdirs via  filesystem  <#storage-filesystem>.  Each  vdir  (basically  just  a
       directory with some files in it) represents a calendar or addressbook.

   Basic Structure
       The main folder (root) contains an arbitrary number of subfolders (collections), which contain only files
       (items). Synonyms for "collection" may be "addressbook" or "calendar".

       An item is:

       • A vCard <https://tools.ietf.org/html/rfc6350> file, in which case the file extension must be .vcf, or

       • An iCalendar <https://tools.ietf.org/html/rfc5545> file, in which case the file extension must be .ics.

       An  item  should contain a UID property as described by the vCard and iCalendar standards. If it contains
       more than one UID property, the values of those must not differ.

       The file must contain exactly one event, task or contact. In  most  cases  this  also  implies  only  one
       VEVENT/VTODO/VCARD  component  per  file,  but  e.g.  recurrence exceptions would require multiple VEVENT
       components per event.

       The filename should have similar properties as the UID  of  the  file  content.   However,  there  is  no
       requirement  for  these  two  to  be  the  same. Programs may choose to store additional metadata in that
       filename, however, at the same time they must  not  assume  that  the  metadata  they  included  will  be
       preserved by other programs.

   Metadata
       Any of the below metadata files may be absent. None of the files listed below have any file extensions.

       • A  file called color inside the vdir indicates the vdir's color, a property that is only relevant in UI
         design.

         Its content is an ASCII-encoded hex-RGB value of the form #RRGGBB.  For  example,  a  file  content  of
         #FF0000  indicates that the vdir has a red (user-visible) color. No short forms or informal values such
         as red (as known from CSS, for example) are allowed. The prefixing # must be present.

       • Files called displayname and description contain a UTF-8 encoded label/ description, that may  be  used
         to represent the vdir in UIs.

       • A  file  called  order  inside the vdir includes the relative order of the calendar, a property that is
         only relevant in UI design.

   Writing to vdirs
       Creating and modifying items or metadata files should happen  atomically  <https://en.wikipedia.org/wiki/
       Atomicity_%28programming%29>.

       Writing  to  a temporary file on the same physical device, and then moving it to the appropriate location
       is usually a very effective solution. For this purpose, files with the  extension  .tmp  may  be  created
       inside collections.

       When changing an item, the original filename must be used.

   Reading from vdirs
       • Any file ending with the .tmp or no file extension must not be treated as an item.

       • The ident part of the filename should not be parsed to improve the speed of item lookup.

   Considerations
       The primary reason this format was chosen is due to its compatibility with the CardDAV <http://tools.ietf
       .org/html/rfc6352> and CalDAV <http://tools.ietf.org/search/rfc4791> standards.

   Performance
       Currently, vdirs suffer from a rather major performance problem, one which current implementations try to
       mitigate by building up indices of the collections for faster search and lookup.

       The  reason  items'  filenames  don't  contain  any  extra information is simple: The solutions presented
       induced duplication of data, where one duplicate might become out of date because of bad implementations.
       As it stands right now, an index format could be formalized separately though.

       vdirsyncer doesn't really have to  bother  about  efficient  item  lookup,  because  its  synchronization
       algorithm  needs  to  fetch  the  whole list of items anyway.  Detecting changes is easily implemented by
       checking the files' modification time.

PACKAGING GUIDELINES

       Thank you very much for packaging vdirsyncer! The following guidelines should  help  you  to  avoid  some
       common pitfalls.

       If  you  find yourself needing to patch anything, or going in a different direction, please open an issue
       so we can also address in a way that works for everyone.  Otherwise  we  get  bug  reports  for  code  or
       scenarios that don't exist in upstream vdirsycner.

   Obtaining the source code
       The  main distribution channel is PyPI <https://pypi.python.org/pypi/vdirsyncer>, and source tarballs can
       be obtained there. We mirror the same package tarball and wheel as GitHub releases. Please do not confuse
       these with the auto-generated GitHub "Source Code" tarball. Those are missing some important metadata and
       your build will fail.

       We give each release a tag in the git repo. If you want to get notified of new  releases,  GitHub's  feed
       <https://github.com/pimutils/vdirsyncer/releases.atom> is a good way.

       Tags  will be signed by the maintainer who is doing the release (starting with 0.16.8), and generation of
       the tarball and wheel is done by CI. Hence, only the tag itself is signed.

   Dependency versions
       As with most Python  packages,  setup.py  denotes  the  dependencies  of  vdirsyncer.  It  also  contains
       lower-bound versions of each dependency. Older versions will be rejected by the testsuite.

   Testing
       Everything  testing-related  goes  through  the  Makefile  in the root of the repository or PyPI package.
       Trying to e.g. run pytest  directly  will  require  a  lot  of  environment  variables  to  be  set  (for
       configuration) and you probably don't want to deal with that.

       You can install the all development dependencies with:

          make install-dev

       You  probably  don't  want  this  since  it will use pip to download the dependencies. Alternatively test
       dependencies are listed as test optional dependencies in pyproject.toml, again with  lower-bound  version
       requirements.

       You  also  have to have vdirsyncer fully installed at this point. Merely cd-ing into the tarball will not
       be sufficient.

       Running the tests happens with:

          pytest

       Hypothesis  will  randomly  generate  test  input.  If  you  care  about  deterministic  tests,  set  the
       DETERMINISTIC_TESTS variable to "true":

          make DETERMINISTIC_TESTS=true test

       There  are  a  lot of additional variables that allow you to test vdirsyncer against a particular server.
       Those variables are not "stable" and may change drastically between minor versions. Just don't use  them,
       you are unlikely to find bugs that vdirsyncer's CI hasn't found.

   Documentation
       Using  Sphinx  <www.sphinx-doc.org/>  you  can  generate  the documentation you're reading right now in a
       variety of formats, such as HTML, PDF, or even as a manpage. That said, I only  take  care  of  the  HTML
       docs' formatting.

       You  can  find  a  list  of dependencies in docs-requirements.txt. Again, you can install those using pip
       with:

          pip install -r docs-requirements.txt

       Then change into the docs/ directory and build whatever format you want using the Makefile in there  (run
       make for the formats you can build).

   Contrib files
       Reference systemd.service and systemd.timer unit files are provided. It is recommended to install this if
       your distribution is systemd-based.

SUPPORT AND CONTACT

       • The  #pimutils  IRC channel on Libera.Chat <https://pimutils.org/contact> might be active, depending on
         your timezone. Use it for support and general (including off-topic) discussion.

       • Open a GitHub issue  <https://github.com/pimutils/vdirsyncer/issues/>  for  concrete  bug  reports  and
         feature requests.

       • For security issues, contact contact@pimutils.org.

CHANGELOG

       This  changelog  only contains information that might be useful to end users and package maintainers. For
       further info, see the git commit log.

       Package maintainers and users who have to manually update their installation may  want  to  subscribe  to
       GitHub's tag feed <https://github.com/pimutils/vdirsyncer/tags.atom>.

   Version 0.20.0
       • Remove dependency on abandoned atomicwrites library.

       • Implement filter_hook for the HTTP storage.

       • Drop support for Python 3.7.

       • Add support for Python 3.12 and Python 3.13.

       • Properly  close the status database after using. This especially affects tests, where we were leaking a
         large amount of file descriptors.

       • Extend supported versions of aiostream to include 0.7.x.

   Version 0.19.3
       • Added a no_delete option  to  the  storage  configuration.  issue  #1090  <https://github.com/pimutils/
         vdirsyncer/issues/1090>

       • Fix  crash  when  running  vdirsyncer repair on a collection. issue #1019 <https://github.com/pimutils/
         vdirsyncer/issues/1019>

       • Add an option to request vCard v4.0.  issue #1066 <https://github.com/pimutils/vdirsyncer/issues/1066>

       • Require matching BEGIN and END lines in vobjects. issue #1103  <https://github.com/pimutils/vdirsyncer/
         issues/1103>

       • A  Docker  environment  for Vdirsyncer has been added Vdirsyncer DOCKERIZED <https://github.com/Bleala/
         Vdirsyncer-DOCKERIZED>.

       • Implement digest auth. issue #1137 <https://github.com/pimutils/vdirsyncer/issues/1137>

       • Add filter_hook parameter to http <#storage-http>. issue #1136 <https://github.com/pimutils/vdirsyncer/
         issues/1136>

   Version 0.19.2
       • Improve the  performance  of  SingleFileStorage.  issue  #818  <https://github.com/pimutils/vdirsyncer/
         issues/818>

       • Properly document some caveats of the Google Contacts storage.

       • Fix crash when using auth certs. issue #1033 <https://github.com/pimutils/vdirsyncer/issues/1033>

       • The   filesystem   storage   can   be   specified   with   type  =  "filesystem/icalendar"  or  type  =
         "filesystem/vcard". This has not functional impact, and is merely for forward  compatibility  with  the
         Rust implementation of vdirsyncer.

       • Python 3.10 and 3.11 are officially supported.

       • Instructions  for  integrating  with  Google  CalDav/CardDav have changed.  Applications now need to be
         registered as "Desktop applications". Using "Web  application"  no  longer  works  due  to  changes  on
         Google's side. issue #1078 <https://github.com/pimutils/vdirsyncer/issues/1078>

   Version 0.19.1
       • Fixed  crash  when  operating  on  Google Contacts. issue #994 <https://github.com/pimutils/vdirsyncer/
         issues/994>

       • The HTTP_PROXY and HTTPS_PROXY are now respected. issue #1031  <https://github.com/pimutils/vdirsyncer/
         issues/1031>

       • Instructions  for  integrating  with  Google  CalDav/CardDav have changed.  Applications now need to be
         registered as "Web Application". issue #975 <https://github.com/pimutils/vdirsyncer/issues/975>

       • Various documentation updates.

   Version 0.19.0
       • Add "shell" password fetch strategy to pass command string to a shell.

       • Add  "description"  and  "order"  as  metadata.   These   fetch   the   CalDAV:   calendar-description,
         CardDAV:addressbook-description and apple-ns:calendar-order properties respectively.

       • Add a new showconfig status. This prints some configuration values as JSON. This is intended to be used
         by external tools and helpers that interact with vdirsyncer, and considered experimental.

       • Update  TLS-related  tests  that were failing due to weak MDs. issue #903 <https://github.com/pimutils/
         vdirsyncer/issues/903>

       • pytest-httpserver and trustme are now required for tests.

       • pytest-localserver is no longer required for tests.

       • Multithreaded support has been dropped. The "--max-workers has been removed.

       • A new asyncio backend is now used. So far, this shows substantial speed improvements in  discovery  and
         metasync,  but  little  change  in  sync.   This  will  likely continue improving over time. issue #906
         <https://github.com/pimutils/vdirsyncer/issues/906>

       • The google storage types no  longer  require  requests-oauthlib,  but  require  python-aiohttp-oauthlib
         instead.

       • Vdirsyncer no longer includes experimental support for EteSync <https://www.etesync.com/>. The existing
         integration  had not been supported for a long time and no longer worked. Support for external storages
         may be added if anyone is interested in maintaining an EteSync plugin. EteSync  users  should  consider
         using etesync-dav <https://github.com/etesync/etesync-dav>.

       • The  plist  for macOS has been dropped. It was broken and homebrew generates their own based on package
         metadata. macOS users are encouraged to use that as a reference.

   Changes to SSL configuration
       Support for md5 and sha1 certificate fingerprints has been  dropped.  If  you're  validating  certificate
       fingerprints, use sha256 instead.

       When using a custom verify_fingerprint, CA validation is always disabled.

       If verify_fingerprint is unset, CA verification is always active. Disabling both features is insecure and
       no longer supported.

       The  verify  parameter  no  longer  takes boolean values, it is now optional and only takes a string to a
       custom CA for verification.

       The verify and verify_fingerprint will likely be merged into a single parameter in future.

   Version 0.18.0
       Note: Version 0.17 has some alpha releases but ultimately was never finalised.  0.18  actually  continues
       where 0.16 left off.

       • Support  for  Python  3.5  and  3.6 has been dropped. This release mostly focuses on keeping vdirsyncer
         compatible with newer environments.

       • click 8 and click-threading 0.5.0 are now required.

       • For those using pipsi, we now recommend using pipx, it's successor.

       • Python 3.9 is now supported.

       • Our Debian/Ubuntu build scripts have been updated. New versions should be pushed to those  repositories
         soon.

   Version 0.16.8
       released 09 June 2020

       • Support Python 3.7 and 3.8.

       This  release is functionally identical to 0.16.7.  It's been tested with recent Python versions, and has
       been marked as supporting them. It will also be the final release supporting Python 3.5 and 3.6.

   Version 0.16.7
       released on 19 July 2018

       • Fixes for Python 3.7

   Version 0.16.6
       released on 13 June 2018Packagers: Documentation building no longer needs a working installation of vdirsyncer.

   Version 0.16.5
       released on 13 June 2018Packagers: click-log 0.3 is required.

       • All output will now happen on stderr (because of the upgrade of click-log).

   Version 0.16.4
       released on 05 February 2018

       • Fix tests for new Hypothesis version. (Literally no other change included)

   Version 0.16.3
       released on 03 October 2017

       • First version with custom Debian and Ubuntu  packages.  See  issue  #663  <https://github.com/pimutils/
         vdirsyncer/issues/663>.

       • Remove  invalid  ASCII  control  characters  from server responses. See issue #626 <https://github.com/
         pimutils/vdirsyncer/issues/626>.

       • packagers: Python 3.3 is no longer  supported.  See  pull  request  #674  <https://github.com/pimutils/
         vdirsyncer/pull/674>.

   Version 0.16.2
       released on 24 August 2017

       • Fix  crash when using daterange or item_type filters in google_calendar <#storage-google_calendar>, see
         issue #657 <https://github.com/pimutils/vdirsyncer/issues/657>.

       • Packagers: Fixes for new version 0.2.0 of  click-log.  The  version  requirements  for  the  dependency
         click-log changed.

   Version 0.16.1
       released on 8 August 2017

       • Removed remoteStorage support, see issue #647 <https://github.com/pimutils/vdirsyncer/issues/647>.

       • Fixed  test  failures  caused  by latest requests version, see issue #660 <https://github.com/pimutils/
         vdirsyncer/issues/660>.

   Version 0.16.0
       released on 2 June 2017

       • Strip METHOD:PUBLISH added by some calendar providers,  see  issue  #502  <https://github.com/pimutils/
         vdirsyncer/issues/502>.

       • Fix crash of Google storages when saving token file.

       • Make  DAV discovery more RFC-conformant, see pull request #585 <https://github.com/pimutils/vdirsyncer/
         pull/585>.

       • Vdirsyncer is  now  tested  against  Xandikos,  see  pull  request  #601  <https://github.com/pimutils/
         vdirsyncer/pull/601>.

       • Subfolders  with  a  leading  dot are now ignored during discover for filesystem storage. This makes it
         easier to combine it with version control.

       • Statuses are now stored in a sqlite database. Old data is automatically  migrated.  Users  with  really
         large  datasets  should encounter performance improvements. This means that sqlite3 is now a dependency
         of vdirsyncer.

       • Vdirsyncer is now licensed under the 3-clause BSD license, see issue #610 <https://github.com/pimutils/
         vdirsyncer/issues/610>.

       • Vdirsyncer now includes experimental support for EteSync <https://www.etesync.com/>, see  pull  request
         #614 <https://github.com/pimutils/vdirsyncer/pull/614>.

       • Vdirsyncer now uses more filesystem metadata for determining whether an item changed. You will notice a
         possibly heavy CPU/IO spike on the first sync after upgrading.

       • Packagers:  Reference  systemd.service  and systemd.timer unit files are provided. It is recommended to
         install these as documentation if your distribution is systemd-based.

   Version 0.15.0
       released on 28 February 2017

       • Deprecated syntax for configuration values is now completely rejected. All values now have to be  valid
         JSON.

       • A  few  UX  improvements  for  Google storages, see issue #549 <https://github.com/pimutils/vdirsyncer/
         issues/549> and issue #552 <https://github.com/pimutils/vdirsyncer/issues/552>.

       • Fix collection discovery for google_contacts <#storage-google_contacts>, see issue #564 <https://github
         .com/pimutils/vdirsyncer/issues/564>.

       • iCloud is now tested on Travis, see issue #567 <https://github.com/pimutils/vdirsyncer/issues/567>.

   Version 0.14.1
       released on 05 January 2017vdirsyncer repair no longer changes "unsafe" UIDs by default, an extra option has to be specified.  See
         issue #527 <https://github.com/pimutils/vdirsyncer/issues/527>.

       • A lot of important documentation updates.

   Version 0.14.0
       released on 26 October 2016vdirsyncer  sync now continues other uploads if one upload failed.  The exit code in such situations is
         still non-zero.

       • Add partial_sync option to pair section. See the config docs <#partial-sync-def>.

       • Vdirsyncer will now warn if there's a string without quotes in your config.  Please file issues if  you
         find documentation that uses unquoted strings.

       • Fix an issue that would break khal's config setup wizard.

   Version 0.13.1
       released on 30 September 2016

       • Fix a bug that would completely break collection discovery.

   Version 0.13.0
       released on 29 September 2016

       • Python  2 is no longer supported at all. See issue #219 <https://github.com/pimutils/vdirsyncer/issues/
         219>.

       • Config sections are now checked for duplicate names. This also means that you  cannot  have  a  storage
         section  [storage foo] and a pair [pair foo] in your config, they have to have different names. This is
         done such that console output is  always  unambiguous.  See  issue  #459  <https://github.com/pimutils/
         vdirsyncer/issues/459>.

       • Custom  commands  can  now  be used for conflict resolution during sync. See issue #127 <https://github
         .com/pimutils/vdirsyncer/issues/127>.

       • http <#storage-http> now completely ignores UIDs. This avoids a lot of unnecessary down- and uploads.

   Version 0.12.1
       released on 20 August 2016

       • Fix a crash for Google and DAV storages. See pull request #492 <https://github.com/pimutils/vdirsyncer/
         pull/492>.

       • Fix an URL-encoding problem  with  DavMail.  See  issue  #491  <https://github.com/pimutils/vdirsyncer/
         issues/491>.

   Version 0.12
       released on 19 August 2016singlefile  <#storage-singlefile>  now supports collections. See pull request #488 <https://github.com/
         pimutils/vdirsyncer/pull/488>.

   Version 0.11.3
       released on 29 July 2016

       • Default value of auth parameter was changed from guess to  basic  to  resolve  issues  with  the  Apple
         Calendar   Server   (issue   #457   <https://github.com/pimutils/vdirsyncer/issues/457>)   and  improve
         performance. See issue #461 <https://github.com/pimutils/vdirsyncer/issues/461>.

       • Packagers: The click-threading requirement is now >=0.2.  It  was  incorrect  before.  See  issue  #478
         <https://github.com/pimutils/vdirsyncer/issues/478>.

       • Fix a bug in the DAV XML parsing code that would make vdirsyncer crash on certain input. See issue #480
         <https://github.com/pimutils/vdirsyncer/issues/480>.

       • Redirect  chains  should  now be properly handled when resolving well-known URLs. See pull request #481
         <https://github.com/pimutils/vdirsyncer/pull/481>.

   Version 0.11.2
       released on 15 June 2016

       • Fix typo that would break tests.

   Version 0.11.1
       released on 15 June 2016

       • Fix a bug in collection validation.

       • Fix a cosmetic bug in debug output.

       • Various documentation improvements.

   Version 0.11.0
       released on 19 May 2016

       • Discovery is no longer automatically done when running vdirsyncer sync.  vdirsyncer discover now has to
         be explicitly called.

       • Add a .plist example for Mac OS X.

       • Usage under Python 2 now requires a special config parameter to be set.

       • Various deprecated configuration parameters do no longer have specialized  errormessages.  The  generic
         error message for unknown parameters is shown.

         • Vdirsyncer no longer warns that the passwordeval parameter has been renamed to password_command.

         • The  keyring  fetching strategy has been dropped some versions ago, but the specialized error message
           has been dropped.

         • An old status format from version 0.4 is no longer supported. If you're experiencing  problems,  just
           delete your status folder.

   Version 0.10.0
       released on 23 April 2016

       • New    storage    types    google_calendar    <#storage-google_calendar>    and    google_contacts   <#
         storage-google_contacts> have been added.

       • New global command line option --config,  to  specify  an  alternative  config  file.  See  issue  #409
         <https://github.com/pimutils/vdirsyncer/issues/409>.

       • The collections parameter can now be used to synchronize differently-named collections with each other.

       • Packagers: The lxml dependency has been dropped.

       • XML  parsing  is  now a lot stricter. Malfunctioning servers that used to work with vdirsyncer may stop
         working.

   Version 0.9.3
       released on 22 March 2016singlefile <#storage-singlefile> and http <#storage-http> now handle recurring events properly.

       • Fix a typo in the packaging guidelines.

       • Moved to pimutils organization on GitHub. Old links should redirect, but be aware  of  client  software
         that doesn't properly handle redirects.

   Version 0.9.2
       released on 13 March 2016

       • Fixed  testsuite  for  environments  that  don't have any web browser installed.  See pull request #384
         <https://github.com/pimutils/vdirsyncer/pull/384>.

   Version 0.9.1
       released on 13 March 2016

       • Removed    leftover    debug    print    statement    in    vdirsyncer     discover,     see     commit
         3d856749f37639821b148238ef35f1acba82db36.

       • metasync  will  now strip whitespace from the start and the end of the values. See issue #358 <https://
         github.com/pimutils/vdirsyncer/issues/358>.

       • New Packaging Guidelines have been added to the documentation.

   Version 0.9.0
       released on 15 February 2016

       • The collections parameter is now required in pair configurations.  Vdirsyncer will tell you what to  do
         in its error message. See issue #328 <https://github.com/pimutils/vdirsyncer/issues/328>.

   Version 0.8.1
       released on 30 January 2016

       • Fix  error  messages  when invalid parameter fetching strategy is used. This is important because users
         would receive awkward errors for using deprecated keyring fetching.

   Version 0.8.0
       released on 27 January 2016

       • Keyring support has  been  removed,  which  means  that  password.fetch  =  ["keyring",  "example.com",
         "myuser"] doesn't work anymore.

         For  existing  setups:  Use  password.fetch  =  ["command",  "keyring", "get", "example.com", "myuser"]
         instead, which is more generic. See the documentation for details.

       • Now emitting a warning when running  under  Python  2.  See  issue  #219  <https://github.com/pimutils/
         vdirsyncer/issues/219>.

   Version 0.7.5
       released on 23 December 2015

       • Fixed a bug in remotestorage that would try to open a CLI browser for OAuth.

       • Fix a packaging bug that would prevent vdirsyncer from working with newer lxml versions.

   Version 0.7.4
       released on 22 December 2015

       • Improved error messages instead of faulty server behavior, see issue #290 <https://github.com/pimutils/
         vdirsyncer/issues/290> and issue #300 <https://github.com/pimutils/vdirsyncer/issues/300>.

       • Safer shutdown of threadpool, avoid exceptions, see issue #291 <https://github.com/pimutils/vdirsyncer/
         issues/291>.

       • Fix a sync bug for read-only storages see commit ed22764921b2e5bf6a934cf14aa9c5fede804d8e.

       • Etag  changes  are  no  longer  sufficient to trigger sync operations. An actual content change is also
         necessary. See issue #257 <https://github.com/pimutils/vdirsyncer/issues/257>.

       • remotestorage now automatically opens authentication dialogs in your configured GUI browser.

       • Packagers: lxml>=3.1 is now required (newer lower-bound version).

   Version 0.7.3
       released on 05 November 2015

       • Make remotestorage-dependencies actually optional.

   Version 0.7.2
       released on 05 November 2015

       • Un-break testsuite.

   Version 0.7.1
       released on 05 November 2015Packagers: The setuptools extras keyring and remotestorage have been added. They're basically  optional
         dependencies. See setup.py for more details.

       • Highly  experimental  remoteStorage  support  has  been  added. It may be completely overhauled or even
         removed in any version.

       • Removed mentions of old password_command in documentation.

   Version 0.7.0
       released on 27 October 2015Packagers: New dependencies are click_threading, click_log and click>=5.0.

       • password_command is gone. Keyring support got completely overhauled. See Storing passwords <>.

   Version 0.6.0
       released on 06 August 2015password_command invocations with non-zero exit code are now fatal  (and  will  abort  synchronization)
         instead of just producing a warning.

       • Vdirsyncer  is  now able to synchronize metadata of collections. Set metadata = ["displayname"] and run
         vdirsyncer metasync.

       • Packagers: Don't use the GitHub tarballs, but the PyPI ones.

       • Packagers: build.sh is gone, and Makefile is included in tarballs. See the content of Makefile  on  how
         to run tests post-packaging.

       • verify_fingerprint doesn't automatically disable verify anymore.

   Version 0.5.2
       released on 15 June 2015

       • Vdirsyncer now checks and corrects the permissions of status files.

       • Vdirsyncer is now more robust towards changing UIDs inside items.

       • Vdirsyncer  is  now handling unicode hrefs and UIDs correctly. Software that produces non-ASCII UIDs is
         broken, but apparently it exists.

   Version 0.5.1
       released on 29 May 2015N.b.: The PyPI upload of 0.5.0 is completely broken.

       • Raise version of required requests-toolbelt to 0.4.0.

       • Command line should be a lot faster when no work is done, e.g. for help output.

       • Fix compatibility with iCloud again.

       • Use only one worker if debug mode is activated.

       • verify=false is now disallowed in vdirsyncer, please use verify_fingerprint instead.

       • Fixed a bug where vdirsyncer's DAV storage was  not  using  the  configured  useragent  for  collection
         discovery.

   Version 0.4.4
       released on 12 March 2015

       • Support  for  client  certificates via the new auth_cert parameter, see issue #182 <https://github.com/
         pimutils/vdirsyncer/issues/182> and  pull  request  #183  <https://github.com/pimutils/vdirsyncer/pull/
         183>.

       • The icalendar package is no longer required.

       • Several bugfixes related to collection creation.

   Version 0.4.3
       released on 20 February 2015

       • More performance improvements to singlefile-storage.

       • Add post_hook param to filesystem-storage.

       • Collection creation now also works with SabreDAV-based servers, such as Baikal or ownCloud.

       • Removed some workarounds for Radicale. Upgrading to the latest Radicale will fix the issues.

       • Fixed issues with iCloud discovery.

       • Vdirsyncer now includes a simple repair command that seeks to fix some broken items.

   Version 0.4.2
       released on 30 January 2015

       • Vdirsyncer now respects redirects when uploading and updating items. This might fix issues with Zimbra.

       • Relative status_path values are now interpreted as relative to the configuration file's directory.

       • Fixed  compatibility  with  custom  SabreDAV  servers.  See  issue  #166  <https://github.com/pimutils/
         vdirsyncer/issues/166>.

       • Catch harmless threading exceptions that occur when shutting down vdirsyncer.  See issue #167 <https://
         github.com/pimutils/vdirsyncer/issues/167>.

       • Vdirsyncer now depends on atomicwrites.

       • Massive performance improvements to singlefile-storage.

       • Items with extremely long UIDs should now be saved  properly  in  filesystem-storage.  See  issue  #173
         <https://github.com/pimutils/vdirsyncer/issues/173>.

   Version 0.4.1
       released on 05 January 2015

       • All  create  arguments  from  all  storages  are  gone.  Vdirsyncer now asks if it should try to create
         collections.

       • The old config values True, False, on, off and None are now invalid.

       • UID conflicts are now properly handled instead of ignoring one  item.  Card-  and  CalDAV  servers  are
         already supposed to take care of those though.

       • Official Baikal support added.

   Version 0.4.0
       released on 31 December 2014

       • The passwordeval parameter has been renamed to password_command.

       • The old way of writing certain config values such as lists is now gone.

       • Collection  discovery  has  been  rewritten.  Old configuration files should be compatible with it, but
         vdirsyncer now caches the results of the collection discovery. You have to run vdirsyncer  discover  if
         collections were added or removed on one side.

       • Pair  and  storage  names are now restricted to certain characters. Vdirsyncer will issue a clear error
         message if your configuration file is invalid in that regard.

       • Vdirsyncer now supports the XDG-Basedir specification. If the  VDIRSYNCER_CONFIG  environment  variable
         isn't  set  and the ~/.vdirsyncer/config file doesn't exist, it will look for the configuration file at
         $XDG_CONFIG_HOME/vdirsyncer/config.

       • Some improvements to CardDAV and CalDAV discovery, based on problems found with FastMail.  Support  for
         .well-known-URIs has been added.

   Version 0.3.4
       released on 8 December 2014

       • Some more bugfixes to config handling.

   Version 0.3.3
       released on 8 December 2014

       • Vdirsyncer now also works with iCloud. Particularly collection discovery and etag handling were fixed.

       • Vdirsyncer now encodes Cal- and CardDAV requests differently. This hasn't been well-tested with servers
         like Zimbra or SoGo, but isn't expected to cause any problems.

       • Vdirsyncer  is  now  more robust regarding invalid responses from CalDAV servers. This should help with
         future compatibility with Davmail/Outlook.

       • Fix a bug when specifying item_types of caldav <#storage-caldav> in the deprecated config format.

       • Fix a bug where vdirsyncer would ignore all but one character specified in unsafe_href_chars of  caldav
         <#storage-caldav> and carddav <#storage-carddav>.

   Version 0.3.2
       released on 3 December 2014

       • The  current  config  format  has been deprecated, and support for it will be removed in version 0.4.0.
         Vdirsyncer warns about this now.

   Version 0.3.1
       released on 24 November 2014

       • Fixed a bug where vdirsyncer would delete items if they're deleted on side A but modified  on  side  B.
         Instead  vdirsyncer  will  now  upload  the  new  items  to side A. See issue #128 <https://github.com/
         pimutils/vdirsyncer/issues/128>.

       • Synchronization continues with the remaining pairs if one pair crashes, see issue #121  <https://github
         .com/pimutils/vdirsyncer/issues/121>.

       • The  processes  config  key is gone. There is now a --max-workers option on the CLI which has a similar
         purpose. See pull request #126 <https://github.com/pimutils/vdirsyncer/pull/126>.

       • The Read The Docs-theme is no longer required for building the  docs.  If  it  is  not  installed,  the
         default theme will be used. See issue #134 <https://github.com/pimutils/vdirsyncer/issues/134>.

   Version 0.3.0
       released on 20 September 2014

       • Add  verify_fingerprint  parameter  to  http  <#storage-http>,  caldav <#storage-caldav> and carddav <#
         storage-carddav>, see issue #99  <https://github.com/pimutils/vdirsyncer/issues/99>  and  pull  request
         #106 <https://github.com/pimutils/vdirsyncer/pull/106>.

       • Add  passwordeval  parameter  to General Section <#general-config>, see issue #108 <https://github.com/
         pimutils/vdirsyncer/issues/108> and  pull  request  #117  <https://github.com/pimutils/vdirsyncer/pull/
         117>.

       • Emit  warnings  (instead of exceptions) about certain invalid responses from the server, see issue #113
         <https://github.com/pimutils/vdirsyncer/issues/113>.  This is  apparently  required  for  compatibility
         with Davmail.

   Version 0.2.5
       released on 27 August 2014

       • Don't  ask for the password of one server more than once and fix multiple concurrency issues, see issue
         #101 <https://github.com/pimutils/vdirsyncer/issues/101>.

       • Better validation of DAV endpoints.

   Version 0.2.4
       released on 18 August 2014

       • Include workaround for collection discovery with latest version of Radicale.

       • Include metadata files such as the changelog or license in source distribution, see issue #97 <https://
         github.com/pimutils/vdirsyncer/issues/97>  and   issue   #98   <https://github.com/pimutils/vdirsyncer/
         issues/98>.

   Version 0.2.3
       released on 11 August 2014

       • Vdirsyncer now has a --version flag, see issue #92 <https://github.com/pimutils/vdirsyncer/issues/92>.

       • Fix  a  lot  of bugs related to special characters in URLs, see issue #49 <https://github.com/pimutils/
         vdirsyncer/issues/49>.

   Version 0.2.2
       released on 04 August 2014

       • Remove a security check that caused problems with special characters in DAV URLs and  certain  servers.
         On  top  of  that,  the  security  check  was nonsensical.  See issue #87 <https://github.com/pimutils/
         vdirsyncer/issues/87> and issue #91 <https://github.com/pimutils/vdirsyncer/issues/91>.

       • Change some errors to warnings, see issue #88 <https://github.com/pimutils/vdirsyncer/issues/88>.

       • Improve collection autodiscovery for servers without full support.

   Version 0.2.1
       released on 05 July 2014

       • Fix bug where vdirsyncer shows empty addressbooks when using CardDAV with Zimbra.

       • Fix infinite loop when password doesn't exist in system keyring.

       • Colorized errors, warnings and debug messages.

       • vdirsyncer now depends on the click package instead of argvard.

   Version 0.2.0
       released on 12 June 2014

       • vdirsyncer now depends on the icalendar package from PyPI, to get rid of its own broken parser.

       • vdirsyncer now also depends on requests_toolbelt. This makes it possible to  guess  the  authentication
         type instead of blankly assuming basic.

       • Fix  a  semi-bug  in  caldav and carddav storages where a tuple (href, etag) instead of the proper etag
         would have been returned from  the  upload  method.   vdirsyncer  might  do  unnecessary  copying  when
         upgrading to this version.

       • Add   the   storage  singlefile  <#storage-singlefile>.  See  issue  #48  <https://github.com/pimutils/
         vdirsyncer/issues/48>.

       • The collections parameter for pair sections now accepts the special  values  from  a  and  from  b  for
         automatically discovering collections.  See Pair Section <#pair-config>.

       • The read_only parameter was added to storage sections. See Storage Section <#storage-config>.

   Version 0.1.5
       released on 14 May 2014

       • Introduced changelogs

       • Many bugfixes

       • Many doc fixes

       • vdirsyncer now doesn't necessarily need UIDs anymore for synchronization.

       • vdirsyncer  now aborts if one collection got completely emptied between synchronizations. See issue #42
         <https://github.com/pimutils/vdirsyncer/issues/42>.

CREDITS AND LICENSE

   Contributors
       In alphabetical order:

       • Ben Boeckel

       • Bleala

       • Christian Geier

       • Clément Mondon

       • Corey Hinshaw

       • Kai Herlemann

       • Hugo Osvaldo Barrera

       • Jason Cox

       • Julian Mehne

       • Malte Kiefer

       • Marek Marczykowski-Górecki

       • Markus Unterwaditzer

       • Michael Adler

       • rEnr3n

       • Thomas Weißschuh

       • Witcher01

       Special thanks goes to:

       • FastMail <https://github.com/pimutils/vdirsyncer/issues/571> sponsors a paid account for testing  their
         servers.

       • Packagecloud <https://packagecloud.io/> provide repositories for vdirsyncer's Debian packages.

   License

DONATIONS

       vdirsyncer  is  and  will always be free and open source software. We appreciate sponsors willing to fund
       our continued work on it.

       If you found my work useful, please consider donating. Thank you!

       • Bitcoin: 13p42uWDL62bNRH3KWA6cSpSgvnHy1fs2E.

       • Sponsor via one-time tips or recurring donations via Ko-fi <https://ko-fi.com/whynothugo>.

       • Sponsor via recurring donations via liberapay <https://liberapay.com/WhyNotHugo/>.

Author

       Markus Unterwaditzer

Copyright

       2014-2025, Markus Unterwaditzer & contributors

0.20                                              Sep 09, 2025                                     VDIRSYNCER(1)