From 337c46ebdad4147898248126b818cb862ea74dc3 Mon Sep 17 00:00:00 2001 From: John Ellis Date: Mon, 24 Aug 2026 08:41:15 -0700 Subject: [PATCH] Treat an unreadable backend probe as the older server, not an error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stalwart before 0.16 does not know urn:stalwart:jmap, and rejects the whole request rather than the one call when `using` names a capability it cannot parse. The probe is only sent when the session advertises that capability, so this should not arise — but if it ever does, throwing turns a server we can still manage credentials on into a Security page that only shows an error. Fall through to the endpoint those servers do have. --- server/src/account.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/server/src/account.ts b/server/src/account.ts index 7a95d25..80f769b 100644 --- a/server/src/account.ts +++ b/server/src/account.ts @@ -83,11 +83,17 @@ async function probeBackend(ctx: Ctx): Promise { // A server with the registry answers x:AccountPassword/get; one without it // fails to parse the method name at all and returns unknownMethod. if (ctx.session.capabilities && STALWART_CAP in ctx.session.capabilities) { - const res = await jmap(ctx, [["x:AccountPassword/get", { accountId: accountId(ctx), ids: [SINGLETON] }, "p"]]); - const [name, args] = res.methodResponses?.[0] ?? []; - if (name && name !== "error") return "registry"; - const type = (args as { type?: string } | undefined)?.type; - if (type && type !== "unknownMethod") return "registry"; // present, but refused us + try { + const res = await jmap(ctx, [["x:AccountPassword/get", { accountId: accountId(ctx), ids: [SINGLETON] }, "p"]]); + const [name, args] = res.methodResponses?.[0] ?? []; + if (name && name !== "error") return "registry"; + const type = (args as { type?: string } | undefined)?.type; + if (type && type !== "unknownMethod") return "registry"; // present, but refused us + } catch { + // Not an answer we can read - most likely a server too old to know the + // capability we named, which rejects the whole request rather than the + // one call. Fall through and try the endpoint such servers do have. + } } return "legacy"; }