ICS-Termine
Wenn Sie Termine mit Outlook, Teams oder anderen Programmen planen, dann werden im Hintergrund per Mail so genannte ICS-Dateien versendet. Ein Blick hinter die Kulissen und Besonderheiten von Outlook und warum eine Termineinladungen mit BCC-Empfängern beim Empfänger meist die komplette Teilnehmerliste anzeigt.
ICS Format und Felder
As Format der ICS-Dateien ist ein der "RFC5545: Internet Calendaring and Scheduling Core Object Specification (iCalendar)" beschrieben und im Abschnitt 3.6.5 werden die zwingend erforderlichen Felder beschrieben. Die kleinste ICS-Datei hat dabei den folgenden Aufbau:
BEGIN:VCALENDAR VERSION:2.0 PRODID:MSXFAQSample END:VCALENDAR
Damit kommen Sie natürlich nicht wirklich weiter, da keinerlei Information enthalten ist. Ein paar Daten sollten Sie schon addieren, damit Outlook und andere Programme auch einen Termin daraus formen können, z.B.
BEGIN:VCALENDAR VERSION:2.0 PRODID:MSXFAQSample BEGIN:VEVENT UID:1234567@msxfaq.de DTSTAMP:20230207T224510Z DTSTART:20230207T224500Z END:VEVENT END:VCALENDAR
Wenn ich diese Information als ICS-Datei abspeichere und per Doppelklick in Outlook öffne, sehe ich einen neuen Termin mit dem Startdatum, der Standarddauer von 1h und alle Felder sin sind leer. Es ist noch keine Einladung oder Absage. Wenn ich eine Termineinladung von Outlook abfange, dann siehst das schon deutlich umfangreiche aus. Ich habe die Elemente zur Lesbarkeit etwas eingerückt, damit Sie die Blöcke besser erkennen können.
Bei einer realen Datei ist nicht erlaubt, da Feldinhaltkönnen auch über mehrere Zeilen gehen können und die Folgezeile eingerückt wird.
BEGIN:VCALENDAR METHOD:REQUEST PRODID:Microsoft Exchange Server 2010 VERSION:2.0 BEGIN:VTIMEZONE TZID:W. Europe Standard Time BEGIN:STANDARD DTSTART:16010101T030000 TZOFFSETFROM:+0200 TZOFFSETTO:+0100 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:+0100 TZOFFSETTO:+0200 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN="User1 (MSXFAQLAB)":mailto:user1@msfaqlab.onmicrosoft.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=User2 /MSXFAQLBA):mailto:user2@msfaqlab.onmicrosoft.com DESCRIPTION;LANGUAGE=de-DE:MSXFAQ Termintest2023\n UID:uniqueid1 SUMMARY;LANGUAGE=de-DE:TestFC Einladung DTSTART;TZID=W. Europe Standard Time:20230301T090000 DTEND;TZID=W. Europe Standard Time:20230301T092500 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20230209T084405Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=de-DE: END:VEVENT END:VCALENDAR
Wenn Sie eine so eingerückte Datei importieren, dann fragt mich Outlook, ob die die ICS als Kalender öffnen oder importieren soll.
Der Parser von Outlook erkennt diese Datei nicht als einzelnen Termin sondern als Kalender. Ohne Einrückung wird direkt der Termin geöffnet.
In dem Beispiel wird unter "BEGIN:VTIMEZONE" auch die Zeitzone definiert, was für den Termin nur wichtig ist, wenn darauf auch im VEVENT verwiesen wird. Für den Termin interessant it der Block zwischen "BEGIN:VEVENT" und "END:VEVENT"
- RFC 5545 Internet Calendaring and Scheduling Core Object Specification (iCalendar)
https://datatracker.ietf.org/doc/html/rfc5545 - iCalendar
https://en.wikipedia.org/wiki/ICalendar
Um mehr über die ICS-Dateien im Einsatz zu erfahren, habe ich einen Termin mit Outlook erstellt und an ein IMAP4-Postfach gesendet. So kann ich einfach die ICAL-Datei per Thunderbird abrufen, denn Outlook versteckt die Anlage, wenn es einen Termin erkennt. Ich habe zu einem Termin eingeladen, zugesagt, dann aktualisiert und zuletzt wieder abgesagt.
Im Hintergrund hat Outlook verschiedene Mails mit ICS-Anlagen an die Empfänger gesendet, die ich genauer betrachtet habe.
Mail-Header
Bei einer per Mail übertragene Einladung gib es den "Envelope Header" und den "Mail-Header". Der erste Header ist für die Benutzer nicht sichtbar aber enthält die Empfänger, an die der SMTP-Server die Mails zustellen muss. Der Mail-Header sieht der Anwender. BCC Empfänger sind daher im Mail-Header nicht enthalten sondern nur im Envelope Header.
Mit der ICS-Datei als Anlage kommt nun eine dritte Empfängerliste dazu. Im Mail-Header steht klassischerweise nur der Absender, die Empfänger und der Betreff. Die eigentliche Termininformation steckt in einer ICAL-Anlage. Dennoch finden sich im SMTP-Header zwei Felder:
Feld | Einladung | Update | Absage |
---|---|---|---|
x-ms-exchange-calendar-series-instance-id: |
In x-ms-exchange-calendar-series-instance-id steht wohl eine binäre ID, die wohl proprietär für Microsoft ist und bei allen Mails unverändert erhalten blieb. |
||
--boundary.... |
... Content-Type: text/calendar; charset="utf-8"; method=REQUEST |
... Content-Type: text/calendar; charset="utf-8"; method=REQUEST |
... Content-Type: text/calendar; charset="utf-8"; method=CANCEL |
Bei einer Einladung von einem UNIX-System habe ich auch folgende Einbindung als Anlage gesehen.
--_004_212342JavaMailLINUX1_ Content-Type: text/calendar; name="einladung.ics" Content-Description: calendar1.ics Content-Disposition: attachment; filename="einladung.ics"; size=10187; creation-date="Tue, 02 Feb 2022 14:53:17 GMT"; modification-date="Wed, 03 Feb 2022 14:37:08 GMT" Content-ID: <9D0A2AB5DF21EC4F9E5B74F964838CE7@eurprd08.prod.outlook.com> Content-Transfer-Encoding: base64
In dem Fall zeigt Outlook keine Mail mit einer ICS-Anlage zum Anklicken an, sondern wechselt direkt in die Terminanzeige.
Interessant ist dabei, woher Outlook welche Informationen nimmt, da es immer mehrere Quellen gibt:
Feld | Quelle | Quelle |
---|---|---|
Titel der Einladung |
ICS:SUMMARY |
Den Text "TestFC Einladung" übernimmt Outlook aus dem Feld "SUMMARY" der ICS-Datei. Er ignoriert also den "Subject" aus dem SMTP-Header oder andere Quellen |
Body der Einladung |
SMTP:Body |
Diese Information bezieht Outlook nun wieder aus dem Body
der Mail. Die Testmail hatte sowohl einen TEXT als auch einen HTML-Body. Je nach ihren Präferenzen wird einer davon angezeigt. Outlook ignoriert hier die Felder "Description" und "X-ALT-DESC" aus der ICS-Anlage |
Termindaten |
ICS |
Der Start und Ende-Termin u.a. kommt allerdings wieder aus der ICS-Datei. Dafür gibt es ja keine Felder in der Mail sebst |
Maildatum |
SMTP:Date |
Das Datum, wann die Einladung versendet wurde, kommt aus dem "Date"-Feld des SMTP-Headers |
In den meisten Fällen senden Client heute heute eine Multipart-Mime-Message mit einer Text-Version, einer HTML-Version und der eigentlichen ICS-Datei. In der Multipart Mime-Boundary ist bei der "Method" aber auch schon ein Unterschied bei der Absage zu sehen.
ICS-Felder
Interessanter ist dann die ICAL-Anlage, die ich aus der Mail mittels BASE64-Decodierung extrahier habe. Ich geben hier nur die Abschnitte wieder, die mir wichtig erscheinen und sich unterscheiden
Feld | Einladung | Update | Absage |
---|---|---|---|
METHOD |
REQUEST |
REQUEST |
CANCEL |
PRIORITY |
5 |
5 |
1 |
DTSTAMP |
20230209T084405Z |
20230209T084423Z |
20230209T084441Z |
SEQUENCE |
0 |
1 |
2 |
X-MICROSOFT-CDO-APPT-SEQUENCE X-MICROSOFT-CDO-OWNERAPPTID X-MICROSOFT-CDO-BUSYSTATUS X-MICROSOFT-CDO-INTENDEDSTATUS X-MICROSOFT-CDO-ALLDAYEVENT X-MICROSOFT-CDO-IMPORTANCE X-MICROSOFT-CDO-INSTTYPE X-MICROSOFT-DONOTFORWARDMEETING X-MICROSOFT-DISALLOW-COUNTER X-MICROSOFT-LOCATIONS |
0 -989255705 TENTATIVE BUSY FALSE 1 0 FALSE FALSE [] |
1 -989255705 TENTATIVE BUSY FALSE 1 0 FALSE FALSE [] |
2 -989255705 FREE FREE FALSE 2 0 FALSE FALSE <leer> |
BEGIN:VALARM DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M ACTION:DISPLAY END:VALARM |
VALARM REMINDER -PT15M DISPLAY VALARM |
VALARM REMINDER -PT15M DISPLAY VALARM |
<leer> <leer> <leer> <leer> <leer> |
Der Unterschied zwischen einer erste Einladung und einem Update ist minimal. Eigentlich hat sich nur die "SEQUENCE" geändert. Erst bei einer Absage wird neben der SEQUENCE auch noch die METHOD und die PRIORITY geändert. Zusätzlich ändern sich noch ein paar Microsoft-spezifischen Felder.
Die PRIORITY muss ein Wert zwischen 0 und 9 annehmen und anscheinend möchte Outlook mit einer "1" die höchstmögliche Priorität vorgeben. Die SEQUENCE-Nummer beginnt bei 0 muss mit jedem Update hochgezählt werden.
- RFC 5545 Internet Calendaring and Scheduling Core Object Specification (iCalendar)
https://datatracker.ietf.org/doc/html/rfc5545 - 3.8.7.4. Sequence Number
https://icalendar.org/iCalendar-RFC-5545/3-8-7-4-sequence-number.html - 3.8.1.9. Priority
https://icalendar.org/iCalendar-RFC-5545/3-8-1-9-priority.html - 5.3. UID Property
https://icalendar.org/New-Properties-for-iCalendar-RFC-7986/5-3-uid-property.html
Feld: SEQUENCE
Wenn es manchmal hektisch zugeht, dann wird ein Termin mehrfach aktualisiert und da die Einladungen als Mails versendet werden, kann die Übertragung schon einmal unterschiedliche Wege nehmen und damit die Reihenfolge der Ankunft nicht mehr passt. Damit hier nicht ein älterer aber später eintreffende Termininformation eine schon verarbeitete jüngere Information überschreibt, muss eine "SEQUENCE" Nummer immer wieder hochgezählt werden. Sie beginnt in der Regel bei "0" und wird mit jedem Update erhöht.
Der Anwender sieht dies auch, wenn eine solche veraltete Aktualisierung im Postfach erscheint und Outlook verarbeitet diese nicht.
Wie immer gibt es aber auch hier eine Ausnahme. Bei einem CANCEL akzeptiert Outlook auch die gleiche SEQUENCE-Nummer aber sie darf nicht niedriger sein.
Feld: METHOD:CANCEL
Bei der Absage eines Termins durch die Methode "CANCEL" gibt es ebenfalls ein paar Dinge zu beachten:
- Sequence-Nummer gleich oder höher als die vorherigen Updates
Dies weicht von den anderen REQUEST-Optionen ab. - UID muss übereinstimmen
Sonst kann Outlook nicht den passenden Eintrag finden. Es versteht sich von selbst, dass Sie möglichst eindeutige UIDs pro Termin generieren müssen. Wenn Sie mehrere Termine mit der gleichen UID haben, weil Sie z.B. fälschlicherweise mehrere PUBLISH-Einladungen angenommen haben, dann können diese mit mehreren CANCEL-Absagen natürlich nacheinander gelöscht werden. - Immer nur ein Termin
Ein Cancel entfernt bei Zustimmung des Benutzers immer nur einen Termin. Wenn Sie z.B. zwei Elemente mit der gleichen UID per PUBLISH eingetragen haben, dann wird nur der erste gefundene Eintrag entfernt. Mehrfache "CANCEL"-Meldungen räumen dann immer einen weiteren Termin weg. - Outlook markiert zur Löschung beim Öffnen
Sobald Sie die CANCEL-Nachricht öffnen, wird der Termin im Kalender schon "weiss" gekennzeichnet aber noch nicht gelöscht
Wenn Sie die Mail mit der Absage ohne weitere Aktion schließen, dann bleibt der Termin in dem "Abgesagt"-Status aber weiter im Kalender stehen. - Outlook löscht schon beim Druck auf den Button
Wenn Sie in der Absage aber oben auf den Button drücken, dann wird der Termin im Kalender ohne weitere Rückfrage entfernt. Es kommt zwar noch eine Rückfragen, aber die bezieht sich auf die Löschung der Absagemail selbst.
- Absage ohne Termin
Wenn Sie eine Absage für einen Termin bekommen, den Sie schon lange selbst gelöscht haben, dann zeigt Outlook dennoch die Absage ohne weitere Hinweise an. Bestätigen Sie die Absage einfach, damit die Mail gelöscht wird.
Achtung:
Outlook prüft bei einer Absage nur die UID und die korrekte
SEQUENCE. Wenn ich z.B. über einen Trojaner oder schlechten
Code die UID eines Termins erraten oder ermitteln kann,
reicht eine Mail mit einer entsprechend präparierten
ICS-Datei, um den Termin im Kalender zu löschen.
ICS:METHOD
Wie ein Client mit den Daten umgehen soll, wird über das Feld "METHOD" definiert. Die eigentliche RFC5545 definiert dazu keine Werte.
No methods are defined by this specification. This is the subject of other
specifications, such as the iCalendar Transport- independent Interoperability
Protocol (iTIP) defined by [2446bis].
https://www.rfc-editor.org/rfc/rfc5545#section-2.1
Stattdessen wird auf "2446bis iCalendar Transport-Independent Interoperability Protocol (iTIP)", Work in Progress, April 2009" verwiesen, die im Dezember 2009 zur RFC 5546 geworden ist.
- RFC5546 iCalendar Transport-Independent Interoperability Protocol (iTIP)
https://datatracker.ietf.org/doc/rfc5546/ - iCalendar Transport-Independent Interoperability Protocol (iTIP)
draft-ietf-calsify-2446bis-10
https://datatracker.ietf.org/doc/draft-ietf-calsify-2446bis/10/
Am geläufigsten sind die folgenden Metehoden:
Methode | Beschreibung |
---|---|
REQUEST |
Das ist die normale Methode um einen Termin anzufragen. Die RFC 5545 schreibt dazu: "REQUEST" refers to the method for
requesting a scheduling calendar component be created or
modified Der Anwender bekommt den Termin mit seinem Kalender angezeigt, um die Vereinbarkeit zu prüfen und darauf zu reagieren.
Auch Updates von Terminen sind immer wieder ein Request mit der gleichen UID und höheren SEQUENCE. |
CANCEL |
Mit diesem Verb kann der Organisator einen früher versendeten Termin wieder absagen. Er muss nur die UID und eine gleiche oder höhere SEQUENCE mitliefern. |
PUBLISH |
Ein PUBLISH wird normal verwendet, wenn Sie ein oder mehrere Termine in einer ICS-Datei als Kalender-Feed bereitstellen. Outlook und andere System können so einen Datenquelle z:B. per HTTPS abonnieren und einbinden. Sie können aber auch eine ICS-Datei per Mail als Einladung mit der METHOD=PUBLISH versenden. Das ist aber nicht sehr freundlich, denn der Anwender bekommt dann den Termin ohne die Kalendervorschau angezeigt:
Zudem ignoriert Outlook die SEQUENCE-Nummern und UIDs, so dass Termine immer wieder neu angelegt werden. Ein "Update" einer früheren Einladung ist nicht möglich, es sei denn ich sende vorher ein "CANCEL" zum Entfernen des vorherigen Termins. Verwenden Sie daher PUBLISH besser nicht mit einem per Mail versendeten Termin. |
REPLY |
Analog dazu kann der Anwender dann auf einen Termin mit einer Zusage antworten, indem er eine ICS-Datei zurücksendet. Dazu ist es natürlich erforderlich, dass die ICS-Datei die Teilnehmer auch dazu auffordert, z.B. durch einen Eintrag wie: ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=user1:mailto:user1@msxfaq.de |
Die RFC 5545 selbst dokumentiert keine Methoden:
No methods are defined by this specification. This is the subject of other
specifications, such as the iCalendar Transport- independent Interoperability
Protocol (iTIP) defined by [2446bis].
https://www.rfc-editor.org/rfc/rfc5545#section-2.1
Stattdessen wird auf "2446bis iCalendar Transport-Independent Interoperability Protocol (iTIP)", Work in Progress, April 2009" verwiesen, die im Dezember 2009 zur RFC 5546 geworden ist
- RFC5546 iCalendar Transport-Independent Interoperability Protocol (iTIP)
https://datatracker.ietf.org/doc/rfc5546/ - iCalendar Transport-Independent Interoperability Protocol (iTIP)
draft-ietf-calsify-2446bis-10
https://datatracker.ietf.org/doc/draft-ietf-calsify-2446bis/10/
Outlook Testserie
Natürlich habe ich Outlook etwas gestresst, indem ich eine ICS bzw. EML-Datei immer wieder etwas angepasst und an Outlook übergeben habe. Hier ein paar Testergebnisse:
- Erneute Einladung mit anderem Text aber
gleicher UID/SEQUENCENUMBER
Kein Update. Outlook erkennt den bestehenden Termin aber aktualisiert ihn nicht - Erneute Einladung mit anderem
DESCRIPTION aber gleicher UID/SEQUENCENUMBER
Kein Update. Outlook erkennt den bestehenden Termin aber aktualisiert ihn nicht - Erneute Einladung mit anderem SUMMARY
aber gleicher UID/SEQUENCENUMBER
Kein Update. Outlook zeigt den Termin mit geändertem Betreff an, erkennt den bestehenden Termin aber aktualisiert ihn nicht - Erneute Einladung mit X-ALT-DESC aber
gleicher UID/SEQUENCENUMBER
Kein Update. Outlook zeigt den Termin mit geändertem Betreff an, erkennt den bestehenden Termin aber aktualisiert ihn nicht - Erneute Einladung mit geändertem
X-ALT-DESC, gleicher UID und
SEQUENCENUMBER+1
Termin wird aktualisiert - Beliebige Änderungen mit SEQUENCENUMBER
<= höchste verarbeitete Nummer
Das Element wird angezeigt aber nicht übernommen. - Änderung von DTSTAMP
Hat keine Auswirkungen. - ICS-Datei mit mehreren VEVENT-Einträgen
per Doppelklick importieren
Es wird immer nur der erste Eintrag importiert - ICS-Datei mit mehreren VEVENT-Einträgen
per "Datei - Import" importieren
Es werden alle VEVENT-Einträge in den Kalender importiert. Bestehende Termine werden anhand der UID gefunden und aktualisiert, wenn DTSTAMP neuer und die SEQUENCE nicht niedriger ist.
Outlook orientiert sich also wie erwartet an der UID zum Wiedererkennen des Termins und übernimmt nur Elemente mit einer höheren SEQUENCE-Nummer. Der Titel des Termins wird aus dem Feld "SUMMARY" übernommen. Beim Import einer ICS-Datei wird der Inhalt von "DESCRIPTION" nur dann in Outlook sichtbar, wenn eine X-ALT-DESC nicht gepflegt ist. Beide Felder werden aber ignoriert, wenn die Einladung als Mail zugestellt wird.
Teams in ICS
Eine Besonderheit sind natürlich Termine in Verbindung mit Microsoft Teams. Natürlich werden die für das Team-Meeting erforderlichen Zugangsdaten sowohl in die TEXT als auch HTML-Body der Mail eingetragen, so dass der Empfänger selbst ohne ICS-kompatiblen Client das Meeting verstehen und beitreten kann. Hier am Beispiel von Thunderbird, der gut die SMTP-Body-Version anzeigt:
Zusätzlich finden wir aber auch im SMTP-Header der Einladung die Links zum Teams-Meeting.
-MICROSOFT-SKYPETEAMSMEETINGURL:https://teams.microsoft.com/l/meetup-join/ 19%3ameeting_xxxx%40thread.v2/0?context=%7b%22Tid%22%3a%22<tenantid>%22%2c%22Oid%22%3a%22<meetingid>0186effe82c%22%7d X-MICROSOFT-SCHEDULINGSERVICEUPDATEURL:https://api.scheduler.teams.microsof t.com/teams/<tenantid>/<meetingid>/19_meeting_<session>@thread.v2/0 X-MICROSOFT-SKYPETEAMSPROPERTIES:{"cid":"19:<session>@thread.v2"\,"private":true\,"type":0\,"mid":0\," rid":0\,"uid":null} X-MICROSOFT-ONLINEMEETINGCONFLINK:conf:sip:frank.carius@netatwork.de\;gruu\ ;opaque=app:conf:focus:id:teams:2:0!19:meeting_xxxxxxx-thread.v2!xxxxxxxxxxxxx
Irgendwie komisch, dass hier noch der Name "Skype" statt Teams oder SkypeforBusiness auftaucht. Aber vielleicht gibt es doch das ein oder andere Programm, welches genau diese Header auswertet, um dem Anwender den Beitritt ins Meeting zu vereinfachen.
Teilnehmer verbergen
Sie haben nun gelernt, dass die Empfänger einer Einladung und die Teilnehmer in der ICS-Einladung selbst zwei unterschiedliche Listen sind. Die Empfänger der Mail können Sie recht einfach mit "BCC" verbergen, so dass die Teilnehmer nicht wissen, wer noch die Einladung bekommen hat. Die Teilnehmer in der ICS-Datei sind damit aber dennoch weiterhin bei allen Empfängern sichtbar. Dies kann aber zumindest in Outlook for the Web gesteuert werden. Hier gibt es einen Punkte "Teilnehmer verbergen":
Damit kann ich in der ICS-Datei die Teilnehmerliste ausblenden, dass kein Empfänger diese mehr sieht. In der ICS-Datei gibt es dann keine "ATTENDEE"-Felder mehr sondern nur noch der ORGANIZER" ist sichtbar. Leider ist diese Funktion wohl in Teams, Outlook und anderen Clients nicht verfügbar.
- Teilnehmer unsichtbar schalten
https://answers.microsoft.com/de-de/msteams/forum/all/teilnehmer-unsichtbar-schalten/99252076-3f32-497e-b712-71ff049b10a4 - Hide Meeting Attendees in Outlook
https://web.archive.org/web/20200813070035/https:/mattdrobysh.com/hide-meeting-attendees-in-outlook/
Zusammenfassung
ICS-Dateien und deren Spezifikation in der RFC5545 und RFC5546 beschreiben sehr gut die Funktion und Definition. Für Anwender ist es aber erst einmal ungewöhnlich, wenn ich eine Termineinladung an mehrere Personen per Mail sende und in der ICS-Anlage eine andere Teilnehmergruppe adressiert ist. Für Outlook und Exchange ist die Mail und deren Empfänger nur das Transportmittel der Einladung aber nicht mit den Teilnehmern identisch. Alle Funktionen einer Mai, inklusive der Versand per "BCC" funktioniert nicht, da in der ICS-Datei die Teilnehmer aufgeführt werden. Das mag überraschen aber ist eigentlich auch logisch.
Weitere Links
- Envelope und Header
- SMTP-Header
- SMTP P1/P2-Felder
- TerminFAQ
- RFC5545 Internet Calendaring and Scheduling Core Object Specification (iCalendar)
https://datatracker.ietf.org/doc/html/rfc5545 - RFC5546 iCalendar Transport-Independent Interoperability Protocol (iTIP)
https://datatracker.ietf.org/doc/rfc5546/ - iCalendar
https://en.wikipedia.org/wiki/ICalendar - iCalendar – Das iCal-Format im Überblick
https://www.ionos.de/digitalguide/websites/web-entwicklung/icalendar/ - The long tail of the iCalendar ecosystem
https://blog.jonudell.net/2011/09/30/the-long-tail-of-the-icalendar-ecosystem/