Can't authenticate to STMP from LDAP directory

Issue Description

Accounts auto-created via external LDAP directory can authenticate via IMAP (AUTH=PLAIN SASL-IR) but cannot authenticate via SMTP or log in to the Web UI. The LDAP bind succeeds (User has access in Authentik logs) but Stalwart’s internal permission check returns 550 5.7.1 Your account is not authorized to use this service.
The authenticate permission is present in the User role but is not applied to LDAP-linked accounts. Assigning the Admin role and restarting does not fix it.

Expected Behavior

SMTP AUTH and Web UI login should succeed with the same LDAP credentials that work for IMAP.

Actual Behavior

  • IMAP: AUTH=PLAIN → success
  • SMTP: AUTH LOGIN / AUTH PLAIN550 5.7.1 Your account is not authorized to use this service
  • Web UI: login fails
  • LDAP outpost logs (Authentik): User has access — bind succeeds
  • Stalwart internal log (expected, tracing is Enterprise-only): security.unauthorized with details = "authenticate"

Reproduction Steps

Steps to reproduce

  1. Configure an LDAP directory in Stalwart
  2. Authenticate via IMAP on port 993 (AUTH=PLAIN) → works
  3. Attempt SMTP AUTH on port 465 or 587 (AUTH LOGIN or AUTH PLAIN) → fails with 550 5.7.1
  4. Attempt Web UI login → fails (invalid credentials)

Relevant Log Output

LDAP outpost (Authentik) — shows the LDAP bind succeeds (correct password):

{"bindDN":"----","client":"172.x.x.x","event":"User has access","level":"info","requestId":"d7e0fc21-789d-4a98-9d11-0b06789c0541","timestamp":"2026-05-27T15:17:28Z"}
{"bindDN":"-----","client":"172.x.x.x","event":"Bind request","level":"info","requestId":"d7e0fc21-789d-4a98-9d11-0b06789c0541","timestamp":"2026-05-27T15:17:28Z","took-ms":2092}

LDAP outpost (Authentik) — wrong password (for comparison, shows the error is NOT misconfigured LDAP):

{"bindDN":"-----","client":"172.x.x.x","error":"flow error password: Invalid password","event":"failed to execute flow","level":"warning","requestId":"086d59ca-a608-4cd4-93d0-91c31897e3a8","timestamp":"2026-05-27T15:20:39Z"}

SMTP session (client-side) — correct password: LDAP bind succeeds, but Stalwart rejects after auth:

$ openssl s_client -connect mail.x.it:465 -quiet
250-AUTH PLAIN LOGIN
AUTH LOGIN
334 VXNlcm5hbWU6
<base64-username>
334 UGFzc3dvcmQ6
<base64-password>
550 5.7.1 Your account is not authorized to use this service.

SMTP session (client-side) — wrong password (for comparison):

AUTH LOGIN
334 VXNlcm5hbWU6
...
535 5.7.8 Authentication credentials invalid.

Stalwart internal (expected — tracing is Enterprise-only, but based on GitHub issue #2038):

INFO  Authentication successful (auth.success) accountName="[email protected]"
INFO  Unauthorized access (security.unauthorized) details="authenticate"

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

PostgreSQL

Blob Storage

PostgreSQL

Search Engine

PostgreSQL

Directory Backend

LDAP

Additional Context

  • Stalwart: v0.16.6
  • Database: PostgreSQL 16
  • Directory: LDAP (Authentik 2025.8.3 LDAP outpost) ←
  • Deployment: Docker

What we tried (none fixed it)

  • Set mustMatchSender to false in MtaStageAuth
  • Change saslMechanisms to [login], [plain], [plain, login]
  • Assign Admin role to account + restart
  • Delete and recreate account (fresh LDAP auto-creation) + restart
  • Create account manually via stalwart-cli create Account
  • Restart Stalwart after every change

Additional observations

  • defaultUserRoleIds in Authentication singleton is <none> and cannot be modified
  • Cannot set credentials for accounts in an external directory (prevents adding a local password workaround)
  • Setting explicit permissions on the account also fails

Related

  • GitHub issue #2038 (marcato fixed in v0.16.0, but persists for LDAP-authenticated accounts)

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

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

Additional finding: incoming mail delivery is also broken for LDAP users. Messages to [email protected] (no LDAP entry) are rejected at SMTP time with 550 5.1.2 Mailbox does not exist. Messages to [email protected] (found via LDAP) are accepted (250 2.0.0 Message queued) but never delivered — queue shows 0, mailbox shows 0 emails, no bounce generated. Likely the same root cause as SMTP AUTH: emailReceive permission not applied.

Validate using ldapsearch all your LDAP queries to make sure they yield valid results. Also check the Authentication object to make sure the User roles are correctly linked.

Ecco una risposta:


Thanks for the pointers. LDAP queries were validated and all return correct results.

The key issue was that Authentication.defaultUserRoleIds was empty — setting it to the built-in User role (b) fixed the SMTP auth problem. There’s also the known #2038 restart requirement after any role/permission changes.

With both fixes applied, everything works: IMAP, SMTP, and external delivery.

Thanks again for the great project!