diff --git a/app/api/account/stalwart/jmap/route.ts b/app/api/account/stalwart/jmap/route.ts index 150e5e2a..76c9a37d 100644 --- a/app/api/account/stalwart/jmap/route.ts +++ b/app/api/account/stalwart/jmap/route.ts @@ -55,9 +55,23 @@ export async function POST(request: NextRequest) { logger.error('Stalwart JMAP passthrough redirect error', { error: error.message }); return NextResponse.json({ error: error.message }, { status: 502 }); } + // `fetch failed` from undici is too generic to debug — the real reason + // (ENOTFOUND, ECONNREFUSED, self-signed TLS, …) lives on `error.cause`. + const err = error as Error & { cause?: { code?: string; message?: string } }; logger.error('Stalwart JMAP passthrough error', { - error: error instanceof Error ? error.message : 'Unknown', + error: err?.message ?? 'Unknown', + causeCode: err?.cause?.code, + causeMessage: err?.cause?.message, }); + // The server this process failed to reach is the user's own mail server, + // so the reason is worth surfacing: an opaque 500 leaves operators with + // nothing to act on. + if (err?.cause?.code) { + return NextResponse.json( + { error: `Cannot reach the JMAP server (${err.cause.code})` }, + { status: 502 }, + ); + } return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } diff --git a/package-lock.json b/package-lock.json index bce5d6b7..5b47f334 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6280,6 +6280,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -7976,6 +7977,17 @@ } } }, + "node_modules/next-intl/node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",