Use mailing lists instead of groups with external directories

Your question

I have attached an external directory source for automatic account provisioning using OpenID Connect. The account properties and groups belongings are correctly synced, everything works as expected.

However, the Group object paradigm is terribly counter-intuitive when we first used a professional e-mail provider, because these works more like mailing lists (by routing incoming messages to personal addresses) than shared inboxes.

I wanted to know if there is a way to either bind the group attribute of the OIDC userinfo endpoint to mailing lists instead of groups, or make groups behave like mailing lists?

Stalwart version: v0.16.22
Directory type: OpenID Connect

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Based on this, mailing lists are a separate object type from directory-synced groups; there’s no claim mapping to auto-create mailing lists from OIDC group claims - only Group principals are provisioned that way. I have enough to answer.

Currently there is no way to bind the OIDC claimGroups mapping to mailing lists, and no setting that makes group principals behave like mailing lists. The claimGroups claim in the OIDC directory config only maps synced group memberships to Group principals: it populates the account’s groups field, which Stalwart resolves against existing Group objects, and groups are fundamentally shared-inbox constructs (members access one shared folder), not distribution lists.

Mailing Lists are a separate first-class object with their own recipients set (a static list of member email addresses configured via the WebUI or JMAP MailingList/set), and that recipient list isn’t tied to any directory group or claim. A group’s lists field only lets a group receive mail sent to a mailing list, it doesn’t make the mailing list distribute to that group’s members.

So today there’s no supported way to have your OIDC groups claim automatically populate a Mailing List’s recipients, groups can only be synced as shared-inbox groups. If you want mailing-list-style delivery for OIDC-synced groups, you would need to maintain those Mailing List recipient sets manually (or via your own script driven by the OIDC provider’s group membership) rather than through the directory sync feature.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Not possible today: the groups claim feeds the code that creates Group principals, and there is no path from a directory claim to a MailingList object. Nor can a group be made to fan out. A group address delivers into the group’s own mailbox, which members then see as a shared folder; a mailing list address expands to its recipient set. Those are two separate resolution branches with no switch between them.

MailingList objects are local-only, and their recipients are plain addresses with no link back to accounts or groups, so there is nothing for a directory sync to attach to.

The route that works for you is to keep OIDC for accounts and provision the lists themselves from your IdP, either through x:MailingList/set over JMAP or with stalwart-cli create mailing-list. One thing in your favour: because OIDC directories do not do recipient lookups, mailing list resolution falls through to the registry and keeps working while OIDC is active. That is not true with an LDAP directory, where an address LDAP resolves first never reaches the registry at all.

The two models coexist if you want both, a group for shared-inbox access and a list for fan-out on the same team, as long as the addresses differ.

Thank you for your reply!

So because the feature is not there (yet?), I have set up a workaround that automatically syncs specific groups of my LDAP (which is the source of my OIDC provider) with specifically crafted mailing lists (i.e. containing ldapgroup:<group-name> in the description).

Here is what I have deployed so far, if anyone encounters the same problem:

#!/bin/sh
#
# VARIABLES:
# - STALWART_USER: Stalwart username
# - STALWART_PASSWORD: Stalwart password
# - LDAP_READONLY_PASS: LDAP password for a readonly account
# - LDAPTLS_CACERT: Path to CA certificate for the LDAP

set -eu

ldaplookup() {
    ldapsearch -D 'uid=readonlyuser,cn=users,cn=realm,dc=tld' -w "LDAP_READONLY_PASS" -H ldaps://ldap.realm.tld:636 $@
}

initgroup() {
    echo '{}' > "$1.json"
}

for group in group1 group2 group3
do
    initgroup "$group"
    
    # Fetching accounts belonging to each group in the LDAP
    ldaplookup -b "cn=$group,cn=groups,cn=realm,dc=tld" member | grep '^member: ' | sed 's/member: //g' | while IFS= read -r userDN
    do
        ldaplookup -b "$userDN" "(!(nsaccountlock=TRUE))" mail | grep -E '^mail: .*@domain\.tld$' | sed 's/mail: //g' | while IFS= read -r address
        do
            # Building json patch for mailing lists
            yq -i ".recipients +={\"$address\": true}" "$group.json"

        done
    done

    # Checker that prevents pushing empty lists crafted because of network errors
    if jq -e '.recipients' "$groupe.json" >/dev/null
    then
      # Pushing MailingList patches on the server
      stalwart-cli --url https://server.domain.tld query --where "text=ldapgroup:$group" MailingList --json | jq -r '.id' | while IFS= read -r mailinglist
      do
        stalwart-cli --url https://server.domain.tld update MailingList "$mailinglist" --file "$group.json"
      done
    fi
done