Files
smartmta/ts/mail/security/classes.dkimverifier.ts
Juergen Kunz b82468ab1e
Some checks failed
CI / Build Test (Current Platform) (push) Failing after 4s
CI / Type Check & Lint (push) Failing after 6s
CI / Build All Platforms (push) Failing after 4s
BREAKING CHANGE(rust-bridge): make Rust the primary security backend, remove all TS fallbacks
Phase 3 of the Rust migration: the Rust security bridge is now mandatory
and all TypeScript security fallback implementations have been removed.

- UnifiedEmailServer.start() throws if Rust bridge fails to start
- SpfVerifier gutted to thin wrapper (parseSpfRecord stays in TS)
- DKIMVerifier gutted to thin wrapper delegating to bridge.verifyDkim()
- IPReputationChecker delegates to bridge.checkIpReputation(), keeps LRU cache
- DmarcVerifier keeps alignment logic (works with pre-computed results)
- DKIM signing via bridge.signDkim() in all 4 locations
- Removed mailauth and ip packages from plugins.ts (~1,200 lines deleted)
2026-02-10 20:30:43 +00:00

87 lines
2.5 KiB
TypeScript

import { logger } from '../../logger.js';
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
import { RustSecurityBridge } from '../../security/classes.rustsecuritybridge.js';
/**
* Result of a DKIM verification
*/
export interface IDkimVerificationResult {
isValid: boolean;
domain?: string;
selector?: string;
status?: string;
details?: any;
errorMessage?: string;
signatureFields?: Record<string, string>;
}
/**
* DKIM verifier — delegates to the Rust security bridge.
*/
export class DKIMVerifier {
constructor() {}
/**
* Verify DKIM signature for an email via Rust bridge
*/
public async verify(
emailData: string,
options: {
useCache?: boolean;
returnDetails?: boolean;
} = {}
): Promise<IDkimVerificationResult> {
try {
const bridge = RustSecurityBridge.getInstance();
const results = await bridge.verifyDkim(emailData);
const first = results[0];
const result: IDkimVerificationResult = {
isValid: first?.is_valid ?? false,
domain: first?.domain ?? undefined,
selector: first?.selector ?? undefined,
status: first?.status ?? 'none',
details: options.returnDetails ? results : undefined,
};
SecurityLogger.getInstance().logEvent({
level: result.isValid ? SecurityLogLevel.INFO : SecurityLogLevel.WARN,
type: SecurityEventType.DKIM,
message: `DKIM verification ${result.isValid ? 'passed' : 'failed'} for domain ${result.domain || 'unknown'}`,
details: { selector: result.selector, status: result.status },
domain: result.domain || 'unknown',
success: result.isValid
});
logger.log(result.isValid ? 'info' : 'warn',
`DKIM verification: ${result.status} for domain ${result.domain || 'unknown'}`);
return result;
} catch (error) {
logger.log('error', `DKIM verification failed: ${error.message}`);
SecurityLogger.getInstance().logEvent({
level: SecurityLogLevel.ERROR,
type: SecurityEventType.DKIM,
message: `DKIM verification error`,
details: { error: error.message },
success: false
});
return {
isValid: false,
status: 'temperror',
errorMessage: `Verification error: ${error.message}`
};
}
}
/** No-op — Rust bridge handles its own caching */
public clearCache(): void {}
/** Always 0 — cache is managed by the Rust side */
public getCacheSize(): number {
return 0;
}
}