feat: enhance error handling in Stalwart API responses

This commit is contained in:
Linus Rath
2026-04-03 15:10:11 +02:00
parent c53ff5a30a
commit 14ecae61dc
13 changed files with 71 additions and 16 deletions
+17 -2
View File
@@ -2,6 +2,20 @@ import { NextRequest, NextResponse } from 'next/server';
import { logger } from '@/lib/logger';
import { getStalwartCredentials } from '@/lib/stalwart/credentials';
/**
* Parse Stalwart error response to extract meaningful error message
*/
function parseStalwartError(responseText: string): string {
try {
const error = JSON.parse(responseText);
if (error.detail) return error.detail;
if (error.error) return error.error;
return `HTTP ${error.status || 'Error'}`;
} catch {
return responseText;
}
}
/**
* GET /api/account/stalwart/auth
* Proxy to Stalwart GET /api/account/auth
@@ -20,9 +34,10 @@ export async function GET(request: NextRequest) {
if (!response.ok) {
const text = await response.text();
logger.warn('Stalwart auth info failed', { status: response.status });
const detail = parseStalwartError(text);
logger.warn('Stalwart auth info failed', { status: response.status, detail });
return NextResponse.json(
{ error: 'Failed to fetch auth info', details: text },
{ error: detail || 'Failed to fetch auth info' },
{ status: response.status }
);
}
+17 -2
View File
@@ -2,6 +2,20 @@ import { NextRequest, NextResponse } from 'next/server';
import { logger } from '@/lib/logger';
import { getStalwartCredentials } from '@/lib/stalwart/credentials';
/**
* Parse Stalwart error response to extract meaningful error message
*/
function parseStalwartError(responseText: string): string {
try {
const error = JSON.parse(responseText);
if (error.detail) return error.detail;
if (error.error) return error.error;
return `HTTP ${error.status || 'Error'}`;
} catch {
return responseText;
}
}
/**
* GET /api/account/stalwart/crypto
* Proxy to Stalwart GET /api/account/crypto
@@ -20,9 +34,10 @@ export async function GET(request: NextRequest) {
if (!response.ok) {
const text = await response.text();
logger.warn('Stalwart crypto info failed', { status: response.status });
const detail = parseStalwartError(text);
logger.warn('Stalwart crypto info failed', { status: response.status, detail });
return NextResponse.json(
{ error: 'Failed to fetch crypto info', details: text },
{ error: detail || 'Failed to fetch crypto info' },
{ status: response.status }
);
}
+17 -2
View File
@@ -2,6 +2,20 @@ import { NextRequest, NextResponse } from 'next/server';
import { logger } from '@/lib/logger';
import { getStalwartCredentials } from '@/lib/stalwart/credentials';
/**
* Parse Stalwart error response to extract meaningful error message
*/
function parseStalwartError(responseText: string): string {
try {
const error = JSON.parse(responseText);
if (error.detail) return error.detail;
if (error.error) return error.error;
return `HTTP ${error.status || 'Error'}`;
} catch {
return responseText;
}
}
/**
* GET /api/account/stalwart/principal
* Proxy to Stalwart GET /api/principal/{username}
@@ -20,9 +34,10 @@ export async function GET(request: NextRequest) {
if (!response.ok) {
const text = await response.text();
logger.warn('Stalwart principal fetch failed', { status: response.status });
const detail = parseStalwartError(text);
logger.warn('Stalwart principal fetch failed', { status: response.status, detail });
return NextResponse.json(
{ error: 'Failed to fetch principal', details: text },
{ error: detail || 'Failed to fetch principal' },
{ status: response.status }
);
}
@@ -157,6 +157,7 @@ function DisplayNameSection() {
<Input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder={displayName || t('display_name.placeholder')}
className="w-48"
/>
<Button
@@ -523,7 +524,7 @@ export function AccountSecuritySettings() {
if (isStalwart === false) {
return (
<SettingsSection title={t('title')} description={t('description')}>
<p className="text-sm text-muted-foreground py-4">{t('not_available')}</p>
<div className="text-sm text-muted-foreground py-4" dangerouslySetInnerHTML={{ __html: t('not_available') }} />
</SettingsSection>
);
}
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Kontosicherheit",
"description": "Verwalten Sie Ihr Passwort, Zwei-Faktor-Authentifizierung und Sicherheitseinstellungen",
"detecting": "Serverfunktionen werden erkannt...",
"not_available": "Kontosicherheitsverwaltung ist für diesen Mailserver nicht verfügbar.",
"not_available": "Kontosicherheitsverwaltung ist für diesen Mailserver nicht verfügbar. Erforderliche Berechtigungen könnten deaktiviert sein. Siehe die <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">Dokumentation</a> für Details.",
"password": {
"title": "Passwort ändern",
"current": "Aktuelles Passwort",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Anzeigename",
"description": "Ihr Name, wie er auf dem Server angezeigt wird",
"placeholder": "Geben Sie Ihren Anzeigenamen ein",
"save": "Speichern",
"success": "Anzeigename aktualisiert",
"error": "Anzeigename konnte nicht aktualisiert werden"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Account Security",
"description": "Manage your password, two-factor authentication, and security settings",
"detecting": "Detecting server capabilities...",
"not_available": "Account security management is not available for this mail server.",
"not_available": "Account security management is not available for this mail server. Required permissions may be disabled. See the <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentation</a> for details.",
"password": {
"title": "Change Password",
"current": "Current Password",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Display Name",
"description": "Your name as it appears on the server",
"placeholder": "Enter your display name",
"save": "Save",
"success": "Display name updated",
"error": "Failed to update display name"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Seguridad de la cuenta",
"description": "Administre su contraseña, autenticación de dos factores y configuración de seguridad",
"detecting": "Detectando capacidades del servidor...",
"not_available": "La gestión de seguridad de la cuenta no está disponible para este servidor de correo.",
"not_available": "La gestión de seguridad de la cuenta no está disponible para este servidor de correo. Es posible que los permisos requeridos estén deshabilitados. Consulte la <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentación</a> para obtener más detalles.",
"password": {
"title": "Cambiar contraseña",
"current": "Contraseña actual",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Nombre para mostrar",
"description": "Su nombre tal como aparece en el servidor",
"placeholder": "Ingrese su nombre para mostrar",
"save": "Guardar",
"success": "Nombre para mostrar actualizado",
"error": "No se pudo actualizar el nombre para mostrar"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Sécurité du compte",
"description": "Gérez votre mot de passe, l'authentification à deux facteurs et les paramètres de sécurité",
"detecting": "Détection des capacités du serveur...",
"not_available": "La gestion de la sécurité du compte n'est pas disponible pour ce serveur de messagerie.",
"not_available": "La gestion de la sécurité du compte n'est pas disponible pour ce serveur de messagerie. Les permissions requises peuvent être désactivées. Consultez la <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentation</a> pour plus de détails.",
"password": {
"title": "Changer le mot de passe",
"current": "Mot de passe actuel",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Nom d'affichage",
"description": "Votre nom tel qu'il apparaît sur le serveur",
"placeholder": "Entrez votre nom d'affichage",
"save": "Enregistrer",
"success": "Nom d'affichage mis à jour",
"error": "Impossible de mettre à jour le nom d'affichage"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Sicurezza dell'account",
"description": "Gestisci la tua password, l'autenticazione a due fattori e le impostazioni di sicurezza",
"detecting": "Rilevamento delle funzionalità del server...",
"not_available": "La gestione della sicurezza dell'account non è disponibile per questo server di posta.",
"not_available": "La gestione della sicurezza dell'account non è disponibile per questo server di posta. I permessi richiesti potrebbero essere disabilitati. Consultare la <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentazione</a> per i dettagli.",
"password": {
"title": "Cambia password",
"current": "Password attuale",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Nome visualizzato",
"description": "Il tuo nome come appare sul server",
"placeholder": "Inserisci il tuo nome visualizzato",
"save": "Salva",
"success": "Nome visualizzato aggiornato",
"error": "Impossibile aggiornare il nome visualizzato"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "アカウントセキュリティ",
"description": "パスワード、二要素認証、セキュリティ設定を管理します",
"detecting": "サーバー機能を検出中...",
"not_available": "このメールサーバーではアカウントセキュリティ管理は利用できません。",
"not_available": "このメールサーバーではアカウントセキュリティ管理は利用できません。必要な権限が無効になっている可能性があります。詳細は<a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">ドキュメント</a>を参照してください。",
"password": {
"title": "パスワードの変更",
"current": "現在のパスワード",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "表示名",
"description": "サーバー上に表示される名前",
"placeholder": "表示名を入力",
"save": "保存",
"success": "表示名が更新されました",
"error": "表示名を更新できませんでした"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Accountbeveiliging",
"description": "Beheer uw wachtwoord, tweefactorauthenticatie en beveiligingsinstellingen",
"detecting": "Servermogelijkheden worden gedetecteerd...",
"not_available": "Accountbeveiligingsbeheer is niet beschikbaar voor deze mailserver.",
"not_available": "Accountbeveiligingsbeheer is niet beschikbaar voor deze mailserver. Vereiste machtigingen kunnen zijn uitgeschakeld. Zie de <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentatie</a> voor details.",
"password": {
"title": "Wachtwoord wijzigen",
"current": "Huidig wachtwoord",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Weergavenaam",
"description": "Uw naam zoals weergegeven op de server",
"placeholder": "Voer uw weergavenaam in",
"save": "Opslaan",
"success": "Weergavenaam bijgewerkt",
"error": "Kan weergavenaam niet bijwerken"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Segurança da conta",
"description": "Gerencie sua senha, autenticação de dois fatores e configurações de segurança",
"detecting": "Detectando recursos do servidor...",
"not_available": "O gerenciamento de segurança da conta não está disponível para este servidor de e-mail.",
"not_available": "O gerenciamento de segurança da conta não está disponível para este servidor de e-mail. As permissões necessárias podem estar desabilitadas. Consulte a <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">documentação</a> para obter detalhes.",
"password": {
"title": "Alterar senha",
"current": "Senha atual",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Nome de exibição",
"description": "Seu nome como aparece no servidor",
"placeholder": "Digite seu nome de exibição",
"save": "Salvar",
"success": "Nome de exibição atualizado",
"error": "Não foi possível atualizar o nome de exibição"
+2 -1
View File
@@ -993,7 +993,7 @@
"title": "Безопасность аккаунта",
"description": "Управляйте паролем, двухфакторной аутентификацией и настройками безопасности",
"detecting": "Определение возможностей сервера...",
"not_available": "Управление безопасностью аккаунта недоступно для этого почтового сервера.",
"not_available": "Управление безопасностью аккаунта недоступно для этого почтового сервера. Требуемые разрешения могут быть отключены. Подробнее см. в <a href=\"/docs/guides/account-security\" class=\"underline hover:opacity-80\" target=\"_blank\">документации</a>.",
"password": {
"title": "Изменить пароль",
"current": "Текущий пароль",
@@ -1009,6 +1009,7 @@
"display_name": {
"label": "Отображаемое имя",
"description": "Ваше имя, отображаемое на сервере",
"placeholder": "Введите ваше отображаемое имя",
"save": "Сохранить",
"success": "Отображаемое имя обновлено",
"error": "Не удалось обновить отображаемое имя"