feat(mailer-smtp): add SCRAM-SHA-256 auth, Ed25519 DKIM, opportunistic TLS, SNI cert selection, pipelining and delivery/bridge improvements

This commit is contained in:
2026-02-11 10:11:43 +00:00
parent 7908cbaefa
commit b10597fd5e
28 changed files with 1849 additions and 153 deletions

View File

@@ -115,7 +115,7 @@ export class DKIMCreator {
}
}
// Create a DKIM key pair - changed to public for API access
// Create an RSA DKIM key pair - changed to public for API access
public async createDKIMKeys(): Promise<{ privateKey: string; publicKey: string }> {
const { privateKey, publicKey } = await generateKeyPair('rsa', {
modulusLength: 2048,
@@ -126,6 +126,16 @@ export class DKIMCreator {
return { privateKey, publicKey };
}
// Create an Ed25519 DKIM key pair (RFC 8463)
public async createEd25519Keys(): Promise<{ privateKey: string; publicKey: string }> {
const { privateKey, publicKey } = await generateKeyPair('ed25519', {
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
});
return { privateKey, publicKey };
}
// Store a DKIM key pair - uses storage manager if available, else disk
public async storeDKIMKeys(
privateKey: string,
@@ -176,8 +186,11 @@ export class DKIMCreator {
.replace(pemFooter, '')
.replace(/\n/g, '');
// Detect key type from PEM header
const keyAlgo = keys.privateKey.includes('ED25519') || keys.publicKey.length < 200 ? 'ed25519' : 'rsa';
// Now generate the DKIM DNS TXT record
const dnsRecordValue = `v=DKIM1; h=sha256; k=rsa; p=${keyContents}`;
const dnsRecordValue = `v=DKIM1; h=sha256; k=${keyAlgo}; p=${keyContents}`;
return {
name: `mta._domainkey.${domainArg}`,
@@ -375,8 +388,11 @@ export class DKIMCreator {
.replace(pemFooter, '')
.replace(/\n/g, '');
// Detect key type from PEM header
const keyAlgo = keys.privateKey.includes('ED25519') || keys.publicKey.length < 200 ? 'ed25519' : 'rsa';
// Generate the DKIM DNS TXT record
const dnsRecordValue = `v=DKIM1; h=sha256; k=rsa; p=${keyContents}`;
const dnsRecordValue = `v=DKIM1; h=sha256; k=${keyAlgo}; p=${keyContents}`;
return {
name: `${selector}._domainkey.${domain}`,