mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 00:07:01 +00:00
fix: count a dkim pass the receiver reports by header.i only (bulwarkmail/webmail#1420)
This commit is contained in:
@@ -85,6 +85,16 @@ describe('getSenderVerification', () => {
|
||||
expect(getSenderVerification(undefined, 'a@bank.example')).toBeNull();
|
||||
});
|
||||
|
||||
it('takes the signing domain from header.i when the receiver writes no header.d (bulwarkmail/webmail#1420)', () => {
|
||||
const from = 'noreply@example.org';
|
||||
expect(getSenderVerification(parseAuthenticationResults('mx.example.net; dkim=pass header.i=@example.org'), from)).toBeNull();
|
||||
expect(getSenderVerification(parseAuthenticationResults('mx; dkim=pass header.i=bounce@mail.example.org'), from)).toBeNull();
|
||||
expect(getSenderVerification(parseAuthenticationResults('mx; dkim=pass header.i=@other.example'), from))
|
||||
.toEqual({ status: 'unverified', domain: 'example.org' });
|
||||
// header.d still wins when both are there.
|
||||
expect(parseAuthenticationResults('mx; dkim=pass header.d=a.example header.i=@b.example').dkim?.domain).toBe('a.example');
|
||||
});
|
||||
|
||||
it('does not count a HELO pass', () => {
|
||||
const auth = parseAuthenticationResults('mx; spf=pass smtp.helo=bank.example; spf=none smtp.mailfrom=bank.example');
|
||||
expect(getSenderVerification(auth, 'a@bank.example')?.status).toBe('unverified');
|
||||
|
||||
@@ -323,6 +323,12 @@ function parseResinfos(header: string): ResInfo[] {
|
||||
.filter((info): info is ResInfo => info !== null);
|
||||
}
|
||||
|
||||
/** The domain of a DKIM identity (`header.i`): `@domain` or `user@domain`. */
|
||||
function identityDomain(identity: string | undefined): string | undefined {
|
||||
const at = identity?.lastIndexOf('@') ?? -1;
|
||||
return identity && at >= 0 && at < identity.length - 1 ? identity.slice(at + 1) : undefined;
|
||||
}
|
||||
|
||||
const DMARC_SEVERITY: Record<string, number> = {
|
||||
fail: 3,
|
||||
permerror: 2,
|
||||
@@ -394,7 +400,9 @@ export function parseAuthenticationResults(headers: string | readonly string[]):
|
||||
.filter((info) => info.method === 'dkim')
|
||||
.map((info) => ({
|
||||
result: info.result as DkimResult,
|
||||
domain: info.props['header.d'],
|
||||
// Some receivers name the signature only by its identity (`header.i`,
|
||||
// `@domain` or `user@domain`, RFC 8601 2.7.1); its domain is the signer's.
|
||||
domain: info.props['header.d'] ?? identityDomain(info.props['header.i']),
|
||||
selector: info.props['header.s'],
|
||||
}));
|
||||
if (dkimResults.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user