import dns from 'dns'; import spfParser from 'spf-parse'; import {SPFValidator} from '../../../modules/spf'; import cidrTools from 'cidr-tools'; import ipRangeCheck from "ip-range-check"; // import dkimVerify from 'python-dkim-verify'; import dmarc from 'dmarc-solution'; function fetchSPFRecordForDomainFromTXT(records) { // console.log("records",records) var spfString = null; try { if (records == undefined) { return "v=spf1 "; } else { for (var i = 0; i < records.length; i++) { if (records[i][0].startsWith('v=spf1')) { var spfRecord = spfParser(records[i][0]); if (spfRecord.valid) { for (var j = 0; j < spfRecord.mechanisms.length; j++) { if (spfRecord.mechanisms[j].prefix == 'v') { spfString = spfRecord.mechanisms[j].prefix + "=" + spfRecord.mechanisms[j].value; continue; } else if (spfRecord.mechanisms[j].type == 'all') { break; } else { if (spfRecord.mechanisms[j].value) spfString = spfString + " " + spfRecord.mechanisms[j].type + ":" + spfRecord.mechanisms[j].value; else spfString = spfString + " " + spfRecord.mechanisms[j].type; } } if (spfString && spfString.includes("all")) break; } } } } return spfString; } catch (err) { console.log(err) return "v=spf1 "; } } function getSPfRecord(domain){ // console.log("getSPfRecord",domain) return new Promise((resolve) => { dns.resolveTxt(domain, async(err, addresses) => { console.log('TXT records:', addresses,err) resolve(await fetchSPFRecordForDomainFromTXT(addresses)) }) }); } function flattenSpfRecord(record, domain, version){ return new Promise((resolve, reject)=> { var sp = new SPFValidator({ 'domain': record, 'expandIncludes': true }) sp.getRecords(record) .then(r => { // console.log("r",r) var ips = []; if(r[record].ip4 && r[record].ip4.length ) ips = cidrTools.merge(r[record].ip4) if(r[record].ip6 && r[record].ip6.length ) ips = ips.concat(cidrTools.merge(r[record].ip6)) if(r[record].ext && r[record].ext.length ) ips = ips.concat(r[record].ext); // console.log("ips",ips); return ips; }) .then(r => { resolve(r) }) .catch(e => { console.log("err",e); reject(e) }) }) } async function checkSpf(senderIp, senderDomain){ let spfRecord = await getSPfRecord(senderDomain) // console.log("spfRecord is",spfRecord) let ips = await flattenSpfRecord(spfRecord) var check = ipRangeCheck(senderIp, ips) ? true : ipRangeCheck(senderIp, ips) // console.log("check is",check) return check ? "Pass" : "Fail"; } async function checkDkim(header){ try { const result = await dkimVerify(header); console.log("result is",result); return result ? "Pass" : "Fail"; } catch (err) { console.error("Error while verifying dkim",err); return "Fail"; } } function fetchDmarcClass(senderDomain){ let aspf = "r"; let adkim = "r"; // Fetcher from DNS return dmarc.fetch(senderDomain) .then(record => { // console.log(record); if(record.tags.aspf) aspf = record.tags.aspf.value; if(record.tags.adkim) adkim = record.tags.adkim.value; return {aspf, adkim} }) .catch(err => { console.log(err); return {aspf, adkim} }); }