fix(07): NTLM support for Exchange EWS + crypto key init timing fix
Tessera CI/CD / Lint & Type Check (push) Waiting to run
Tessera CI/CD / Tests (push) Blocked by required conditions
Tessera CI/CD / Build & Deploy (push) Blocked by required conditions

- ExchangeInboxProvider rewritten to use httpntlm + raw EWS SOAP:
  FindItem / GetItem / GetAttachment via NTLM challenge-response.
  No longer requires Basic Auth on Exchange EWS virtual directory.
  Folder name mapped to EWS DistinguishedFolderId (Inbox/SentItems/etc).
- CalendarCryptoService: move key init from onModuleInit to constructor
  so MailModule.forRootAsync() factory can call decrypt() before NestJS
  lifecycle hooks execute (startup crash when SmtpConfig row has password).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 10:02:48 +02:00
parent 3b2a36cd61
commit a4e03830c1
4 changed files with 330 additions and 200 deletions
+8 -6
View File
@@ -1,4 +1,4 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
@@ -9,14 +9,16 @@ import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
* Encrypted values are stored as `iv:authTag:ciphertext` (hex-joined).
*
* Security: T-05-10 — credentials encrypted at rest, never returned in GET responses.
*
* Key is initialised in the constructor (not onModuleInit) so that async factory
* functions in other modules (e.g. MailModule.forRootAsync) can call decrypt()
* before NestJS lifecycle hooks run.
*/
@Injectable()
export class CalendarCryptoService implements OnModuleInit {
private key!: Buffer;
export class CalendarCryptoService {
private readonly key: Buffer;
constructor(private readonly configService: ConfigService) {}
onModuleInit() {
constructor(private readonly configService: ConfigService) {
const hexKey = this.configService.get<string>('CALENDAR_ENCRYPTION_KEY');
if (!hexKey) {