diff --git a/.planning/quick/261005-d5d-kalender-test-zeitgrenze/261005-d5d-SUMMARY.md b/.planning/quick/261005-d5d-kalender-test-zeitgrenze/261005-d5d-SUMMARY.md index dca2ba0..76403e6 100644 --- a/.planning/quick/261005-d5d-kalender-test-zeitgrenze/261005-d5d-SUMMARY.md +++ b/.planning/quick/261005-d5d-kalender-test-zeitgrenze/261005-d5d-SUMMARY.md @@ -10,4 +10,4 @@ date: 2026-10-05 - `CalendarSourceUnreachableError` + `isNetworkUnreachableError` (calendar.service.ts); `testConnection`/`testConnectionFromConfig` liefern `error: 'unreachable'`, lastSyncError „Server not reachable“. - Formular: `formTestUnreachable` statt `formTestFailed`. - Nachweis (lokaler Container, kompilierter Provider): 172.16.0.3 -> nicht erreichbar nach 15,0 s; owa.ctl.de mit falschem Passwort -> erreichbar/abgelehnt 0,0 s. Tests api 2219+, web 1372 gruen. -- Gleiches Muster steckt in `inbox/exchange-inbox.provider.ts` (eigenes httpntlm ohne Zeitgrenze) — nicht angefasst. +- Nachtrag (User „fix“): `inbox/exchange-inbox.provider.ts` bekommt denselben Timer, 60 s (laedt PDF-Anhaenge). testConnection meldet dann „EWS server not reachable (no answer within 60 s)“. Unit-Test mit Fake-Timern; echter Lauf nicht wiederholt (gleiche Mechanik wie im Kalender, dort echt gemessen). diff --git a/CHANGELOG.md b/CHANGELOG.md index e20bfa2..13ae104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T ### Behoben - Kalender (Exchange): Ist der Exchange-Server nicht erreichbar, bricht „Verbindung testen“ jetzt nach 15 Sekunden ab, statt rund zwei Minuten auf „Verbindung wird geprüft …“ zu stehen, und meldet „Der Kalender-Server ist nicht erreichbar“ statt des Hinweises auf Adresse und Zugangsdaten. Auch der regelmäßige Abruf im Hintergrund wartet nicht mehr länger als 15 Sekunden. +- Postfach-Abruf über Exchange (E-Mail-Alarme, PDF-Anhänge): Ein nicht erreichbarer Exchange-Server blockiert den Abruf und den Verbindungstest nicht mehr minutenlang, sondern höchstens 60 Sekunden. - Links in Notiz-Kacheln öffnen jetzt immer in einem neuen Tab, statt das Dashboard im selben Fenster zu verlassen. In der Desktop-App öffnen sie wie gewohnt im Browser. ## 1.9.2 – 2026-10-02 diff --git a/apps/api/src/inbox/exchange-inbox.provider.spec.ts b/apps/api/src/inbox/exchange-inbox.provider.spec.ts index 05d4625..5657c36 100644 --- a/apps/api/src/inbox/exchange-inbox.provider.spec.ts +++ b/apps/api/src/inbox/exchange-inbox.provider.spec.ts @@ -128,6 +128,24 @@ beforeEach(() => { httpntlmPost.mockClear(); }); +describe('ExchangeInboxProvider — Zeitgrenze (quick-261005)', () => { + it('testConnection meldet nach 60 s ohne Antwort „nicht erreichbar“ statt zu haengen', async () => { + vi.useFakeTimers(); + try { + httpntlmPost.mockImplementation(() => { + /* ruft nie zurueck — wie ein unbeantworteter Verbindungsaufbau */ + }); + const pending = new ExchangeInboxProvider().testConnection(BASE_CONFIG); + await vi.advanceTimersByTimeAsync(60_000); + const result = await pending; + expect(result.success).toBe(false); + expect(result.message).toContain('not reachable'); + } finally { + vi.useRealTimers(); + } + }); +}); + describe('ExchangeInboxProvider.fetchMessages', () => { it('a BodyType="HTML" GetItem response yields bodyHtml populated and bodyText empty', async () => { mockEwsFlow(getItemHtmlResponse()); diff --git a/apps/api/src/inbox/exchange-inbox.provider.ts b/apps/api/src/inbox/exchange-inbox.provider.ts index 78e4ec5..5c426f8 100644 --- a/apps/api/src/inbox/exchange-inbox.provider.ts +++ b/apps/api/src/inbox/exchange-inbox.provider.ts @@ -258,9 +258,28 @@ interface NtlmResponse { body?: Buffer | string; } +/** + * quick-261005: Obergrenze je EWS-Aufruf. Ohne sie wartete ein Aufruf auf + * eine nicht erreichbare Adresse rund zwei Minuten. 60 s statt der 15 s im + * Kalender, weil hier auch PDF-Anhaenge geladen werden. + */ +const INBOX_EWS_TIMEOUT_MS = 60_000; + function ntlmPost(opts: NtlmOptions): Promise<{ statusCode: number; body: string }> { return new Promise((resolve, reject) => { + // Eigener Timer statt httpreqs `timeout`: dessen Leerlaufgrenze greift + // waehrend des Verbindungsaufbaus ueber den Keep-alive-Agenten von + // httpntlm nicht (gemessen 05.10., siehe calendar/providers/exchange.provider.ts). + const timer = setTimeout(() => { + reject( + Object.assign( + new Error(`EWS server not reachable (no answer within ${INBOX_EWS_TIMEOUT_MS / 1000} s)`), + { code: 'TIMEOUT' }, + ), + ); + }, INBOX_EWS_TIMEOUT_MS); httpntlm.post(opts, (err, res) => { + clearTimeout(timer); if (err) return reject(err); resolve({ statusCode: res.statusCode,