Skip to content

Commit

Permalink
helpers: apply sanitizations to email; add removeLabels
Browse files Browse the repository at this point in the history
  • Loading branch information
saleel committed Apr 2, 2024
1 parent 2a72632 commit 32c4cbf
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 19 deletions.
46 changes: 27 additions & 19 deletions packages/helpers/src/dkim/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { pki } from "node-forge";
import { DkimVerifier } from "./dkim-verifier";
import { DkimVerifier } from "./mailauth/dkim-verifier";
import {
getSigningHeaderLines,
parseDkimHeaders,
parseHeaders,
writeToStream,
} from "./tools";
import { revertCommonARCModifications } from "./arc";
} from "./mailauth/tools";
import sanitizers from "./sanitizers";

export interface DKIMVerificationResult {
publicKey: bigint;
Expand All @@ -24,28 +24,36 @@ export interface DKIMVerificationResult {
export async function verifyDKIMSignature(
email: Buffer | string,
domain: string = "",
tryRevertARCChanges: boolean = true
enableSanitization: boolean = true
): Promise<DKIMVerificationResult> {

const emailStr = email.toString();

const pgpMarkers = [
"BEGIN PGP MESSAGE",
"BEGIN PGP SIGNED MESSAGE",
];

const isPGPEncoded = pgpMarkers.some(marker => emailStr.includes(marker));
const pgpMarkers = ["BEGIN PGP MESSAGE", "BEGIN PGP SIGNED MESSAGE"];

const isPGPEncoded = pgpMarkers.some((marker) => emailStr.includes(marker));
if (isPGPEncoded) {
throw new Error("PGP encoded emails are not supported.");
}

let dkimResult = await tryVerifyDKIM(email, domain);

// If DKIM verification fails, revert common modifications made by ARC and try again.
if (dkimResult.status.comment === "bad signature" && tryRevertARCChanges) {
const modified = await revertCommonARCModifications(email.toString());
dkimResult = await tryVerifyDKIM(modified, domain);
// If DKIM verification fails, try again after sanitizing email
if (dkimResult.status.comment === "bad signature" && enableSanitization) {
const results = await Promise.all(
sanitizers.map((sanitize) =>
tryVerifyDKIM(sanitize(emailStr), domain).then((result) => ({
result,
sanitizer: sanitize.name,
}))
)
);

const passed = results.find((r) => r.result.status.result === "pass");

if (passed) {
console.log(`DKIM: Verification passed after applying sanitization "${passed.sanitizer}"`);
dkimResult = passed.result;
}
}

const {
Expand Down Expand Up @@ -141,7 +149,7 @@ export interface Options {
}

// export dkim functions
export * from "./dkim-verifier";
export * from "./message-parser";
export * from "./parse-dkim-headers";
export * from "./tools";
export * from "./mailauth/dkim-verifier";
export * from "./mailauth/message-parser";
export * from "./mailauth/parse-dkim-headers";
export * from "./mailauth/tools";
48 changes: 48 additions & 0 deletions packages/helpers/src/dkim/sanitizers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function getHeaderValue(email: string, header: string) {
const headerStartIndex = email.indexOf(`${header}: `) + header.length + 2;
const headerEndIndex = email.indexOf("\n", headerStartIndex);
const headerValue = email.substring(headerStartIndex, headerEndIndex);

return headerValue;
}

function setHeaderValue(email: string, header: string, value: string) {
return email.replace(getHeaderValue(email, header), value);
}


// Google sets their own Message-ID and put the original one in X-Google-Original-Message-ID
// when ARC forwarding
function revertGoogleMessageId(email: string): string {
// (Optional check) This only happens when google does ARC
if (!email.includes("ARC-Authentication-Results")) {
return email;
}

const googleReplacedMessageId = getHeaderValue(
email,
"X-Google-Original-Message-ID"
);

if (googleReplacedMessageId) {
return setHeaderValue(email, "Message-ID", googleReplacedMessageId);
}

return email;
}

// Remove labels inserted to Subject - `[ListName] Newsletter 2024` to `Newsletter 2024`
function removeLabels(email: string): string {
// Replace Subject: [label] with Subject:
const sanitized = email.replace(/Subject: \[.*\]/, "Subject:");
return sanitized;
}


const sanitizers = [
revertGoogleMessageId,
removeLabels,
];


export default sanitizers;

0 comments on commit 32c4cbf

Please sign in to comment.