Domains
Purpose. A domain is a DNS name the server accepts mail for. Everything under it — mailboxes, aliases, forwarders, the catch-all — belongs to the domain; the first domain is created during setup.
Behaviour.
POST /api/v1/domains{ name, defaultQuotaBytes }— name is lower-cased and must be a FQDN; duplicates → 409. New mailboxes inheritdefaultQuotaBytes(0 = unlimited). Creating a domain also generates its DKIM key and adds the aliasdmarc-reports@<domain>→ the system reports mailbox, so that address cannot be used for a mailbox. Refused with402 license_degradedfrom the licence’sdegradedstage on, or402 license_limit_reachedat the licence’s domain limit (nothing is refused in grace or in an install’s 30-day evaluation).- Postfix starts accepting mail for the domain immediately (it reads
v_virtual_domainslive); nothing is rendered or reloaded. PATCHactive:falsestops inbound acceptance and IMAP login for every mailbox in the domain without deleting anything.- Mail routing:
PATCHrouting: 'local' | 'remote'(UI: the domain’s DNS & routing section → Mail routing). Owner and admin only — adomain_adminmay update the domain but gets403changing its routing — and setup’s first domain cannot be routed away (409): it holds the system mailboxes,dmarc-reports@, which every other domain’s reports alias to, andnoreply@.remotemeans the domain’s mail is received by another server: Postfix stops accepting it at once (it readsv_virtual_domainslive), mail from this server’s users to it goes out by the domain’s MX, and its aliases, forwarders and catch-all stop applying. Its mailboxes still sign in, send and keep what they hold; nothing new arrives. The DNS & routing section then asks for no MX, MTA-STS, TLS-RPT,autoconfig.orautodiscover., and an SPF naming this host to merge into the domain’s existing record; this server stops answering, and issuing certificates for, the domain’smta-sts.,autoconfig.andautodiscover.names. A backup-MX mode is not offered. - Inbox categories (Inbox categories):
PATCHcategories: true | false, on by default, allows or forbids the Inbox’s category tabs for every mailbox in the domain. Adomain_adminmay set it. Each save that sends the field, changed or not, pushes every active mailbox’s filter script again, because the switch is read when a script is compiled; if any push fails the change is still saved and the answer is502 sieve_unavailablenaming up to five of the mailboxes, and saving the same value again retries them. DELETEis refused (409) while mailboxes exist; aliases and the catch-all are removed with the domain.GET /api/v1/domains/{id}/stats?days=7(1–90) — the domain’s activity from the delivery log over whole UTC days:received(delivered or forwarded for an address in the domain, by recipient or original recipient),refused(rejected at SMTP time for one),sent,failed(bounced or expired) anddeferred(retry attempts) for a sender in it, anddaily{ date, received, sent, failed }for every day of the window. Counted per recipient, as the log records deliveries; mail between two of the server’s domains counts on both sides. Who may read it is decided exactly as for the domain’s DMARC and TLS-report routes beside it.GET /api/v1/domains/{id}/dnsreturns the records to publish: A (host) and PTR whenPUBLIC_IPis set, the AAAA and IPv6 PTR when IPv6 is on andPUBLIC_IP6is set, MX, SPF (v=spf1 mx -all; a domain routed to another server getsv=spf1 a:<hostname> -all, to merge into the record it already publishes), DKIM (one per key), DMARC (monitor), IMAP/SMTP SRV autodiscover, the mail host’s own SPF (TXT <hostname> "v=spf1 a -all", for SRS-rewritten forwarded mail), and — with ACME TLS only, and for a domain routed to this server only — the autoconfig/autodiscover CNAMEs and, unlessmtaSts.modeisnone, the MTA-STS and TLS-RPT rows. With an outbound relay configured, both SPF rows carry its term before-all;POST …/dns/verifychecks them live (DNS records & live verification). Creating a domain also generates its DKIM key and pushes it to rspamd (DKIM signing); deleting a domain removes the key.
Configuration. None on the host. Domain defaults live in the database.
Limits & edge cases. One tenant in v1; IDNA names must be supplied in punycode. Renaming is not supported (delete + create). The server’s own hostname does not need to be a domain.