Skip to main content
A DistributionGroup is an OxiMail JMAP extension (urn:oximail:params:jmap:distributiongroups): an alias at the organization’s domain that resolves to N recipients. team-eng@example.com reaches alice, bob and carol; partners@ reaches an external address and another group. It is an alias, nothing more: no membership state on the recipient’s side, no moderation, no archive. What arrives in a member’s Inbox still shows team-eng@example.com in To:, never the list of members.

The capability object

These are the hard caps, announced so a client can refuse an oversized edit before the server does. The operator sets the effective depth below the hard one: [distribution_groups] max_depth (3 by default, capped at 10), max_flat_size (1000), fanout_per_minute (5000), and enabled.

Objects and methods

A member is one of three kinds, tagged by kind: account (accountId; the email shown is resolved by the server at read and never read at write, so a client references by id alone), email (an external address), group (groupId, nested; its name is a display copy, same rule). An update patches membership with addMembers and removeMembers rather than replacing the list. DistributionGroup/query takes no filter and no sort yet: a supplied one is refused (unsupportedFilter, unsupportedSort), never executed as if absent.

Behaviours worth knowing

  • Anyone may create; the owner or an admin may change. A create by any member of the organization makes the caller the owner; naming a different ownerAccountId requires an admin. Update and destroy are the owner’s or an admin’s. Every membership mutation and every destroy writes an audit line in the handler’s transaction, since a group used in a shareWith grant changes the effective rights of N accounts.
  • A group cannot shadow a colleague. Inbound expansion runs before account resolution, deliberately, so a group named after a colleague’s local part would silently divert their mail to the members; create and rename refuse any name already carried by a live group, a historical alias, an account address or an email alias of the organization. The guard is per organization: a group team in one organization never expands a message sent to team@ another organization’s domain, which is passed through verbatim.
  • Renaming keeps the old name alive. The previous name becomes a historical alias, served in aliases (oldest first), and old-name@ keeps resolving.
  • Who sees the members. An admin, the owner (whoever manages the membership must read it), a member, or anyone when membersVisibleToTenant is true; everyone else receives members: null. memberCount is always served.
  • Nesting is bounded and precomputed. A set recomputes the flat expansion of the group and of every ancestor in the same transaction, refusing a cycle, a depth over the cap and a flat size over the cap with a typed error; the refused object rolls back to its savepoint while the other objects of the call proceed. Delivery and submission then read the flat cache, one SQL lookup and no recursion.
  • A fan-out budget per organization. Each expansion consumes N units of a sliding one-minute window (fanout_per_minute); over it, the resolution fails rather than sending, so a runaway sender cannot turn a group into a flood.
  • A full member is skipped. On delivery to a group, a member whose mailbox is over quota is skipped, logged and counted; the other members receive the message (storage). When a colleague leaves, oximail account offboard names the groups they belong to and changes none of them: group mail already follows the address redirection member by member (CLI).
Strictness rules are identical to the mail surface: unknown ids in notFound, invalidProperties over coercion, stateMismatch on ifInState.