Provide mail through an SMTP gateway

Workspace owns mailboxes and webmail. An upstream gateway such as Proxmox Mail Gateway remains the public SMTP edge and retains MX, PTR, reputation, DKIM, filtering, and the external queue.

This operations guide is for Workspace and mail administrators. It leads from the tenant-bound access check to verifiable inbound and outbound tests. At the end, Workspace manages personal and shared mailboxes plus distribution lists, while the gateway continues to own public mail delivery. See Integrate the mail API and gateway handoff for the technical API contract.

Check access and the agent workflow

Log in to the target tenant with nucli. Check the identity, mail permissions, and reachable mail endpoints before changing state:

bash
nucli --tenant <tenant> whoami --scopes
nucli --tenant <tenant> api GET /api/v1/mail/mailboxes --summary
nucli --tenant <tenant> api GET /api/v1/mail/admin/domains --summary

An automated agent reads the built-in mail workflow before it starts:

bash
nucli skills show mail

The skill uses only tenant-bound HTTP. It must not use database access, numin, Storage paths, or gateway access to bypass authentication, tenancy, permissions, or mail contracts. Mailbox roles and ResourceACL grant mail content access; a tenant administrator role alone does not.

Prepare mailboxes

  1. Create the hosted domain through POST /api/v1/mail/admin/domains.
  2. Create personal or shared mailboxes through POST /api/v1/mail/admin/mailboxes.
  3. Add shared-mailbox members through POST /api/v1/mail/admin/mailboxes/{id}/memberships.
  4. Create distribution lists separately through POST /api/v1/mail/admin/distribution-lists.
  5. Set tenant configuration storage.context.mail.store_id to the existing encrypted mail store.

Distribution lists fan out delivery to target mailboxes. Shared mailboxes instead share work state, assignment, and sender rules.

Pass write payloads as protected files so addresses and identity IDs do not enter shell history:

bash
nucli --tenant <tenant> api POST /api/v1/mail/admin/domains \
  --input mail-domain.json --summary
nucli --tenant <tenant> api POST /api/v1/mail/admin/mailboxes \
  --input mailbox.json --summary
nucli --tenant <tenant> api POST \
  /api/v1/mail/admin/mailboxes/<mailbox-id>/memberships \
  --input membership.json --summary
nucli --tenant <tenant> api POST /api/v1/mail/admin/distribution-lists \
  --input distribution-list.json --summary

Use personal or shared as the mailbox type and owner, editor, or viewer as the membership role. Grant a new member historical access only through an explicit, audited historyGrantedFromAt decision. Every mutation requires explicit administrator approval.

Secure the private handoff

Enable mail.handoff.mailbox.enabled only after configuring:

  • a private or loopback mail.handoff.mailbox.bind_address;
  • the internal mail.handoff.mailbox.port;
  • mail.handoff.mailbox.tls.cert_file and mail.handoff.mailbox.tls.key_file;
  • mail.handoff.mailbox.tls.client_ca_file; and
  • authorized certificate fingerprints in mail.handoff.mailbox.gateway_sha256.

The listener requires TLS 1.3 and a valid client certificate. PMG may remove a message from its queue only after successful recipient validation and the final 250 stored. Normal delivery and DSNs use separate recipient routers on this private handoff.

Route delivery and bounces

Point the existing tenant SMTP configuration only at the gateway. Workspace does not deliver directly to foreign MX servers. Set mail.outbound.bounce_domain to the bounce domain routed back by the gateway.

Workspace stores DSNs encrypted, copies the sent message's content ACL, and shows the separate queue state for every envelope recipient in the thread.

Import Zimbra safely

Create a Storage store containing encrypted Zimbra IMAP credentials. Run mailbox.import.imap with:

json
{
  "tenant_id": "<tenant-uuid>",
  "source_store_id": "<zimbra-source-store-uuid>",
  "target_store_id": "<mail-storage-store-uuid>",
  "recipient": "user@example.com"
}

Run a full import, a delta import, and a final delta immediately before gateway cutover. Replays are idempotent by source store, source UID, Message-ID, and content hash. Taskstream reports processed and skipped messages. Compare those counts, then test inbound mail, outbound mail, and one DSN.

Change MX, PTR, SPF, DKIM, and DMARC only in a separately approved operations change. Workspace never changes that external configuration.

Verify the deployment

The deployment is complete when all of these checks succeed:

  1. GET /api/v1/mail/mailboxes shows only the personal and shared mailboxes granted to the test identity.
  2. A test message to a hosted address receives 250 stored on the private handoff only after durable Storage persistence and then appears in the mail workbench.
  3. An approved outbound test first reaches stored and queued state. Then check every envelope recipient; queued does not mean delivered.
  4. An intentionally generated DSN enters through the separate bounce router and attaches to the sent thread.
  5. A shared-mailbox member sees only the granted history range and can read or send only as allowed by the assigned role.
  6. A distribution list delivers an authorized test message to its configured target mailboxes without creating shared work state.

Users continue with Work with mail.

Plan an installation without PMG

The product core does not depend on PMG. An installation without an existing gateway needs a separately operated mail edge based on established MTA software. That edge owns the same public responsibilities and uses the same private mTLS handoff. Ship it only after a dedicated licensing, security, update, and operations gate; the Workspace server does not become a public MTA.