dmarc-solution
Advanced tools
Comparing version 1.0.4 to 1.0.5
@@ -1,28 +0,24 @@ | ||
var dns = require('dns'); | ||
var dns = require("dns").promises; | ||
var fetch = function (domainName) { | ||
return new Promise((resolve, reject) => { | ||
dns.resolveTxt('_dmarc.' + domainName, (err, records) => { | ||
if (err) { | ||
if (err.message && typeof err.message == 'string' && err.message.startsWith('queryTxt ENOTFOUND')) | ||
return reject(new Error('DMARC Record not available')); | ||
return reject(err.message); | ||
var fetch = async function (domainName) { | ||
let records = await dns.resolveTxt("_dmarc." + domainName).catch(console.error); | ||
if (!records) { | ||
if (err.message && typeof err.message == "string" && err.message.startsWith("queryTxt ENOTFOUND")) | ||
throw new Error("DMARC Record not available"); | ||
throw new Error(err.message); | ||
} | ||
var record = null; | ||
for (var i = 0; i < records.length; i++) { | ||
for (var j = 0; j < records[i].length; j++) { | ||
if (records[i][j].startsWith("v=DMARC")) { | ||
record = records[i][j]; | ||
break; | ||
} | ||
var record = null; | ||
for (var i = 0; i < records.length; i++) { | ||
for (var j = 0; j < records[i].length; j++) { | ||
if (records[i][j].startsWith('v=DMARC')) { | ||
record = records[i][j]; | ||
break; | ||
} | ||
} | ||
if (record && records[i].length > 0) record = records[i].join("") | ||
if (record != null) | ||
break; | ||
} | ||
if (record == null) return reject(new Error('DMARC Record not available')); | ||
return resolve(record); | ||
}); | ||
}) | ||
} | ||
module.exports = fetch; | ||
} | ||
if (record && records[i].length > 0) record = records[i].join(""); | ||
if (record != null) break; | ||
} | ||
if (record == null) return reject(new Error("DMARC Record not available")); | ||
return record; | ||
}; | ||
module.exports = fetch; |
@@ -1,2 +0,2 @@ | ||
var validators = require('./validator'); | ||
var validators = require("./validator"); | ||
@@ -6,9 +6,9 @@ var generate = function (values) { | ||
if (values.v == undefined) { | ||
throw new Error('DMARC Version is required tag'); | ||
throw new Error("DMARC Version is required tag"); | ||
} | ||
validators.v.validate.call(validators.v, 'v', values.v); | ||
record.push('v=' + values.v); | ||
validators.v.validate.call(validators.v, "v", values.v); | ||
record.push("v=" + values.v); | ||
for (var i = 0; i < Object.keys(values).length; i++) { | ||
var term = Object.keys(values)[i]; | ||
if (term === 'v') continue; | ||
if (term === "v") continue; | ||
if (validators[term]) { | ||
@@ -24,5 +24,5 @@ let settings = validators[term]; | ||
} | ||
return record.join('; '); | ||
} | ||
return record.join("; "); | ||
}; | ||
module.exports = generate; | ||
module.exports = generate; |
@@ -1,3 +0,3 @@ | ||
'use strict'; | ||
var validators = require('./validator'); | ||
"use strict"; | ||
var validators = require("./validator"); | ||
@@ -9,14 +9,12 @@ function parse(policy) { | ||
let terms = policy.split(/;/) | ||
.map(t => t.trim()) // Trim surrounding whitespace | ||
.filter(x => x !== ''); // Ignore empty tags | ||
let terms = policy | ||
.split(/;/) | ||
.map((t) => t.trim()) // Trim surrounding whitespace | ||
.filter((x) => x !== ""); // Ignore empty tags | ||
let rules = terms.map( | ||
x => x.split(/[=]/) | ||
.map(p => p.trim()) | ||
); | ||
let rules = terms.map((x) => x.split(/[=]/).map((p) => p.trim())); | ||
let retval = { | ||
tags: {}, | ||
messages: [] | ||
messages: [], | ||
}; | ||
@@ -41,3 +39,3 @@ | ||
debugger; | ||
let termRegex = new RegExp(`^${validatorTerm}$`, 'i'); | ||
let termRegex = new RegExp(`^${validatorTerm}$`, "i"); | ||
if (termRegex.test(term)) { | ||
@@ -48,3 +46,3 @@ found = true; | ||
// tag: term, | ||
description: settings.description | ||
description: settings.description, | ||
}; | ||
@@ -57,4 +55,3 @@ | ||
retval.tags[term] = tag; | ||
} | ||
catch (err) { | ||
} catch (err) { | ||
retval.messages.push(err.message); | ||
@@ -81,2 +78,2 @@ } | ||
module.exports = parse; | ||
module.exports = parse; |
@@ -1,2 +0,2 @@ | ||
const validator = require('email-validator'); | ||
const validator = require("email-validator"); | ||
@@ -6,13 +6,13 @@ const validators = { | ||
required: true, | ||
description: 'The v tag is required and represents the protocol version. An example is v=DMARC1', | ||
description: "The v tag is required and represents the protocol version. An example is v=DMARC1", | ||
validate(term, value) { | ||
if (value !== 'DMARC1') { | ||
if (value !== "DMARC1") { | ||
throw new Error(`Invalid DMARC version: '${value}'`); | ||
} | ||
} | ||
}, | ||
}, | ||
fo: { | ||
description: 'The FO tag pertains to how forensic reports are created and presented to DMARC users.', | ||
description: "The FO tag pertains to how forensic reports are created and presented to DMARC users.", | ||
validate(term, originalValue) { | ||
var value = originalValue.split(':'); | ||
var value = originalValue.split(":"); | ||
if (value.length <= 4) { | ||
@@ -34,9 +34,9 @@ if (!/^([01ds])$/i.test(value[0])) { | ||
generate(value) { | ||
if (value && value.length) | ||
return value.join(':'); | ||
throw new Error("Invalid for 'fo' tag") | ||
} | ||
if (value && value.length) return value.join(":"); | ||
throw new Error("Invalid for 'fo' tag"); | ||
}, | ||
}, | ||
p: { | ||
description: 'The required p tag demonstrates the policy for domain (or requested handling policy). It directs the receiver to report, quarantine, or reject emails that fail authentication checks. Policy options are: 1) None 2) Quarantine or 3) Reject.', | ||
description: | ||
"The required p tag demonstrates the policy for domain (or requested handling policy). It directs the receiver to report, quarantine, or reject emails that fail authentication checks. Policy options are: 1) None 2) Quarantine or 3) Reject.", | ||
validate(term, value) { | ||
@@ -46,3 +46,3 @@ if (!/^(none|quarantine|reject)$/i.test(value)) { | ||
} | ||
} | ||
}, | ||
}, | ||
@@ -54,7 +54,6 @@ pct: { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a positive integer`); | ||
} | ||
else if (parseInt(value, 10) > 100 || parseInt(value, 10) < 0) { | ||
} else if (parseInt(value, 10) > 100 || parseInt(value, 10) < 0) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be an integer between 0 and 100`); | ||
} | ||
} | ||
}, | ||
}, | ||
@@ -65,13 +64,15 @@ rf: { | ||
// The RFC says the values are colon-separated but a lot of examples/docs around the net show commas... so we'll do both | ||
let values = value.split(/,|:/).map(x => x.trim()); | ||
let values = value.split(/,|:/).map((x) => x.trim()); | ||
for (let val of values) { | ||
if (!/^(afrf|iodef)$/i.test(val)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one or more of these values: afrf, iodef. Multiple values must be separated by a comma or colon`); | ||
throw new Error( | ||
`Invalid value for '${term}': '${value}', must be one or more of these values: afrf, iodef. Multiple values must be separated by a comma or colon` | ||
); | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
ri: { | ||
description: 'The ri tag corresponds to the aggregate reporting interval and provides DMARC feedback for the outlined criteria.', | ||
description: "The ri tag corresponds to the aggregate reporting interval and provides DMARC feedback for the outlined criteria.", | ||
validate(term, value) { | ||
@@ -81,8 +82,8 @@ if (!/^\d+$/.test(value)) { | ||
} | ||
} | ||
}, | ||
}, | ||
rua: { | ||
description: 'This optional tag is designed for reporting URI(s) for aggregate data. An rua example is rua=mailto:CUSTOMER@for.example.com.', | ||
description: "This optional tag is designed for reporting URI(s) for aggregate data. An rua example is rua=mailto:CUSTOMER@for.example.com.", | ||
validate(term, value) { | ||
let values = value.split(/,/).map(x => x.trim()); | ||
let values = value.split(/,/).map((x) => x.trim()); | ||
@@ -104,16 +105,16 @@ for (let val of values) { | ||
for (var i = 0; i < value.length; i++) { | ||
if (typeof value[i] === 'string') { | ||
if (!value[i].startsWith('mailto:')) | ||
value[i] = 'mailto:' + value[i]; | ||
if (mailtoList.indexOf(value[i]) == -1) mailtoList.push(value[i]) | ||
if (typeof value[i] === "string") { | ||
if (!value[i].startsWith("mailto:")) value[i] = "mailto:" + value[i]; | ||
if (mailtoList.indexOf(value[i]) == -1) mailtoList.push(value[i]); | ||
} else throw new Error("Invalid Email: '" + value[i] + "' for 'rua' tag"); | ||
} | ||
return mailtoList.join(','); | ||
} else throw new Error(`Invalid value for 'rua' tag`) | ||
} | ||
return mailtoList.join(","); | ||
} else throw new Error(`Invalid value for 'rua' tag`); | ||
}, | ||
}, | ||
ruf: { | ||
description: 'Like the rua tag, the ruf designation is an optional tag. It directs addresses to which message-specific forensic information is to be reported (i.e., comma-separated plain-text list of URIs). An ruf example is ruf=mailto:CUSTOMER@for.example.com.', | ||
description: | ||
"Like the rua tag, the ruf designation is an optional tag. It directs addresses to which message-specific forensic information is to be reported (i.e., comma-separated plain-text list of URIs). An ruf example is ruf=mailto:CUSTOMER@for.example.com.", | ||
validate(term, value) { | ||
let values = value.split(/,/).map(x => x.trim()); | ||
let values = value.split(/,/).map((x) => x.trim()); | ||
@@ -135,11 +136,10 @@ for (let val of values) { | ||
for (var i = 0; i < value.length; i++) { | ||
if (typeof value[i] === 'string') { | ||
if (!value[i].startsWith('mailto:')) | ||
value[i] = 'mailto:' + value[i]; | ||
if (mailtoList.indexOf(value[i]) == -1) mailtoList.push(value[i]) | ||
if (typeof value[i] === "string") { | ||
if (!value[i].startsWith("mailto:")) value[i] = "mailto:" + value[i]; | ||
if (mailtoList.indexOf(value[i]) == -1) mailtoList.push(value[i]); | ||
} else throw new Error("Invalid Email: '" + value[i] + "' for 'ruf' tag"); | ||
} | ||
return mailtoList.join(','); | ||
} else throw new Error(`Invalid value for 'ruf' tag`) | ||
} | ||
return mailtoList.join(","); | ||
} else throw new Error(`Invalid value for 'ruf' tag`); | ||
}, | ||
}, | ||
@@ -152,6 +152,6 @@ sp: { | ||
} | ||
} | ||
}, | ||
}, | ||
aspf: { | ||
description: 'The aspf tag represents alignment mode for SPF. An optional tag, aspf=r is a common example of its configuration.', | ||
description: "The aspf tag represents alignment mode for SPF. An optional tag, aspf=r is a common example of its configuration.", | ||
validate(term, value) { | ||
@@ -161,6 +161,6 @@ if (!/^(s|r)$/i.test(value)) { | ||
} | ||
} | ||
}, | ||
}, | ||
adkim: { | ||
description: 'Similar to aspf, the optional adkim tag is the alignment mode for the DKIM protocol. A sample tag is adkim=r.', | ||
description: "Similar to aspf, the optional adkim tag is the alignment mode for the DKIM protocol. A sample tag is adkim=r.", | ||
validate(term, value) { | ||
@@ -170,6 +170,6 @@ if (!/^(s|r)$/i.test(value)) { | ||
} | ||
} | ||
} | ||
}, | ||
}, | ||
}; | ||
module.exports = validators; | ||
module.exports = validators; |
53
index.js
@@ -1,40 +0,23 @@ | ||
var parser = require('./bin/parser'); | ||
var fetcher = require('./bin/fetcher'); | ||
var generator = require('./bin/generator'); | ||
var parser = require("./bin/parser"); | ||
var fetcher = require("./bin/fetcher"); | ||
var generator = require("./bin/generator"); | ||
var recordParser = function (dmarcRecord) { | ||
return new Promise((resolve, reject) => { | ||
var result = parser(dmarcRecord); | ||
if (result.messages && result.messages.length) return reject(result.messages); | ||
resolve(result.tags); | ||
}); | ||
} | ||
var recordParser = async function (dmarcRecord) { | ||
var result = parser(dmarcRecord); | ||
if (result.messages && result.messages.length) throw new Error(result.messages); | ||
return result.tags; | ||
}; | ||
var recordFetcher = function (domainName) { | ||
return new Promise((resolve, reject) => { | ||
return fetcher(domainName) | ||
.then(record => { | ||
return recordParser(record).then(r => [r, record]); | ||
}) | ||
.then(([data, record]) => { | ||
resolve({ record: record, tags: data }); | ||
}) | ||
.catch(err => { | ||
reject(err); | ||
}) | ||
}) | ||
} | ||
var recordFetcher = async function (domainName) { | ||
let record = await fetcher(domainName); | ||
let data = await recordParser(record); | ||
return { record: record, tags: data }; | ||
}; | ||
var recordGenerator = async function (values) { | ||
return generator(values); | ||
}; | ||
var recordGenerator = function (values) { | ||
return new Promise((resolve, reject) => { | ||
try { | ||
resolve(generator(values)) | ||
} catch (err) { | ||
reject(err.message) | ||
} | ||
}) | ||
} | ||
exports.parse = recordParser; | ||
exports.fetch = recordFetcher; | ||
exports.generate = recordGenerator; | ||
exports.generate = recordGenerator; |
{ | ||
"name": "dmarc-solution", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "One stop solution for all DMARC Problems. This package includes fetching of dmarc record, parsing the provided/fetched record, validation of DMARC record, generating a new DMARC record", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
9
14375
283