fix(mail): drop contacts from the EAS bundle — Stalwart 404s empty addressbook homes
ci / changes (push) Successful in 3s
ci / tc_booking (push) Has been skipped
ci / tc_operator (push) Has been skipped
ci / tc_platform_api (push) Has been skipped
ci / test_platform_api (push) Has been skipped
ci / tc_website (push) Successful in 20s
ci / tc_portal (push) Successful in 26s
ci / build_booking (push) Has been skipped
ci / build_operator (push) Has been skipped
ci / build_platform_api (push) Has been skipped
ci / build_zpush (push) Successful in 11s
ci / build_portal (push) Successful in 41s
ci / deploy (push) Successful in 39s

BackendCombined login is all-or-nothing, and Stalwart returns 404 for
/dav/card/<account>/ when the account's default address book was never
created (it doesn't auto-create on the gateway's PROPFIND the way the
calendar home worked) — so CardDAV killed every otherwise-successful
EAS login. Exchange accounts now bundle mail + calendar; contacts stay
on the Apple-profile CardDAV path. Re-enable BackendCardDAV once
platform-api provisions a default address book at mailbox creation.

Copy/docs aligned: portal hint, SERVICES.md, website FAQ (da+en).
This commit is contained in:
Ronni Baslund
2026-06-12 15:31:27 +02:00
parent 9bc89bcd5d
commit fc621cdf81
4 changed files with 23 additions and 15 deletions
+1 -1
View File
@@ -769,7 +769,7 @@ async function submitCreateMailbox() {
<template v-else>This member signs in with an external address and has no inbox. Create a mailbox on your domain to give them one — and to enable aliases.</template> <template v-else>This member signs in with an external address and has no inbox. Create a mailbox on your domain to give them one — and to enable aliases.</template>
</p> </p>
<p v-if="hasMailbox" class="ud-hint"> <p v-if="hasMailbox" class="ud-hint">
On iPhone and Android the mailbox can also be added as an <strong>Exchange</strong> account — mail, calendar and contacts in one go. Server <Mono>{{ mailHost }}</Mono>, username is the mailbox address. Works in the built-in mail apps (not the Outlook app); on Windows, Outlook syncs the calendar via the free CalDAV Synchronizer add-in. On iPhone and Android the mailbox can also be added as an <strong>Exchange</strong> account — mail and calendar in one go. Server <Mono>{{ mailHost }}</Mono>, username is the mailbox address. Works in the built-in mail apps (not the Outlook app); on Windows, Outlook syncs the calendar via the free CalDAV Synchronizer add-in.
</p> </p>
</div> </div>
</section> </section>
+2 -2
View File
@@ -123,7 +123,7 @@ export const COPY = {
heading: 'Det vi bliver spurgt om.', heading: 'Det vi bliver spurgt om.',
items: [ items: [
['Hvordan virker migration fra Microsoft 365?', 'Vi flytter mail, kalender, kontakter og OneDrive-filer i baggrunden, mens jeres team arbejder videre. Skifte-dagen er en DNS-opdatering. Typisk forløb er 24 uger for 50 brugere.'], ['Hvordan virker migration fra Microsoft 365?', 'Vi flytter mail, kalender, kontakter og OneDrive-filer i baggrunden, mens jeres team arbejder videre. Skifte-dagen er en DNS-opdatering. Typisk forløb er 24 uger for 50 brugere.'],
['Kan jeg stadig bruge Outlook og Office?', 'Ja. Mail virker i Outlook og alle IMAP-klienter. Kalender og kontakter synkroniserer via CalDAV/CardDAV — og som Exchange-konto i mobilens indbyggede apps. Outlook på Windows synkroniserer kalenderen via det gratis CalDAV Synchronizer-tilføjelsesprogram. Drev-filer åbnes med Office desktop via WebDAV. Vi anbefaler vores web- og mobil-apps som primært valg, men kravet er ikke at I skifter vaner.'], ['Kan jeg stadig bruge Outlook og Office?', 'Ja. Mail virker i Outlook og alle IMAP-klienter. Kalender og kontakter synkroniserer via CalDAV/CardDAV — og mail + kalender som Exchange-konto i mobilens indbyggede apps. Outlook på Windows synkroniserer kalenderen via det gratis CalDAV Synchronizer-tilføjelsesprogram. Drev-filer åbnes med Office desktop via WebDAV. Vi anbefaler vores web- og mobil-apps som primært valg, men kravet er ikke at I skifter vaner.'],
['Hvor er data hosted?', 'Hos Hetzner i Tyskland. Tier III-certificerede datacentre, redundant strøm og netværk, ISO 27001-certificeret operatør. Ingen data forlader EU på noget tidspunkt — ikke for analytics, logs eller support.'], ['Hvor er data hosted?', 'Hos Hetzner i Tyskland. Tier III-certificerede datacentre, redundant strøm og netværk, ISO 27001-certificeret operatør. Ingen data forlader EU på noget tidspunkt — ikke for analytics, logs eller support.'],
['Hvad sker der hvis dezky lukker?', 'Hele stakken er open source. I kan eksportere alt og flytte til en anden dezky-partner. Vores forretningsmodel er drift, ikke gidseltagning.'], ['Hvad sker der hvis dezky lukker?', 'Hele stakken er open source. I kan eksportere alt og flytte til en anden dezky-partner. Vores forretningsmodel er drift, ikke gidseltagning.'],
['Hvad er jeres SLA?', '99,9 % uptime garanteret på alle planer. 99,95 % på Enterprise. Status-side med real-time data offentligt tilgængelig på status.dezky.eu.'], ['Hvad er jeres SLA?', '99,9 % uptime garanteret på alle planer. 99,95 % på Enterprise. Status-side med real-time data offentligt tilgængelig på status.dezky.eu.'],
@@ -633,7 +633,7 @@ export const COPY = {
heading: 'What we get asked.', heading: 'What we get asked.',
items: [ items: [
['How does migration from Microsoft 365 work?', 'We move mail, calendar, contacts and OneDrive files in the background while your team keeps working. Cutover day is a DNS update. Typical timeline is 24 weeks for 50 users.'], ['How does migration from Microsoft 365 work?', 'We move mail, calendar, contacts and OneDrive files in the background while your team keeps working. Cutover day is a DNS update. Typical timeline is 24 weeks for 50 users.'],
['Can I still use Outlook and Office?', 'Yes. Mail works in Outlook and any IMAP client. Calendar and contacts sync via CalDAV/CardDAV — and as an Exchange account in the phone\'s built-in apps. Outlook on Windows syncs the calendar via the free CalDAV Synchronizer add-in. Drive files open with Office desktop via WebDAV. We recommend our web and mobile apps, but we don\'t require you to change habits.'], ['Can I still use Outlook and Office?', 'Yes. Mail works in Outlook and any IMAP client. Calendar and contacts sync via CalDAV/CardDAV — and mail + calendar as an Exchange account in the phone\'s built-in apps. Outlook on Windows syncs the calendar via the free CalDAV Synchronizer add-in. Drive files open with Office desktop via WebDAV. We recommend our web and mobile apps, but we don\'t require you to change habits.'],
['Where is data hosted?', 'With Hetzner in Germany. Tier III certified data centers, redundant power and network, ISO 27001 certified operator. No data leaves the EU at any time — not for analytics, logs or support.'], ['Where is data hosted?', 'With Hetzner in Germany. Tier III certified data centers, redundant power and network, ISO 27001 certified operator. No data leaves the EU at any time — not for analytics, logs or support.'],
['What happens if dezky shuts down?', 'The whole stack is open source. You can export everything and move to another dezky partner. Our business model is operations — not hostage-taking.'], ['What happens if dezky shuts down?', 'The whole stack is open source. You can export everything and move to another dezky partner. Our business model is operations — not hostage-taking.'],
['What\'s your SLA?', '99.9% uptime guaranteed on all plans. 99.95% on Enterprise. Public real-time status page at status.dezky.eu.'], ['What\'s your SLA?', '99.9% uptime guaranteed on all plans. 99.95% on Enterprise. Public real-time status page at status.dezky.eu.'],
+5 -2
View File
@@ -158,8 +158,11 @@ docker compose port stalwart 25
**URL:** https://mail.dezky.local/Microsoft-Server-ActiveSync (+ EAS **URL:** https://mail.dezky.local/Microsoft-Server-ActiveSync (+ EAS
autodiscover on https://autodiscover.dezky.local) autodiscover on https://autodiscover.dezky.local)
**Purpose:** Exchange ActiveSync gateway in front of Stalwart — "Exchange" **Purpose:** Exchange ActiveSync gateway in front of Stalwart — "Exchange"
accounts on iOS/Android native Mail/Calendar get two-way mail + calendar + accounts on iOS/Android native Mail/Calendar get two-way mail + calendar
contacts sync (IMAP + CalDAV + CardDAV fan-out via BackendCombined). sync (IMAP + CalDAV fan-out via BackendCombined). Contacts are NOT bundled
yet: the combined login is all-or-nothing and Stalwart 404s addressbook
homes that were never created — re-enable CardDAV once platform-api
provisions a default address book at mailbox creation.
**Protocol reality check:** EAS 14.1. Covers native mobile clients; NOT the **Protocol reality check:** EAS 14.1. Covers native mobile clients; NOT the
Outlook mobile app (requires EAS 16.1) and not new Outlook for Windows (no Outlook mobile app (requires EAS 16.1) and not new Outlook for Windows (no
+15 -10
View File
@@ -1,10 +1,16 @@
<?php <?php
// dezky replacement for Z-Push's backend/combined/config.php (applied at // dezky replacement for Z-Push's backend/combined/config.php (applied at
// image build, see Dockerfile). One EAS account fans out to three Stalwart // image build, see Dockerfile). One EAS account fans out to Stalwart over
// protocols: mail over IMAP, calendar/tasks over CalDAV, contacts over // IMAP (mail) and CalDAV (calendar/tasks). Login succeeds only if every
// CardDAV. Login succeeds only if every backend authenticates — they all // backend authenticates — they all hit the same Stalwart account with the
// hit the same Stalwart account with the same credentials, so that's one // same credentials, so that's one effective check.
// effective check. //
// CardDAV (contacts) is deliberately NOT in the bundle yet: the combined
// login is all-or-nothing, and Stalwart 404s the addressbook home of any
// account whose default address book was never created — which killed every
// EAS login on first deploy. Re-add 'd' => BackendCardDAV once platform-api
// provisions a default address book at mailbox creation. Apple devices get
// contacts via the .mobileconfig CardDAV payload meanwhile.
class BackendCombinedConfig { class BackendCombinedConfig {
@@ -13,7 +19,6 @@ class BackendCombinedConfig {
'backends' => array( 'backends' => array(
'i' => array('name' => 'BackendIMAP'), 'i' => array('name' => 'BackendIMAP'),
'c' => array('name' => 'BackendCalDAV'), 'c' => array('name' => 'BackendCalDAV'),
'd' => array('name' => 'BackendCardDAV'),
), ),
'delimiter' => '/', 'delimiter' => '/',
'folderbackend' => array( 'folderbackend' => array(
@@ -28,10 +33,10 @@ class BackendCombinedConfig {
SYNC_FOLDER_TYPE_USER_APPOINTMENT => 'c', SYNC_FOLDER_TYPE_USER_APPOINTMENT => 'c',
SYNC_FOLDER_TYPE_TASK => 'c', SYNC_FOLDER_TYPE_TASK => 'c',
SYNC_FOLDER_TYPE_USER_TASK => 'c', SYNC_FOLDER_TYPE_USER_TASK => 'c',
SYNC_FOLDER_TYPE_CONTACT => 'd', // No contacts/notes/journal on EAS for now — let mail own
SYNC_FOLDER_TYPE_USER_CONTACT => 'd', // them so folder creation never lands somewhere surprising.
// No notes/journal store in Stalwart — let mail own the rest SYNC_FOLDER_TYPE_CONTACT => 'i',
// so folder creation never lands on a DAV backend by surprise. SYNC_FOLDER_TYPE_USER_CONTACT => 'i',
SYNC_FOLDER_TYPE_NOTE => 'i', SYNC_FOLDER_TYPE_NOTE => 'i',
SYNC_FOLDER_TYPE_USER_NOTE => 'i', SYNC_FOLDER_TYPE_USER_NOTE => 'i',
SYNC_FOLDER_TYPE_JOURNAL => 'i', SYNC_FOLDER_TYPE_JOURNAL => 'i',