<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Calendars, contacts, the directory and shared address books over CalDAV and CardDAV]]></title><description><![CDATA[<p dir="auto"><em>Written for 6.3.4. hMailServer 6.3.8 (2 November 2026) has the web services listener, which serves CalDAV and CardDAV, refuse an address an auto-ban or an IP range bans: it closes the connection with no answer, before the TLS handshake, when the IP range that decides for the address allows none of SMTP, POP3 and IMAP, where up to 6.3.7 a banned address could go on guessing passwords there. So an IP range of your own that allows some addresses nothing now closes CalDAV and CardDAV to them as well: check that these services' clients do not come from one. Loopback and the addresses in <code>WebServicesTrustedProxies</code> are never refused by a range, and a failed sign-in from one of them is counted against the name alone (<code>AccountLockoutThreshold</code>, off by default), never towards a ban of that address. A client that signs in with another spelling of the account's address than the stored one, in more than the case of the letters A to Z, or with white space at either end, may no longer sign in. See <a href="/topic/28278">the 6.3.8 announcement</a>.</em></p>
<p dir="auto">This topic covers what hMailServer 6.3.4 serves to a phone or a desktop client over CalDAV and CardDAV, and what the webmail's Calendar, Tasks, Contacts and Directory pages do with the same data. The one thing to know first: CalDAV and CardDAV are served on the <strong>web-services listener</strong>, they take HTTP Basic as the account - its password or an app password - over HTTPS only, and a passkey or single sign-on does not reach them. CardDAV has been there since 6.3.3 with one address book; calendars, several and shared address books, the directory and rooms are all since 6.3.4.</p>
<h3><a class="anchor-offset" name="setting-up-a-phone-or-a-desktop-client"></a>Setting up a phone or a desktop client</h3>
<p dir="auto">A client given the mail address finds the server by discovery: <code>/.well-known/carddav</code> and <code>/.well-known/caldav</code> redirect to <code>/dav/</code>, a PROPFIND there answers the principal, and the principal answers the address-book home and the calendar home. iOS, macOS Contacts and Calendar, DAVx5 on Android and Thunderbird all sync what is there. The IMAP logon's <a href="/topic/28239">lockout and auto-ban</a> apply to the sign-in.</p>
<p dir="auto"><strong>Which password.</strong> An account with a TOTP second factor enrolled uses an app password, because once a secret exists the account password stops being a mailbox credential. Minting an app password on the webmail's Security page asks for the account's own password again, so an account that single sign-on or SCIM made, whose random password nobody was told, needs a password set by an administrator before its person can make an app password for a phone.</p>
<p dir="auto"><strong>The listener.</strong> The web services are off as shipped: <code>WebServicesHttpPort</code> and <code>WebServicesHttpsPort</code> default to <code>0</code>, and the HTTPS port takes <code>WebServicesCertificateFile</code> and <code>WebServicesPrivateKeyFile</code>. Since 6.3.4 these keys are <a href="/topic/28222">kept in the database</a>: change them in the Control Panel (Windows), over REST, or on Linux with <code>hmailserver --set-setting NAME=VALUE</code>, not by editing <code>hMailServer.ini</code>. A saved port or certificate waits for a reinitialise or a restart, since the listener binds when it starts.</p>
<p dir="auto"><strong>On the Devices list</strong> a DAV client appears with the protocol <code>dav</code> and its user agent. It has no connection to drop - each request authenticates afresh - so revoking it means revoking the app password behind it.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Collection</th>
<th>What it is</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/dav/calendars/&lt;address&gt;/calendar/</code></td>
<td>The default calendar, <code>Calendar</code>, made the first time it is asked for</td>
</tr>
<tr>
<td><code>/dav/calendars/&lt;address&gt;/&lt;name&gt;/</code></td>
<td>Another calendar of the account's own, made in the webmail or with <code>MKCALENDAR</code></td>
</tr>
<tr>
<td><code>/dav/calendars/&lt;address&gt;/shared-&lt;id&gt;/</code></td>
<td>A calendar another account, or a group, shares with this one</td>
</tr>
<tr>
<td><code>/dav/addressbooks/&lt;address&gt;/contacts/</code></td>
<td>The default address book, where a client that has synced since 6.3.3 still finds it</td>
</tr>
<tr>
<td><code>/dav/addressbooks/&lt;address&gt;/book-&lt;id&gt;/</code></td>
<td>Another book of the account's own (schema 6079)</td>
</tr>
<tr>
<td><code>/dav/addressbooks/&lt;address&gt;/shared-&lt;id&gt;/</code></td>
<td>A book shared with this account, or with the whole domain</td>
</tr>
<tr>
<td><code>/dav/addressbooks/&lt;address&gt;/directory/</code></td>
<td>The organisation's directory, read-only (schema 6078)</td>
</tr>
</tbody>
</table>
<p dir="auto">Each calendar collection advertises <code>VEVENT</code> and <code>VTODO</code>, so a phone's calendar and its reminders list are the same collection.</p>
<h3><a class="anchor-offset" name="calendars-events-and-tasks"></a>Calendars, events and tasks</h3>
<p dir="auto">An account has one calendar until it makes more. The Calendars box beside the grid adds one with a name and a colour (<code>POST /api/v1/me/calendars</code>), renames or recolours it and deletes it with its events; the default cannot be deleted. Over CalDAV the colour travels as Apple's <code>calendar-color</code>, so a phone shows the same one, and <code>PROPPATCH</code> sets the name and colour from the phone's side.</p>
<p dir="auto"><strong>Events.</strong> An event takes a title, <code>start</code> and <code>end</code> as wall-clock times in <code>tz</code> (an IANA zone the server knows), <code>all_day</code>, a location and notes, <code>rrule</code> (daily, weekly on chosen days, monthly, yearly, with an interval and an end by count or by date), <code>alarm_minutes</code> and guests. The server writes <code>DTSTART;TZID=&lt;zone&gt;</code> so a weekly 09:00 stays 09:00 across a clock change, and a <code>VALARM</code> for the reminder, which is what CalDAV clients ring for. A repeating event is expanded across daylight saving in any of the 592 zone names the server knows; <code>calendar-query</code> with a time range, <code>calendar-multiget</code> and <code>sync-collection</code> are all answered, with ETags and <code>If-Match</code>. Changing one occurrence alone writes an override; deleting one writes an <code>EXDATE</code> on the master.</p>
<p dir="auto"><strong>Tasks.</strong> The Tasks page lists every <code>VTODO</code> of every calendar the account can see, soonest due first. Ticking one off writes <code>STATUS:COMPLETED</code>, <code>COMPLETED</code> and <code>PERCENT-COMPLETE:100</code> as a client does. A second calendar is a task list of its own.</p>
<h3><a class="anchor-offset" name="sharing-a-calendar-and-delegates"></a>Sharing a calendar, and delegates</h3>
<p dir="auto">The owner names another account of this server and whether it may write (<code>PUT /api/v1/me/calendars/{id}/shares/{address}</code> with <code>write</code>). The other account sees the calendar in its own Calendars box and in its CalDAV home as <code>shared-{id}/</code>, with <code>owner</code> pointing at the sharer's principal and a <code>current-user-privilege-set</code> of read, or read and write. A read-only share takes no PUT, no event from the page and no PROPPATCH. The sharee leaves with a CalDAV DELETE of <code>shared-{id}/</code> or from the page.</p>
<p dir="auto"><strong>Shared with a group.</strong> Since schema 6086 the name may be one of the server's groups (<code>hm_groups</code>) instead of an address; a name that is both is the account. The membership is read at the moment a member asks, so somebody added later sees the calendar and somebody removed no longer does. A member cannot leave a group share (403): they leave the group, or the owner takes the share back by the group's name.</p>
<p dir="auto"><strong>A delegate.</strong> A share may be a delegation (<code>delegate: true</code>, which implies <code>write</code><img src="https://www.hmailserver.co.uk/assets/plugins/nodebb-plugin-emoji/emoji/android/1f61e.png?v=6eecd33477c" class="not-responsive emoji emoji-android emoji--disappointed" style="height:23px;width:auto;vertical-align:middle" title="):" alt="😞" /> the sharee may answer the owner's invitations on the owner's behalf. The answer is <code>POST /api/v1/me/calendar/events/{id}/reply</code> with <code>partstat</code> <code>ACCEPTED</code>, <code>TENTATIVE</code> or <code>DECLINED</code>, allowed to the owner and to a delegate and refused (403) to a plain writer or a reader. The organiser receives a <code>METHOD:REPLY</code> whose <code>ATTENDEE</code> carries <code>SENT-BY="mailto:&lt;delegate&gt;"</code>, <code>From:</code> the owner with <code>Sender:</code> the delegate.</p>
<h3><a class="anchor-offset" name="free-busy"></a>Free-busy</h3>
<p dir="auto">An account of the domain can see when a colleague is busy, and nothing else about them. <code>GET /api/v1/me/freebusy?address=&lt;account&gt;&amp;from=&lt;when&gt;&amp;to=&lt;when&gt;</code> answers the busy periods of that account's own calendars - not the ones shared with it - over a window of at most 62 days (400 beyond). An event that is <code>TRANSP:TRANSPARENT</code> or <code>STATUS:CANCELLED</code>, or that the account declined, is left out; a period is <code>tentative</code> when the account's <code>PARTSTAT</code> is <code>TENTATIVE</code> or <code>NEEDS-ACTION</code>, else <code>busy</code>. No title, location or description is answered. Another hosted domain's account, an address nobody has, an inactive account, and an account whose <code>freebusy</code> preference is <code>nobody</code> are one and the same 404, so the route enumerates nothing. The preference is the person's own, in Settings: "Who may see when you are busy".</p>
<p dir="auto">Over CalDAV the same computation answers the <code>free-busy-query</code> REPORT on a calendar the caller may read, as one bare <code>VFREEBUSY</code>, over a <code>time-range</code> that needs both bounds and spans at most 62 days. The webmail's event editor draws an availability strip for the guests of a meeting from the same computation.</p>
<h3><a class="anchor-offset" name="invitations-by-mail-imip"></a>Invitations by mail (iMIP)</h3>
<p dir="auto">An event with guests, saved with "Send invitations by e-mail", mails each guest the event as a <code>text/calendar</code> part with <code>method=REQUEST</code> (RFC 6047) - what Outlook, Gmail and Apple Mail show as an invitation card. Saving a change mails an update with the sequence stepped; deleting the event mails <code>METHOD:CANCEL</code>. A message that carries a <code>text/calendar</code> part or an <code>.ics</code> attachment shows a card with Accept, Maybe, Decline and "Propose a new time" (<code>METHOD:COUNTER</code>).</p>
<p dir="auto"><strong>Filed on delivery.</strong> A <code>METHOD:REQUEST</code> delivered to an account is filed into its default calendar as it arrived (<code>NEEDS-ACTION</code> as a rule) when, and only when, it names the account as an <code>ATTENDEE</code> and not as the organiser. A message flagged as spam files nothing; a <code>REQUEST</code> naming somebody else is not kept; and an account that has never opened a calendar gets nothing filed. A stored copy under the same UID is replaced only by the same or a later <code>SEQUENCE</code>, and never when its <code>ORGANIZER</code> is not the invitation's. A <code>REPLY</code> delivered to the organiser sets that attendee's <code>PARTSTAT</code> in the stored event, so every phone syncing the calendar shows who accepted without anyone opening the mail; a <code>CANCEL</code> delivered to a guest marks the stored copy cancelled.</p>
<h3><a class="anchor-offset" name="rooms-and-equipment-since-6.3.4"></a>Rooms and equipment (since 6.3.4)</h3>
<p dir="auto">A room or a projector is an <strong>account whose kind says so</strong>: <code>person</code> (the default), <code>room</code> or <code>equipment</code>, a column of <code>hm_accounts</code> (schema 6101). It is invited like any guest and answers by itself, from its own address, by its booking policy; what it does not decide it leaves to its <strong>delegates</strong>.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Where</th>
<th>What</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Control Deck</td>
<td>The account editor's <strong>General</strong> group has a select of the three kinds; a room or equipment gets a <strong>Booking policy</strong> card</td>
</tr>
<tr>
<td>REST</td>
<td><code>kind</code> on <code>GET</code> and <code>PUT /api/v1/accounts/{address}</code>; the policy at <code>GET</code> and <code>PUT /api/v1/accounts/{address}/booking-policy</code></td>
</tr>
<tr>
<td>COM (Windows)</td>
<td><code>Account.Kind</code> (0 person, 1 room, 2 equipment), saved by <code>Save()</code>; the booking policy is not on COM</td>
</tr>
<tr>
<td>The Windows Control Panel</td>
<td>Does not show it: a room is an ordinary account to it</td>
</tr>
</tbody>
</table>
<p dir="auto">From the moment its kind is saved every sign-in as the room is refused, whatever the credential, with the ordinary wrong-password answer. A room with no policy row answers by the defaults:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Field</th>
<th>Default</th>
<th>What it decides</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>auto_accept</code></td>
<td><code>true</code></td>
<td>Answer invitations by this policy; <code>false</code> leaves every one for the delegates</td>
</tr>
<tr>
<td><code>window_days</code></td>
<td>180</td>
<td>How many days ahead a booking may start, 1 to 1080</td>
</tr>
<tr>
<td><code>max_duration_minutes</code></td>
<td>1440</td>
<td>The longest booking; 0 is no limit</td>
</tr>
<tr>
<td><code>working_hours_only</code></td>
<td><code>false</code></td>
<td>Only inside the working hours, on the working days</td>
</tr>
<tr>
<td><code>work_days</code>, <code>work_start</code>, <code>work_end</code></td>
<td>Monday to Friday, 08:00 to 17:00</td>
<td>The working days and hours</td>
</tr>
<tr>
<td><code>time_zone</code></td>
<td>UTC</td>
<td>The zone the working hours are in, such as <code>Europe/London</code></td>
</tr>
<tr>
<td><code>allow_conflicts</code></td>
<td><code>false</code></td>
<td>Accept a booking over another one</td>
</tr>
<tr>
<td><code>allow_recurring</code></td>
<td><code>true</code></td>
<td>Accept a recurring meeting</td>
</tr>
<tr>
<td><code>bookers</code></td>
<td>empty</td>
<td>Empty is everyone in this server's own domains; a list is an address, <code>@domain</code>, a distribution list's address or a group's name. An organiser from outside must be named here</td>
</tr>
<tr>
<td><code>capacity</code></td>
<td>0</td>
<td>How many people the room seats, shown in the directory; it decides nothing</td>
</tr>
<tr>
<td><code>delegates</code></td>
<td>none</td>
<td>Addresses and group names, each given a delegate share of the room's calendar</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Who is asking.</strong> The room first decides whether the invitation's <code>ORGANIZER</code> is who sent it, from what the server recorded when the message arrived and never from a <code>From:</code> header or a <code>MAIL FROM</code>. An organiser at this server's own domains is believed only when the message was submitted by a signed-in session as that account, or as one allowed to send as it; a message sent through an API key is not believed. An organiser from outside is believed only when <code>bookers</code> names the address or its <code>@domain</code> <strong>and</strong> the message passed DMARC for that domain. SPF on its own is not enough, and with DMARC off no outside organiser is ever believed. Anything else is neither filed nor answered, and the delegates are told, within limits.</p>
<p dir="auto"><strong>The answer</strong> is decided just after delivery, on a work queue of the rooms' own; no delivery and no SMTP answer waits for it. In order: who is asking; may they book; sent automatically (an empty reverse path or <code>Auto-Submitted</code>, never answered); <code>auto_accept</code>; at most 20 answers an hour to one organiser; recurrence; the window; the longest booking; working hours; conflicts, counting every booking the room holds that is not cancelled as busy. Accepted, the booking is filed and a <code>METHOD:REPLY</code> goes from the room's address, marked <code>Auto-Submitted: auto-replied</code>. Declined, the reply carries the reason alone; a conflict says when, never whose. A request left for the delegates is never put into the room's calendar on the sender's word. <strong>A room with no delegates keeps what it leaves and tells nobody</strong>: name at least one. Two servers sharing one database are not serialised for rooms: run rooms on one node.</p>
<p dir="auto"><strong>Finding a room.</strong> The directory lists a room with its kind and <code>capacity</code>, and its CardDAV card says <code>KIND:location</code> (<code>KIND:device</code> for equipment). Every CalDAV principal says its <code>calendar-user-type</code> - <code>INDIVIDUAL</code>, <code>ROOM</code> or <code>RESOURCE</code> - and the <code>principal-property-search</code> REPORT on <code>/dav/principals/</code>, which is what a client's room finder sends, answers the domain's rooms and equipment. Apple Calendar searches for locations this way; Thunderbird has no room finder. Every request stays in the room's mailbox, and a full mailbox answers nothing more, so give a room a quota and a <code>MessageRetentionDays</code> that suit it.</p>
<h3><a class="anchor-offset" name="contacts-groups-and-several-address-books"></a>Contacts, groups and several address books</h3>
<p dir="auto"><strong>Kept, and other contacts.</strong> A contact has a <code>source</code>: <code>manual</code> for what the person added, imported or kept, and <code>collected</code> for every address the person has written to - from the webmail's send and, since 6.3.4, from a mail client over an authenticated SMTP submission. A collected address is offered under <strong>Other contacts</strong> and by the To, Cc and Bcc completion, and nowhere else: CardDAV serves only what the person kept, so a phone's address book is not filled with everyone ever written to. <strong>Keep</strong> makes it a contact.</p>
<p dir="auto"><strong>What a card carries.</strong> A card a CardDAV client sends is kept as sent and served back byte for byte. The page reads <code>birthday</code> (<code>BDAY</code>), <code>note</code>, <code>phones</code> (every <code>TEL</code>) and the embedded <code>PHOTO</code>; a photo that is only a URL is not the server's to fetch.</p>
<p dir="auto"><strong>Groups.</strong> A group is a card of kind group - <code>KIND:group</code> in vCard 4.0, <code>X-ADDRESSBOOKSERVER-KIND:group</code> in 3.0 - so a group made on the phone appears in the webmail and the reverse. A group's name in To becomes that group's recipients, so the reader sees the people and not the group. The ceilings hold on both surfaces: 500 members in one group (a card past it is refused <code>403 CARDDAV:valid-address-data</code>) and 200 groups in one address book (400 over REST, <code>507 Insufficient Storage</code> over CardDAV). A group is not a distribution list: nothing about it reaches SMTP.</p>
<p dir="auto"><strong>Several address books, and shared ones.</strong> Since schema 6079 the account starts with one book, <code>Contacts</code>, which cannot be deleted, and may have at most 50. The owner shares one from the Contacts page with an address - one account of this server - or with its own domain's name; <em>Can edit</em> makes the share writable, and a book takes at most 200 shares. A domain-wide share aimed at another hosted domain is 403, and a person cannot leave a domain share: only the owner or an administrator removes it. One account holds one address once across all its books, so a contact is moved between books, never copied. Over CardDAV a read-only collection grants <code>read</code> and <code>read-current-user-privilege-set</code> and nothing else, a PUT into it is 403, and DELETE on the collection gives the share back and deletes nobody's contacts. <code>MKCOL</code> is refused: a book is made from the Contacts page or <code>/api/v1/me/address-books</code>. No group is shared, in either direction.</p>
<p dir="auto">The backup carries the books and their contacts; <code>hm_addressbookshares</code> is not carried, so the sharing is set again. The Control Panel and the Control Deck have no page for this. An administrator has <code>GET /api/v1/accounts/{address}/address-books</code>, which shows the shape of the sharing and never the contacts, and a route that removes one share, recorded as <code>address-book-share-removed</code>.</p>
<p dir="auto"><strong>Import and export.</strong> The Contacts page imports a vCard file or a CSV, including Google's and Outlook's exports. <em>Export as vCard</em> downloads <code>contacts.vcf</code>; <em>Export as CSV</em> downloads <code>contacts.csv</code> and leaves groups out.</p>
<h3><a class="anchor-offset" name="the-organisation-s-directory"></a>The organisation's directory</h3>
<p dir="auto">It is <strong>one domain at a time, and always the reader's own</strong>: every active account of the domain whose owner has not opted out, and every enabled distribution list, with what is set on top in <code>hm_directory</code> (schema 6078) - job title, department, work telephone, mobile, office, a photo (JPEG, PNG or GIF, at most 100 KB decoded, judged by its bytes), and a note that is the administrator's alone.</p>
<p dir="auto"><strong>Two switches</strong>, both rows of <code>hm_settings</code> and both on by default. <code>DirectoryEnabled</code> is whether the directory is answered at all; turn it off on a server whose one domain holds people who are not one organisation. With it off the webmail hides its Directory page and the CardDAV collection stays, empty, so a subscribed phone syncs to nothing rather than failing every poll. <code>DirectoryUserEditable</code> is whether a person may set their own fields. <strong>The opt-out is never what a switch takes away</strong>, and it is not invisibility: mail still arrives and the address still works. An administrator changing somebody's opt-out is on the audit trail as <code>directory-opt-out-changed</code>.</p>
<p dir="auto"><strong>The surfaces.</strong> The webmail's Directory page (<code>#/directory</code>); the To completion, which offers the reader's own contacts first and the directory hits after; <code>GET /api/v1/me/directory?q=&amp;limit=</code> for the person and <code>GET</code> and <code>PUT /api/v1/accounts/{address}/directory</code> for the administrator; a <strong>Directory entry</strong> tab in the Windows Control Panel's account dialog, and the same card in the Control Deck; and the read-only CardDAV collection, where PUT, DELETE and PROPPATCH are refused 403. Nothing is learned from anywhere else: there is no import from Active Directory or LDAP, even on a server that authenticates against one, and no LDAP server for a mail client to search.</p>
<h3><a class="anchor-offset" name="what-it-does-not-do"></a>What it does not do</h3>
<ul>
<li>No RFC 6638 scheduling (no <code>schedule-inbox</code> or <code>schedule-outbox</code>), no free-busy of a calendar on another server, no per-calendar time zone (<code>calendar-timezone</code> is not kept), no partial <code>calendar-data</code>, and no time-range filter on a <code>VALARM</code>.</li>
<li>No ActiveSync and no Exchange Web Services: a phone uses IMAP and SMTP for mail, and CalDAV and CardDAV for the rest.</li>
<li>Calendar shares and address-book shares are not in the backup, so set them again after a restore; the booking policy, the books, their contacts and the directory rows are.</li>
</ul>
<h3><a class="anchor-offset" name="where-to-read-more"></a>Where to read more</h3>
<ul>
<li>Wiki: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Connecting-a-Mail-Client" rel="nofollow ugc">Connecting a Mail Client</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Rooms-and-Equipment" rel="nofollow ugc">Rooms and Equipment</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/The-Webmail" rel="nofollow ugc">The Webmail</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Ports-Reference" rel="nofollow ugc">Ports Reference</a>.</li>
<li>Documents: <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Calendar.md" rel="nofollow ugc">Calendar.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Contacts.md" rel="nofollow ugc">Contacts.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SharedAddressBooks.md" rel="nofollow ugc">SharedAddressBooks.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Directory.md" rel="nofollow ugc">Directory.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/RoomsAndEquipment.md" rel="nofollow ugc">RoomsAndEquipment.md</a>.</li>
<li>On this forum: <a href="/topic/28191">The webmail portal at /portal</a>, <a href="/topic/28192">The Control Deck</a>, <a href="/topic/28253">Signing in</a>, <a href="/topic/28255">Connecting a mail client</a>, and the <a href="/topic/28218">6.3.4 announcement</a>.</li>
</ul>
]]></description><link>https://www.hmailserver.co.uk/topic/28252/calendars-contacts-the-directory-and-shared-address-books-over-caldav-and-carddav</link><generator>RSS for Node</generator><lastBuildDate>Fri, 06 Nov 2026 09:05:50 GMT</lastBuildDate><atom:link href="https://www.hmailserver.co.uk/topic/28252.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 19:34:13 GMT</pubDate><ttl>60</ttl></channel></rss>