dmarc-solution
Advanced tools
Comparing version 1.0.2 to 1.0.3
var dns = require('dns'); | ||
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 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 != null) | ||
break; | ||
} | ||
if(record == null) return reject(new Error('DMARC Record not available')); | ||
return resolve(record); | ||
}); | ||
}) | ||
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 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 != null) | ||
break; | ||
} | ||
if (record == null) return reject(new Error('DMARC Record not available')); | ||
return resolve(record); | ||
}); | ||
}) | ||
} | ||
module.exports = fetch; |
var validators = require('./validator'); | ||
var generate = function (values){ | ||
var record = []; | ||
if(values.v == undefined){ | ||
throw new Error('DMARC Version is required tag'); | ||
} | ||
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(validators[term]) { | ||
let settings = validators[term]; | ||
var value = null; | ||
if(settings.generate){ | ||
value = settings.generate(values[term]); | ||
}else value = values[term]; | ||
settings.validate.call(settings, term, value); | ||
record.push(term + "=" + value); | ||
} | ||
} | ||
return record.join('; '); | ||
var generate = function (values) { | ||
var record = []; | ||
if (values.v == undefined) { | ||
throw new Error('DMARC Version is required tag'); | ||
} | ||
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 (validators[term]) { | ||
let settings = validators[term]; | ||
var value = null; | ||
if (settings.generate) { | ||
value = settings.generate(values[term]); | ||
} else value = values[term]; | ||
settings.validate.call(settings, term, value); | ||
record.push(term + "=" + value); | ||
} | ||
} | ||
return record.join('; '); | ||
} | ||
module.exports = generate; |
@@ -5,74 +5,74 @@ 'use strict'; | ||
function parse(policy) { | ||
// Steps | ||
// 1. Split policy string on semicolons into term pairs | ||
// 2. Process and validate each term pair | ||
// Steps | ||
// 1. Split policy string on semicolons into term pairs | ||
// 2. Process and validate each term pair | ||
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: [] | ||
}; | ||
let retval = { | ||
tags: {}, | ||
messages: [] | ||
}; | ||
// Make sure `v` is the first tag | ||
if (!/^v$/i.test(rules[0][0])) { | ||
retval.messages.push(`First tag in a DMARC policy must be 'v', but found: '${rules[0][0]}'`); | ||
return retval; | ||
} | ||
// Make sure `v` is the first tag | ||
if (!/^v$/i.test(rules[0][0])) { | ||
retval.messages.push(`First tag in a DMARC policy must be 'v', but found: '${rules[0][0]}'`); | ||
return retval; | ||
} | ||
for (let rule of rules) { | ||
let term = rule[0]; | ||
let value = rule[1]; | ||
for (let rule of rules) { | ||
let term = rule[0]; | ||
let value = rule[1]; | ||
let found = false; | ||
let found = false; | ||
for (let validatorTerm of Object.keys(validators)) { | ||
let settings = validators[validatorTerm]; | ||
for (let validatorTerm of Object.keys(validators)) { | ||
let settings = validators[validatorTerm]; | ||
// Term matches validaor | ||
debugger; | ||
let termRegex = new RegExp(`^${validatorTerm}$`, 'i'); | ||
if (termRegex.test(term)) { | ||
found = true; | ||
// Term matches validaor | ||
debugger; | ||
let termRegex = new RegExp(`^${validatorTerm}$`, 'i'); | ||
if (termRegex.test(term)) { | ||
found = true; | ||
let tag = { | ||
// tag: term, | ||
description: settings.description | ||
}; | ||
let tag = { | ||
// tag: term, | ||
description: settings.description | ||
}; | ||
if (settings.validate) { | ||
try { | ||
settings.validate.call(settings, term, value); | ||
tag.value = value; | ||
retval.tags[term] = tag; | ||
} | ||
catch (err) { | ||
retval.messages.push(err.message); | ||
} | ||
} | ||
if (settings.validate) { | ||
try { | ||
settings.validate.call(settings, term, value); | ||
tag.value = value; | ||
retval.tags[term] = tag; | ||
} | ||
catch (err) { | ||
retval.messages.push(err.message); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
if (!found) { | ||
retval.messages.push(`Unknown tag '${term}'`); | ||
} | ||
} | ||
if (!found) { | ||
retval.messages.push(`Unknown tag '${term}'`); | ||
} | ||
} | ||
// Remove "messages" | ||
if (retval.messages.length === 0) { | ||
delete retval.messages; | ||
} | ||
// Remove "messages" | ||
if (retval.messages.length === 0) { | ||
delete retval.messages; | ||
} | ||
return retval; | ||
return retval; | ||
} | ||
module.exports = parse; |
const validator = require('email-validator'); | ||
const validators = { | ||
v: { | ||
required: true, | ||
description: 'The v tag is required and represents the protocol version. An example is v=DMARC1', | ||
validate(term, value) { | ||
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.', | ||
validate(term, originalValue) { | ||
var value = originalValue.split(':'); | ||
if(value.length <= 4){ | ||
if(!/^([01ds])$/i.test(value[0])){ | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if(value.length > 1 && !/^([01ds])$/i.test(value[1])){ | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if(value.length > 2 && !/^([01ds])$/i.test(value[2])){ | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if(value.length > 3 && !/^([01ds])$/i.test(value[3])){ | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
} | ||
}, | ||
generate(value) { | ||
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.', | ||
validate(term, value) { | ||
if (!/^(none|quarantine|reject)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of: none, quarantine, reject`); | ||
} | ||
} | ||
}, | ||
pct: { | ||
description: `This DMARC tag specifies the percentage of email messages subjected to filtering. For example, pct=25 means a quarter of your company’s emails will be filtered by the recipient.`, | ||
validate(term, value) { | ||
if (!/^\d+$/.test(value)) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a positive integer`); | ||
} | ||
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`); | ||
} | ||
} | ||
}, | ||
rf: { | ||
description: `Format to be used for message-specific failure reports (colon-separated plain-text list of values)`, | ||
validate(term, value) { | ||
// 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()); | ||
v: { | ||
required: true, | ||
description: 'The v tag is required and represents the protocol version. An example is v=DMARC1', | ||
validate(term, value) { | ||
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.', | ||
validate(term, originalValue) { | ||
var value = originalValue.split(':'); | ||
if (value.length <= 4) { | ||
if (!/^([01ds])$/i.test(value[0])) { | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if (value.length > 1 && !/^([01ds])$/i.test(value[1])) { | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if (value.length > 2 && !/^([01ds])$/i.test(value[2])) { | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
if (value.length > 3 && !/^([01ds])$/i.test(value[3])) { | ||
throw new Error(`Invalid value for '${term}': '${originalValue}', must be colon seprated with: 0, 1, d, s`); | ||
} | ||
} | ||
}, | ||
generate(value) { | ||
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.', | ||
validate(term, value) { | ||
if (!/^(none|quarantine|reject)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of: none, quarantine, reject`); | ||
} | ||
} | ||
}, | ||
pct: { | ||
description: `This DMARC tag specifies the percentage of email messages subjected to filtering. For example, pct=25 means a quarter of your company’s emails will be filtered by the recipient.`, | ||
validate(term, value) { | ||
if (!/^\d+$/.test(value)) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a positive integer`); | ||
} | ||
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`); | ||
} | ||
} | ||
}, | ||
rf: { | ||
description: `Format to be used for message-specific failure reports (colon-separated plain-text list of values)`, | ||
validate(term, value) { | ||
// 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()); | ||
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`); | ||
} | ||
} | ||
} | ||
}, | ||
ri: { | ||
description: 'The ri tag corresponds to the aggregate reporting interval and provides DMARC feedback for the outlined criteria.', | ||
validate(term, value) { | ||
if (!/^\d+$/.test(value)) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be an unsigned integer`); | ||
} | ||
} | ||
}, | ||
rua: { | ||
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()); | ||
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`); | ||
} | ||
} | ||
} | ||
}, | ||
ri: { | ||
description: 'The ri tag corresponds to the aggregate reporting interval and provides DMARC feedback for the outlined criteria.', | ||
validate(term, value) { | ||
if (!/^\d+$/.test(value)) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be an unsigned integer`); | ||
} | ||
} | ||
}, | ||
rua: { | ||
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()); | ||
for (let val of values) { | ||
let matches = val.match(/^mailto:(.+)$/i); | ||
if (!matches) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a list of DMARC URIs such as 'mailto:some.email@somedomain.com'`); | ||
} | ||
let email = matches[1]; | ||
if (!validator.validate(email)) { | ||
throw new Error(`Invalid email address in '${term}': '${email}'`); | ||
} | ||
} | ||
}, | ||
generate(value){ | ||
var mailtoList = []; | ||
if(value && value.length){ | ||
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]) | ||
}else throw new Error("Invalid Email: '" + value[i] + "' 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.', | ||
validate(term, value) { | ||
let values = value.split(/,/).map(x => x.trim()); | ||
for (let val of values) { | ||
let matches = val.match(/^mailto:(.+)$/i); | ||
if (!matches) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a list of DMARC URIs such as 'mailto:some.email@somedomain.com'`); | ||
} | ||
let email = matches[1]; | ||
if (!validator.validate(email)) { | ||
throw new Error(`Invalid email address in '${term}': '${email}'`); | ||
} | ||
} | ||
}, | ||
generate(value) { | ||
var mailtoList = []; | ||
if (value && value.length) { | ||
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]) | ||
} else throw new Error("Invalid Email: '" + value[i] + "' 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.', | ||
validate(term, value) { | ||
let values = value.split(/,/).map(x => x.trim()); | ||
for (let val of values) { | ||
let matches = val.match(/^mailto:(.+)$/i); | ||
if (!matches) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a list of DMARC URIs such as 'mailto:some.email@somedomain.com'`); | ||
} | ||
let email = matches[1]; | ||
if (!validator.validate(email)) { | ||
throw new Error(`Invalid email address in '${term}': '${email}'`); | ||
} | ||
} | ||
}, | ||
generate(value){ | ||
var mailtoList = []; | ||
if(value && value.length){ | ||
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]) | ||
}else throw new Error("Invalid Email: '" + value[i] + "' for 'ruf' tag"); | ||
} | ||
return mailtoList.join(','); | ||
}else throw new Error(`Invalid value for 'ruf' tag`) | ||
} | ||
}, | ||
sp: { | ||
description: 'Requested Mail Receiver policy for all subdomains. Can be "none", "quarantine", or "reject".', | ||
validate(term, value) { | ||
if (!/^(none|quarantine|reject)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of: none, quarantine, reject`); | ||
} | ||
} | ||
}, | ||
aspf: { | ||
description: 'The aspf tag represents alignment mode for SPF. An optional tag, aspf=r is a common example of its configuration.', | ||
validate(term, value) { | ||
if (!/^(s|r)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of "r" or "s"`); | ||
} | ||
} | ||
}, | ||
adkim: { | ||
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) { | ||
if (!/^(s|r)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of "r" or "s"`); | ||
} | ||
} | ||
} | ||
for (let val of values) { | ||
let matches = val.match(/^mailto:(.+)$/i); | ||
if (!matches) { | ||
throw new Error(`Invalid value for '${term}': ${value}, must be a list of DMARC URIs such as 'mailto:some.email@somedomain.com'`); | ||
} | ||
let email = matches[1]; | ||
if (!validator.validate(email)) { | ||
throw new Error(`Invalid email address in '${term}': '${email}'`); | ||
} | ||
} | ||
}, | ||
generate(value) { | ||
var mailtoList = []; | ||
if (value && value.length) { | ||
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]) | ||
} else throw new Error("Invalid Email: '" + value[i] + "' for 'ruf' tag"); | ||
} | ||
return mailtoList.join(','); | ||
} else throw new Error(`Invalid value for 'ruf' tag`) | ||
} | ||
}, | ||
sp: { | ||
description: 'Requested Mail Receiver policy for all subdomains. Can be "none", "quarantine", or "reject".', | ||
validate(term, value) { | ||
if (!/^(none|quarantine|reject)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of: none, quarantine, reject`); | ||
} | ||
} | ||
}, | ||
aspf: { | ||
description: 'The aspf tag represents alignment mode for SPF. An optional tag, aspf=r is a common example of its configuration.', | ||
validate(term, value) { | ||
if (!/^(s|r)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of "r" or "s"`); | ||
} | ||
} | ||
}, | ||
adkim: { | ||
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) { | ||
if (!/^(s|r)$/i.test(value)) { | ||
throw new Error(`Invalid value for '${term}': '${value}', must be one of "r" or "s"`); | ||
} | ||
} | ||
} | ||
}; | ||
module.exports = validators; |
48
index.js
@@ -6,32 +6,32 @@ var parser = require('./bin/parser'); | ||
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); | ||
}); | ||
return new Promise((resolve, reject) => { | ||
var result = parser(dmarcRecord); | ||
if (result.messages && result.messages.length) return reject(result.messages); | ||
resolve(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); | ||
}) | ||
}) | ||
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 recordGenerator = function (values) { | ||
return new Promise((resolve, reject) => { | ||
try { | ||
resolve(generator(values)) | ||
} catch (err) { | ||
reject(err.message) | ||
} | ||
}) | ||
return new Promise((resolve, reject) => { | ||
try { | ||
resolve(generator(values)) | ||
} catch (err) { | ||
reject(err.message) | ||
} | ||
}) | ||
} | ||
@@ -38,0 +38,0 @@ |
{ | ||
"name": "dmarc-solution", | ||
"version": "1.0.2", | ||
"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", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/architjn/dmarc-solution.git" | ||
}, | ||
"keywords": ["dmarc", "dkim", "email", "mail", "spf", "record", "parser", "txt", "dns", "generator", "report"], | ||
"author": "Archit Jain", | ||
"license": "ISC", | ||
"dependencies": { | ||
"email-validator": "^2.0.4" | ||
} | ||
} | ||
"name": "dmarc-solution", | ||
"version": "1.0.3", | ||
"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", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/architjn/dmarc-solution.git" | ||
}, | ||
"keywords": [ | ||
"dmarc", | ||
"dkim", | ||
"email", | ||
"mail", | ||
"spf", | ||
"record", | ||
"parser", | ||
"txt", | ||
"dns", | ||
"generator", | ||
"report" | ||
], | ||
"author": "Archit Jain", | ||
"license": "ISC", | ||
"maintainers": [ | ||
{ | ||
"name": "Archit Jain", | ||
"email": "architjn93@gmail.com" | ||
} | ||
], | ||
"bugs": { | ||
"url": "https://github.com/architjn/dmarc-solution/issues" | ||
}, | ||
"dependencies": { | ||
"email-validator": "^2.0.4" | ||
} | ||
} |
@@ -1,1 +0,62 @@ | ||
# dmarc-solution-1 | ||
# dmarc-solution | ||
> 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 | ||
# Install | ||
npm install --save dmarc-solution | ||
# Usage | ||
### DMARC Generator | ||
```javascript | ||
const dmarc = require('dmarc-solution'); | ||
// Generator | ||
var generateInputs = { | ||
v: 'DMARC1', // only required tag | ||
p: 'quarantine', //must be one of: none, quarantine, reject | ||
rua: ['dmarc@example.com'], //array of emails for aggregate reports | ||
ruf: ['dmarc@example.com'], //array of emails for forensic reports | ||
fo: ['0', '1', 'd'], //array of selected options from: 0, 1, d, s | ||
pct: 75, //integer value from 0 to 100 | ||
rf: 'afrf', //must be one or more of these string values: afrf, iodef | ||
ri: 1, //must be an unsigned integer | ||
sp: 'none', //must be one of: none, quarantine, reject | ||
aspf: 'r', //must be one of "r" or "s" | ||
adkim: 's', //must be one of "r" or "s" | ||
} | ||
dmarc.generate(generateInputs) | ||
.then(record => { | ||
console.log(record); //v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=0:1:d; pct=75; rf=afrf; ri=1; sp=none; aspf=r; adkim=s | ||
}) | ||
.catch(err => { | ||
console.log(err); | ||
}); | ||
``` | ||
### DMARC Fetcher | ||
```javascript | ||
const dmarc = require('dmarc-solution'); | ||
// Fetcher from DNS | ||
dmarc.fetch('github.com') | ||
.then(record => { | ||
console.log(record); | ||
}) | ||
.catch(err => { | ||
console.log(err); | ||
}); | ||
``` | ||
### DMARC Parser | ||
```javascript | ||
const dmarc = require('dmarc-solution'); | ||
// DMARC Record parser | ||
dmarc.parse('v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com;') | ||
.then(record => { | ||
console.log(record); //{"v":{"description":"The v tag is required and represents the protocol version. An example is v=DMARC1","value":"DMARC1"},"p":{"description":"The required p tag demonstrates the policy for domain...","value":"quarantine"},"rua":{"description":"This optional tag is designed for reporting URI(s) for aggregate data...","value":"mailto:dmarc@example.com"}} | ||
}) | ||
.catch(err => { | ||
console.log(err); | ||
}); | ||
``` |
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
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
0
63
2
14555