Skip to content

Commit

Permalink
chore: refactor fallback tests
Browse files Browse the repository at this point in the history
  • Loading branch information
saleel committed Oct 10, 2024
1 parent 4e692ff commit c8e98af
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 88 deletions.
2 changes: 1 addition & 1 deletion packages/helpers/src/dkim/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export async function verifyDKIMSignature(

if (passed) {
console.log(
`DKIM: Verification passed after applying sanitization "${passed.sanitizer}"`
`DKIM: Verification passed after applying sanitization "${passed.sanitizer}"`,
);
dkimResult = passed.result;
appliedSanitization = passed.sanitizer;
Expand Down
178 changes: 91 additions & 87 deletions packages/helpers/tests/dkim.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import fs from "fs";
import path from "path";
import { verifyDKIMSignature } from "../src/dkim";
import * as dnsOverHttp from "../src/dkim/dns-over-http";
import * as dnsArchive from "../src/dkim/dns-archive";
import fs from 'fs';
import path from 'path';
import { verifyDKIMSignature } from '../src/dkim';
import * as dnsOverHttp from '../src/dkim/dns-over-http';
import * as dnsArchive from '../src/dkim/dns-archive';

jest.setTimeout(10000);

describe("DKIM signature verification", () => {
it("should pass for valid email", async () => {
describe('DKIM signature verification', () => {
it('should pass for valid email', async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
path.join(__dirname, 'test-data/email-good.eml'),
);

const result = await verifyDKIMSignature(email);

expect(result.signingDomain).toBe("icloud.com");
expect(result.signingDomain).toBe('icloud.com');
expect(result.appliedSanitization).toBeFalsy();
});

it("should fail for invalid selector", async () => {
it('should fail for invalid selector', async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-invalid-selector.eml")
path.join(__dirname, 'test-data/email-invalid-selector.eml'),
);

expect.assertions(1);
Expand All @@ -29,14 +29,14 @@ describe("DKIM signature verification", () => {
await verifyDKIMSignature(email);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: no key"
'DKIM signature verification failed for domain icloud.com. Reason: no key',
);
}
});

it("should fail for tampered body", async () => {
it('should fail for tampered body', async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-body-tampered.eml")
path.join(__dirname, 'test-data/email-body-tampered.eml'),
);

expect.assertions(1);
Expand All @@ -45,30 +45,32 @@ describe("DKIM signature verification", () => {
await verifyDKIMSignature(email);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: body hash did not verify"
'DKIM signature verification failed for domain icloud.com. Reason: body hash did not verify',
);
}
});

it("should fail for when DKIM signature is not present for domain", async () => {
it('should fail for when DKIM signature is not present for domain', async () => {
// In this email From address is [email protected], but the DKIM signature is only for icloud.com
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-invalid-domain.eml")
path.join(__dirname, 'test-data/email-invalid-domain.eml'),
);

expect.assertions(1);

try {
await verifyDKIMSignature(email);
} catch (e) {
expect(e.message).toBe("DKIM signature not found for domain gmail.com");
expect(e.message).toBe(
'DKIM signature not found for domain gmail.com',
);
}
});

it("should be able to override domain", async () => {
it('should be able to override domain', async () => {
// From address domain is icloud.com
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-different-domain.eml")
path.join(__dirname, 'test-data/email-different-domain.eml'),
);

// Should pass with default domain
Expand All @@ -79,94 +81,96 @@ describe("DKIM signature verification", () => {
// different from From domain and the below check pass.
expect.assertions(1);
try {
await verifyDKIMSignature(email, "domain.com");
await verifyDKIMSignature(email, 'domain.com');
} catch (e) {
expect(e.message).toBe("DKIM signature not found for domain domain.com");
expect(e.message).toBe(
'DKIM signature not found for domain domain.com',
);
}
});
});

it("should fallback to ZK Email Archive if DNS over HTTP fails", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
);

// Mock resolveDNSHTTP to throw an error just for this test
const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));

const consoleSpy = jest.spyOn(console, "log");
await verifyDKIMSignature(email, "icloud.com", true, true);

// Check if the error was logged to ensure fallback to ZK Email Archive happened
expect(consoleSpy).toHaveBeenCalledWith(
"DNS over HTTP failed, falling back to ZK Email Archive"
);
it("should fallback to ZK Email Archive if DNS over HTTP fails", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
);

mockResolveDNSHTTP.mockRestore();
});
// Mock resolveDNSHTTP to throw an error just for this test
const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));

it("should fail on DNS over HTTP failure if fallback is not enabled", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
);
const consoleSpy = jest.spyOn(console, "log");
await verifyDKIMSignature(email, "icloud.com", true, true);

// Mock resolveDNSHTTP to throw an error just for this test
const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));
// Check if the error was logged to ensure fallback to ZK Email Archive happened
expect(consoleSpy).toHaveBeenCalledWith(
"DNS over HTTP failed, falling back to ZK Email Archive"
);

expect.assertions(1);
try {
await verifyDKIMSignature(email, "icloud.com", true, false);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: DNS failure: Failed due to mock"
);
}
mockResolveDNSHTTP.mockRestore();
});
mockResolveDNSHTTP.mockRestore();
});

it("should fail if both DNS over HTTP and ZK Email Archive fail", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
it("should fail on DNS over HTTP failure if fallback is not enabled", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
);

// Mock resolveDNSHTTP to throw an error just for this test
const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));

expect.assertions(1);
try {
await verifyDKIMSignature(email, "icloud.com", true, false);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: DNS failure: Failed due to mock"
);
}
mockResolveDNSHTTP.mockRestore();
});

const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));

const mockResolveDNSFromZKEmailArchive = jest
.spyOn(dnsArchive, "resolveDNSFromZKEmailArchive")
.mockRejectedValue(new Error("Failed due to mock"));

expect.assertions(1);
try {
await verifyDKIMSignature(email, "icloud.com", true, false);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: DNS failure: Failed due to mock"
);
}
it("should fail if both DNS over HTTP and ZK Email Archive fail", async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
);

const mockResolveDNSHTTP = jest
.spyOn(dnsOverHttp, "resolveDNSHTTP")
.mockRejectedValue(new Error("Failed due to mock"));

const mockResolveDNSFromZKEmailArchive = jest
.spyOn(dnsArchive, "resolveDNSFromZKEmailArchive")
.mockRejectedValue(new Error("Failed due to mock"));

expect.assertions(1);
try {
await verifyDKIMSignature(email, "icloud.com", true, false);
} catch (e) {
expect(e.message).toBe(
"DKIM signature verification failed for domain icloud.com. Reason: DNS failure: Failed due to mock"
);
}

mockResolveDNSHTTP.mockRestore();
mockResolveDNSFromZKEmailArchive.mockRestore();
});
mockResolveDNSHTTP.mockRestore();
mockResolveDNSFromZKEmailArchive.mockRestore();
});

describe("DKIM with sanitization", () => {
it("should pass after removing label from Subject", async () => {
describe('DKIM with sanitization', () => {
it('should pass after removing label from Subject', async () => {
const email = fs.readFileSync(
path.join(__dirname, "test-data/email-good.eml")
path.join(__dirname, 'test-data/email-good.eml'),
);

// Add a label to the subject
const tamperedEmail = email
.toString()
.replace("Subject: ", "Subject: [EmailListABC]");
const tamperedEmail = email.toString().replace('Subject: ', 'Subject: [EmailListABC]');

const result = await verifyDKIMSignature(tamperedEmail);

expect(result.appliedSanitization).toBe("removeLabels");
expect(result.appliedSanitization).toBe('removeLabels');
});
});
});

0 comments on commit c8e98af

Please sign in to comment.