Render an Apple configuration profile from the server's PACC document
docs / deploy (push) Successful in 3s
Test / test (push) Successful in 2m9s
Publish release / publish (push) Successful in 1m52s

iOS is the one client none of the mail autoconfiguration reaches: Apple
Mail reads neither Mozilla autoconfig nor Autodiscover for IMAP, so
adding an account means the device probing for ports - and a probe that
meets a filtered port waits out a TCP timeout and reports the account as
unverifiable, which the person reads as a wrong password.

A profile states the hosts and the ports instead, and carries mail,
calendars and contacts in one install. It invents none of them: site.yaml
names a PACC document - the standard defined to be fetched from the mail
domain itself - and every host, port and collection path comes from
there, so the server is described in one place and the profile follows it.

The document holds no address, username or password. iOS asks for those
at install, which means one profile serves everyone with an account and
it can be fetched by anyone: it says no more than PACC already says in
public. Identifiers are derived from the site and the payload rather than
drawn at random, because iOS replaces a profile whose ids it knows and
stacks a duplicate when they differ.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o
This commit is contained in:
Bendik Lynghaug
2026-10-07 11:18:46 +02:00
co-authored by Claude Opus 5
parent 43a2f3a069
commit 44c7ee6870
46 changed files with 6937 additions and 1519 deletions
+44
View File
@@ -126,6 +126,50 @@ mail autoconfiguration (`/.well-known/autoconfig/`) and the CalDAV and
CardDAV redirects are usually handed to a mail server that generates
them.
## A configuration profile
iOS has no autoconfiguration for IMAP accounts - Apple Mail reads neither
Mozilla autoconfig nor Microsoft Autodiscover, which are for ActiveSync - so
adding an account by hand leaves the device probing for ports. A probe that
meets a *filtered* port, a firewall that drops rather than refuses, waits out
a TCP timeout, and the account comes back "could not be verified", which reads
to the person as a wrong password. An Apple configuration profile ends the
guessing by stating the hosts and the ports, and it carries mail, calendars
and contacts in a single install.
Portal renders one at `/profile.mobileconfig` when `site.yaml` says where to
get the values:
```yaml
profile:
pacc: https://mail.example.no/.well-known/user-agent-configuration.json
name: Example # what the accounts are called on the device
organization: Example AS # the profile's publisher, defaults to name
```
`pacc` is the mail server's **PACC** document - the standard that replaces
guessing at hostnames, defined to be fetched from the mail domain itself, and
served by Stalwart among others. Every host, port and collection path in the
profile comes from it, so nothing about the server is written down a second
place to drift from the first: move a collection on the server and the profile
moves with it. Where PACC states no port, the registered implicit-TLS default
is used (993 for IMAP, 465 for submission, 443 for DAV).
What the profile contains is only what PACC already says in public. It carries
**no address and no username** - iOS asks for those and the password at
install - so one document serves everyone with an account and may be fetched
by anyone. Payload identifiers are derived from the site and the payload
rather than drawn at random, so reinstalling replaces the accounts instead of
stacking duplicates beside them.
Two things it cannot do. A profile Portal renders is unsigned, so iOS shows it
as *Unverified* while still offering to install it; signing needs a
certificate the device already trusts. And a PACC document describing no
protocol iOS understands - JMAP alone, or an incoming server with no outgoing
one - is an error rather than a half-empty profile that looks like it worked.
No `profile:` means `/profile.mobileconfig` is a 404.
## An alternative
One choice. Never two actions behind one heading: if two things can be