diff --git a/packages/helpers/src/dkim/dns-archive.ts b/packages/helpers/src/dkim/dns-archive.ts index 0eb84c60..964fd9b7 100644 --- a/packages/helpers/src/dkim/dns-archive.ts +++ b/packages/helpers/src/dkim/dns-archive.ts @@ -1,18 +1,18 @@ -import { CustomError } from "../lib/mailauth/tools"; +import { CustomError } from '../lib/mailauth/tools'; -const ZKEMAIL_DNS_ARCHIVER_API = "https://archive.prove.email/api/key"; +const ZKEMAIL_DNS_ARCHIVER_API = 'https://archive.prove.email/api/key'; export async function resolveDNSFromZKEmailArchive(name: string, type: string) { - if (type !== "TXT") { + if (type !== 'TXT') { throw new Error(`ZK Email Archive only supports TXT records - got ${type}`); } // Get domain from full dns record name - $selector._domainkey.$domain.com - const domain = name.split(".").slice(-2).join("."); - const selector = name.split(".")[0]; + const domain = name.split('.').slice(-2).join('.'); + const selector = name.split('.')[0]; const queryUrl = new URL(ZKEMAIL_DNS_ARCHIVER_API); - queryUrl.searchParams.set("domain", domain); + queryUrl.searchParams.set('domain', domain); const resp = await fetch(queryUrl); const data = await resp.json(); @@ -22,7 +22,7 @@ export async function resolveDNSFromZKEmailArchive(name: string, type: string) { if (!dkimRecord) { throw new CustomError( `DKIM record not found for domain ${domain} and selector ${selector} in ZK Email Archive.`, - "ENODATA" + 'ENODATA', ); } diff --git a/packages/helpers/src/dkim/dns-over-http.ts b/packages/helpers/src/dkim/dns-over-http.ts index ad09aa31..3481c1dd 100644 --- a/packages/helpers/src/dkim/dns-over-http.ts +++ b/packages/helpers/src/dkim/dns-over-http.ts @@ -1,11 +1,11 @@ -import { CustomError } from "../lib/mailauth/tools"; +import { CustomError } from '../lib/mailauth/tools'; // DoH servers list export enum DoHServer { // Google Public DNS - Google = "https://dns.google/resolve", + Google = 'https://dns.google/resolve', // Cloudflare DNS - Cloudflare = "https://cloudflare-dns.com/dns-query", + Cloudflare = 'https://cloudflare-dns.com/dns-query', } /** @@ -17,6 +17,7 @@ export enum DoHServer { export class DoH { // DNS response codes static DoHStatusNoError = 0; + // DNS RR types static DoHTypeTXT = 16; @@ -25,54 +26,53 @@ export class DoH { * * @static * @param {string} name DKIM record name (e.g. 20230601._domainkey.gmail.com) - * @param {string} DNSServer DNS over HTTPS API URL + * @param {string} dnsServerURL DNS over HTTPS API URL * @return {*} {(Promise)} DKIM public key or null if not found * @memberof DoH */ public static async resolveDKIMPublicKey( name: string, - DNSServer: string + dnsServerURL: string ): Promise { - if (!DNSServer.startsWith("https://")) { - DNSServer = "https://" + DNSServer; + let cleanURL = dnsServerURL; + if (!cleanURL.startsWith('https://')) { + cleanURL = `https://${cleanURL}`; } - if (DNSServer.endsWith("/")) { - DNSServer = DNSServer.slice(0, -1); + if (cleanURL.endsWith('/')) { + cleanURL = cleanURL.slice(0, -1); } - const resp = await fetch( - DNSServer + - "?" + - new URLSearchParams({ - name: name, - // DKIM public key record type is TXT - type: DoH.DoHTypeTXT.toString(), - }), - { + + const queryUrl = new URL(cleanURL); + queryUrl.searchParams.set('name', name); + queryUrl.searchParams.set('type', DoH.DoHTypeTXT.toString()); + + const resp = await fetch(queryUrl, { headers: { - accept: "application/dns-json", + accept: 'application/dns-json', }, } ); + if (resp.status === 200) { const out = await resp.json(); if ( - typeof out === "object" && + typeof out === 'object' && out !== null && - "Status" in out && - "Answer" in out + 'Status' in out && + 'Answer' in out ) { - const resp = out as DoHResponse; - if (resp.Status === DoH.DoHStatusNoError && resp.Answer.length > 0) { - for (const ans of resp.Answer) { + const result = out as DoHResponse; + if (result.Status === DoH.DoHStatusNoError && result.Answer.length > 0) { + for (const ans of result.Answer) { if (ans.type === DoH.DoHTypeTXT) { let DKIMRecord = ans.data; /* - Remove all double quotes - Some DNS providers wrap TXT records in double quotes, - and others like Cloudflare may include them. According to - TXT (potentially multi-line) and DKIM (Base64 data) standards, - we can directly remove all double quotes from the DKIM public key. - */ + Remove all double quotes + Some DNS providers wrap TXT records in double quotes, + and others like Cloudflare may include them. According to + TXT (potentially multi-line) and DKIM (Base64 data) standards, + we can directly remove all double quotes from the DKIM public key. + */ DKIMRecord = DKIMRecord.replace(/"/g, ""); return DKIMRecord; } @@ -107,12 +107,12 @@ interface Answer { } export async function resolveDNSHTTP(name: string, type: string) { - if (type !== "TXT") { + if (type !== 'TXT') { throw new Error(`DNS over HTTP: Only type TXT is supported, got ${type}`); } const googleResult = await DoH.resolveDKIMPublicKey(name, DoHServer.Google); if (!googleResult) { - throw new CustomError("No DKIM record found in Google", "ENODATA"); + throw new CustomError('No DKIM record found in Google', 'ENODATA'); } const cloudflareResult = await DoH.resolveDKIMPublicKey( @@ -123,7 +123,7 @@ export async function resolveDNSHTTP(name: string, type: string) { // Log an error if there is a mismatch in the result if (googleResult !== cloudflareResult) { console.error( - "DKIM record mismatch between Google and Cloudflare! Using Google result." + 'DKIM record mismatch between Google and Cloudflare! Using Google result.' ); }