Calendars, contacts, the directory and shared address books over CalDAV and CardDAV
-
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
WebServicesTrustedProxiesare never refused by a range, and a failed sign-in from one of them is counted against the name alone (AccountLockoutThreshold, 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 the 6.3.8 announcement.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 web-services listener, 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.
Setting up a phone or a desktop client
A client given the mail address finds the server by discovery:
/.well-known/carddavand/.well-known/caldavredirect to/dav/, 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 lockout and auto-ban apply to the sign-in.Which password. 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.
The listener. The web services are off as shipped:
WebServicesHttpPortandWebServicesHttpsPortdefault to0, and the HTTPS port takesWebServicesCertificateFileandWebServicesPrivateKeyFile. Since 6.3.4 these keys are kept in the database: change them in the Control Panel (Windows), over REST, or on Linux withhmailserver --set-setting NAME=VALUE, not by editinghMailServer.ini. A saved port or certificate waits for a reinitialise or a restart, since the listener binds when it starts.On the Devices list a DAV client appears with the protocol
davand its user agent. It has no connection to drop - each request authenticates afresh - so revoking it means revoking the app password behind it.Collection What it is /dav/calendars/<address>/calendar/The default calendar, Calendar, made the first time it is asked for/dav/calendars/<address>/<name>/Another calendar of the account's own, made in the webmail or with MKCALENDAR/dav/calendars/<address>/shared-<id>/A calendar another account, or a group, shares with this one /dav/addressbooks/<address>/contacts/The default address book, where a client that has synced since 6.3.3 still finds it /dav/addressbooks/<address>/book-<id>/Another book of the account's own (schema 6079) /dav/addressbooks/<address>/shared-<id>/A book shared with this account, or with the whole domain /dav/addressbooks/<address>/directory/The organisation's directory, read-only (schema 6078) Each calendar collection advertises
VEVENTandVTODO, so a phone's calendar and its reminders list are the same collection.Calendars, events and tasks
An account has one calendar until it makes more. The Calendars box beside the grid adds one with a name and a colour (
POST /api/v1/me/calendars), renames or recolours it and deletes it with its events; the default cannot be deleted. Over CalDAV the colour travels as Apple'scalendar-color, so a phone shows the same one, andPROPPATCHsets the name and colour from the phone's side.Events. An event takes a title,
startandendas wall-clock times intz(an IANA zone the server knows),all_day, a location and notes,rrule(daily, weekly on chosen days, monthly, yearly, with an interval and an end by count or by date),alarm_minutesand guests. The server writesDTSTART;TZID=<zone>so a weekly 09:00 stays 09:00 across a clock change, and aVALARMfor 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;calendar-querywith a time range,calendar-multigetandsync-collectionare all answered, with ETags andIf-Match. Changing one occurrence alone writes an override; deleting one writes anEXDATEon the master.Tasks. The Tasks page lists every
VTODOof every calendar the account can see, soonest due first. Ticking one off writesSTATUS:COMPLETED,COMPLETEDandPERCENT-COMPLETE:100as a client does. A second calendar is a task list of its own.Sharing a calendar, and delegates
The owner names another account of this server and whether it may write (
PUT /api/v1/me/calendars/{id}/shares/{address}withwrite). The other account sees the calendar in its own Calendars box and in its CalDAV home asshared-{id}/, withownerpointing at the sharer's principal and acurrent-user-privilege-setof 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 ofshared-{id}/or from the page.Shared with a group. Since schema 6086 the name may be one of the server's groups (
hm_groups) 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.A delegate. A share may be a delegation (
delegate: true, which implieswrite
the sharee may answer the owner's invitations on the owner's behalf. The answer is POST /api/v1/me/calendar/events/{id}/replywithpartstatACCEPTED,TENTATIVEorDECLINED, allowed to the owner and to a delegate and refused (403) to a plain writer or a reader. The organiser receives aMETHOD:REPLYwhoseATTENDEEcarriesSENT-BY="mailto:<delegate>",From:the owner withSender:the delegate.Free-busy
An account of the domain can see when a colleague is busy, and nothing else about them.
GET /api/v1/me/freebusy?address=<account>&from=<when>&to=<when>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 isTRANSP:TRANSPARENTorSTATUS:CANCELLED, or that the account declined, is left out; a period istentativewhen the account'sPARTSTATisTENTATIVEorNEEDS-ACTION, elsebusy. No title, location or description is answered. Another hosted domain's account, an address nobody has, an inactive account, and an account whosefreebusypreference isnobodyare 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".Over CalDAV the same computation answers the
free-busy-queryREPORT on a calendar the caller may read, as one bareVFREEBUSY, over atime-rangethat 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.Invitations by mail (iMIP)
An event with guests, saved with "Send invitations by e-mail", mails each guest the event as a
text/calendarpart withmethod=REQUEST(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 mailsMETHOD:CANCEL. A message that carries atext/calendarpart or an.icsattachment shows a card with Accept, Maybe, Decline and "Propose a new time" (METHOD:COUNTER).Filed on delivery. A
METHOD:REQUESTdelivered to an account is filed into its default calendar as it arrived (NEEDS-ACTIONas a rule) when, and only when, it names the account as anATTENDEEand not as the organiser. A message flagged as spam files nothing; aREQUESTnaming 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 laterSEQUENCE, and never when itsORGANIZERis not the invitation's. AREPLYdelivered to the organiser sets that attendee'sPARTSTATin the stored event, so every phone syncing the calendar shows who accepted without anyone opening the mail; aCANCELdelivered to a guest marks the stored copy cancelled.Rooms and equipment (since 6.3.4)
A room or a projector is an account whose kind says so:
person(the default),roomorequipment, a column ofhm_accounts(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 delegates.Where What The Control Deck The account editor's General group has a select of the three kinds; a room or equipment gets a Booking policy card REST kindonGETandPUT /api/v1/accounts/{address}; the policy atGETandPUT /api/v1/accounts/{address}/booking-policyCOM (Windows) Account.Kind(0 person, 1 room, 2 equipment), saved bySave(); the booking policy is not on COMThe Windows Control Panel Does not show it: a room is an ordinary account to it 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:
Field Default What it decides auto_accepttrueAnswer invitations by this policy; falseleaves every one for the delegateswindow_days180 How many days ahead a booking may start, 1 to 1080 max_duration_minutes1440 The longest booking; 0 is no limit working_hours_onlyfalseOnly inside the working hours, on the working days work_days,work_start,work_endMonday to Friday, 08:00 to 17:00 The working days and hours time_zoneUTC The zone the working hours are in, such as Europe/Londonallow_conflictsfalseAccept a booking over another one allow_recurringtrueAccept a recurring meeting bookersempty Empty is everyone in this server's own domains; a list is an address, @domain, a distribution list's address or a group's name. An organiser from outside must be named herecapacity0 How many people the room seats, shown in the directory; it decides nothing delegatesnone Addresses and group names, each given a delegate share of the room's calendar Who is asking. The room first decides whether the invitation's
ORGANIZERis who sent it, from what the server recorded when the message arrived and never from aFrom:header or aMAIL FROM. 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 whenbookersnames the address or its@domainand 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.The answer 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
Auto-Submitted, never answered);auto_accept; 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 aMETHOD:REPLYgoes from the room's address, markedAuto-Submitted: auto-replied. 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. A room with no delegates keeps what it leaves and tells nobody: name at least one. Two servers sharing one database are not serialised for rooms: run rooms on one node.Finding a room. The directory lists a room with its kind and
capacity, and its CardDAV card saysKIND:location(KIND:devicefor equipment). Every CalDAV principal says itscalendar-user-type-INDIVIDUAL,ROOMorRESOURCE- and theprincipal-property-searchREPORT on/dav/principals/, 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 aMessageRetentionDaysthat suit it.Contacts, groups and several address books
Kept, and other contacts. A contact has a
source:manualfor what the person added, imported or kept, andcollectedfor 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 Other contacts 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. Keep makes it a contact.What a card carries. A card a CardDAV client sends is kept as sent and served back byte for byte. The page reads
birthday(BDAY),note,phones(everyTEL) and the embeddedPHOTO; a photo that is only a URL is not the server's to fetch.Groups. A group is a card of kind group -
KIND:groupin vCard 4.0,X-ADDRESSBOOKSERVER-KIND:groupin 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 refused403 CARDDAV:valid-address-data) and 200 groups in one address book (400 over REST,507 Insufficient Storageover CardDAV). A group is not a distribution list: nothing about it reaches SMTP.Several address books, and shared ones. Since schema 6079 the account starts with one book,
Contacts, 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; Can edit 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 grantsreadandread-current-user-privilege-setand nothing else, a PUT into it is 403, and DELETE on the collection gives the share back and deletes nobody's contacts.MKCOLis refused: a book is made from the Contacts page or/api/v1/me/address-books. No group is shared, in either direction.The backup carries the books and their contacts;
hm_addressbooksharesis not carried, so the sharing is set again. The Control Panel and the Control Deck have no page for this. An administrator hasGET /api/v1/accounts/{address}/address-books, which shows the shape of the sharing and never the contacts, and a route that removes one share, recorded asaddress-book-share-removed.Import and export. The Contacts page imports a vCard file or a CSV, including Google's and Outlook's exports. Export as vCard downloads
contacts.vcf; Export as CSV downloadscontacts.csvand leaves groups out.The organisation's directory
It is one domain at a time, and always the reader's own: every active account of the domain whose owner has not opted out, and every enabled distribution list, with what is set on top in
hm_directory(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.Two switches, both rows of
hm_settingsand both on by default.DirectoryEnabledis 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.DirectoryUserEditableis whether a person may set their own fields. The opt-out is never what a switch takes away, 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 asdirectory-opt-out-changed.The surfaces. The webmail's Directory page (
#/directory); the To completion, which offers the reader's own contacts first and the directory hits after;GET /api/v1/me/directory?q=&limit=for the person andGETandPUT /api/v1/accounts/{address}/directoryfor the administrator; a Directory entry 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.What it does not do
- No RFC 6638 scheduling (no
schedule-inboxorschedule-outbox), no free-busy of a calendar on another server, no per-calendar time zone (calendar-timezoneis not kept), no partialcalendar-data, and no time-range filter on aVALARM. - No ActiveSync and no Exchange Web Services: a phone uses IMAP and SMTP for mail, and CalDAV and CardDAV for the rest.
- 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.
Where to read more
- Wiki: Connecting a Mail Client, Rooms and Equipment, The Webmail, Ports Reference.
- Documents: Calendar.md, Contacts.md, SharedAddressBooks.md, Directory.md, RoomsAndEquipment.md.
- On this forum: The webmail portal at /portal, The Control Deck, Signing in, Connecting a mail client, and the 6.3.4 announcement.
- No RFC 6638 scheduling (no
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login