Skip to content

Commit

Permalink
chore: add tests for fallbackToZKEmailDNSArchive
Browse files Browse the repository at this point in the history
  • Loading branch information
saleel committed Oct 10, 2024
1 parent 8c63422 commit b4f42da
Showing 1 changed file with 95 additions and 27 deletions.
122 changes: 95 additions & 27 deletions packages/helpers/tests/dkim.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import fs from 'fs';
import path from 'path';
import { verifyDKIMSignature } from '../src/dkim';
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 @@ -27,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 @@ -43,32 +45,30 @@ 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 user@gmail.com, 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,26 +79,94 @@ 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");
}
});

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"
);

mockResolveDNSHTTP.mockRestore();
});

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 not found for domain domain.com',
"DKIM signature verification failed for domain icloud.com. Reason: DNS failure: Failed due to mock"
);
}
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")
);

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();
});
});

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 b4f42da

Please sign in to comment.