mailauth 4.0.2 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -294,6 +294,39 @@ process.stdout.write(headers); // authentication results
294
294
  process.stdout.write(message);
295
295
  ```
296
296
 
297
+ ## DMARC
298
+
299
+ DMARC is verified as part of the authentication process and even as the `dmarc` handler is exported, it requires input from previous steps.
300
+
301
+ ### Helpers
302
+
303
+ #### getDmarcRecord
304
+
305
+ Returns parsed DMARC DNS record for a domain, or a subdomain
306
+
307
+ ```
308
+ const getDmarcRecord = require('mailauth/lib/dmarc/get-dmarc-record');
309
+ const dmarcRecord = getDmarcRecord("ethereal.email");
310
+ console.log(dmarcRecord);
311
+ ```
312
+
313
+ **Output**
314
+
315
+ ```
316
+ {
317
+ v: 'DMARC1',
318
+ p: 'none',
319
+ pct: 100,
320
+ rua: 'mailto:re+joqy8fpatm3@dmarc.postmarkapp.com',
321
+ sp: 'none',
322
+ aspf: 'r',
323
+ rr: 'v=DMARC1; p=none; pct=100; rua=mailto:re+joqy8fpatm3@dmarc.postmarkapp.com; sp=none; aspf=r;',
324
+ isOrgRecord: false
325
+ }
326
+ ```
327
+
328
+ `isOrgRecord` is `true` for sudomains, where organizational domain's DMARC policy applies, so use the `sp`, not `p` policy.
329
+
297
330
  ## BIMI
298
331
 
299
332
  Brand Indicators for Message Identification (BIMI) support is based on [draft-blank-ietf-bimi-01](https://tools.ietf.org/html/draft-blank-ietf-bimi-01).
@@ -0,0 +1,75 @@
1
+ 'use strict';
2
+
3
+ const psl = require('psl');
4
+ const dns = require('dns').promises;
5
+
6
+ const resolveTxt = async (domain, resolver) => {
7
+ try {
8
+ let txt = await resolver(`_dmarc.${domain}`, 'TXT');
9
+ if (!txt || !txt.length) {
10
+ return false;
11
+ }
12
+
13
+ txt = txt.map(row => row.join('').trim()).filter(row => /^v=DMARC1\b/i.test(row));
14
+
15
+ if (txt.length !== 1) {
16
+ //no records or multiple records yield in no policy
17
+ return false;
18
+ }
19
+
20
+ return txt[0];
21
+ } catch (err) {
22
+ if (err.code === 'ENOTFOUND' || err.code === 'ENODATA') {
23
+ return false;
24
+ }
25
+ throw err;
26
+ }
27
+ };
28
+
29
+ const getDmarcRecord = async (domain, resolver) => {
30
+ resolver = resolver || dns.resolve;
31
+
32
+ let txt = await resolveTxt(domain, resolver);
33
+ let isOrgRecord = false;
34
+
35
+ if (!txt) {
36
+ let orgDomain = psl.get(domain);
37
+ if (orgDomain !== domain) {
38
+ // try org domain as well
39
+ txt = await resolveTxt(orgDomain, resolver);
40
+ isOrgRecord = true;
41
+ }
42
+ }
43
+
44
+ if (!txt) {
45
+ return false;
46
+ }
47
+
48
+ let parsed = Object.fromEntries(
49
+ txt
50
+ .split(';')
51
+ .map(e => e.trim())
52
+ .filter(e => e)
53
+ .map(e => {
54
+ let splitPos = e.indexOf('=');
55
+ if (splitPos < 0) {
56
+ return [e.toLowerCase().trim(), false];
57
+ } else if (splitPos === 0) {
58
+ return [false, e];
59
+ }
60
+ let key = e.substr(0, splitPos).toLowerCase().trim();
61
+ let val = e.substr(splitPos + 1);
62
+ if (['pct', 'ri'].includes(key)) {
63
+ val = parseInt(val, 10) || 0;
64
+ }
65
+ return [key, val];
66
+ })
67
+ );
68
+
69
+ parsed.rr = txt;
70
+ parsed.isOrgRecord = isOrgRecord;
71
+
72
+ return parsed;
73
+ };
74
+
75
+ module.exports = getDmarcRecord;
@@ -4,73 +4,7 @@ const dns = require('dns').promises;
4
4
  const punycode = require('punycode/');
5
5
  const psl = require('psl');
6
6
  const { formatAuthHeaderRow, getAlignment } = require('../tools');
7
-
8
- const resolveTxt = async (domain, resolver) => {
9
- try {
10
- let txt = await resolver(`_dmarc.${domain}`, 'TXT');
11
- if (!txt || !txt.length) {
12
- return false;
13
- }
14
-
15
- txt = txt.map(row => row.join('').trim()).filter(row => /^v=DMARC1\b/i.test(row));
16
-
17
- if (txt.length !== 1) {
18
- //no records or multiple records yield in no policy
19
- return false;
20
- }
21
-
22
- return txt[0];
23
- } catch (err) {
24
- if (err.code === 'ENOTFOUND' || err.code === 'ENODATA') {
25
- return false;
26
- }
27
- throw err;
28
- }
29
- };
30
-
31
- const getDmarcRecord = async (domain, resolver) => {
32
- let txt = await resolveTxt(domain, resolver);
33
- let isOrgRecord = false;
34
-
35
- if (!txt) {
36
- let orgDomain = psl.get(domain);
37
- if (orgDomain !== domain) {
38
- // try org domain as well
39
- txt = await resolveTxt(orgDomain, resolver);
40
- isOrgRecord = true;
41
- }
42
- }
43
-
44
- if (!txt) {
45
- return false;
46
- }
47
-
48
- let parsed = Object.fromEntries(
49
- txt
50
- .split(';')
51
- .map(e => e.trim())
52
- .filter(e => e)
53
- .map(e => {
54
- let splitPos = e.indexOf('=');
55
- if (splitPos < 0) {
56
- return [e.toLowerCase().trim(), false];
57
- } else if (splitPos === 0) {
58
- return [false, e];
59
- }
60
- let key = e.substr(0, splitPos).toLowerCase().trim();
61
- let val = e.substr(splitPos + 1);
62
- if (['pct', 'ri'].includes(key)) {
63
- val = parseInt(val, 10) || 0;
64
- }
65
- return [key, val];
66
- })
67
- );
68
-
69
- parsed.rr = txt;
70
- parsed.isOrgRecord = isOrgRecord;
71
-
72
- return parsed;
73
- };
7
+ const getDmarcRecord = require('./get-dmarc-record');
74
8
 
75
9
  const verifyDmarc = async opts => {
76
10
  let { headerFrom, spfDomains, dkimDomains, resolver, arcResult } = opts;
package/lib/tools.js CHANGED
@@ -10,7 +10,6 @@ const https = require('https');
10
10
  const packageData = require('../package');
11
11
  const parseDkimHeaders = require('./parse-dkim-headers');
12
12
  const psl = require('psl');
13
- const pki = require('node-forge').pki;
14
13
  const Joi = require('joi');
15
14
  const base64Schema = Joi.string().base64({ paddingRequired: false });
16
15
 
@@ -288,14 +287,7 @@ const getPublicKey = async (type, name, minBitLength, resolver) => {
288
287
  throw err;
289
288
  }
290
289
 
291
- let modulusLength;
292
- if (publicKeyObj.asymmetricKeyDetails) {
293
- modulusLength = publicKeyObj.asymmetricKeyDetails.modulusLength;
294
- } else {
295
- // fall back to node-forge
296
- const pubKeyData = pki.publicKeyFromPem(publicKeyPem.toString());
297
- modulusLength = pubKeyData.n.bitLength();
298
- }
290
+ let modulusLength = publicKeyObj.asymmetricKeyDetails.modulusLength;
299
291
 
300
292
  if (keyType === 'rsa' && modulusLength < 1024) {
301
293
  let err = new Error('RSA key too short');
package/licenses.txt CHANGED
@@ -1,12 +1,11 @@
1
- name license type link installed version author
2
- ---- ------------ ---- ----------------- ------
3
- @postalsys/vmc MIT https://registry.npmjs.org/@postalsys/vmc/-/vmc-1.0.6.tgz 1.0.6 Postal Systems OÜ
4
- fast-xml-parser MIT git+https://github.com/NaturalIntelligence/fast-xml-parser.git 4.0.9 Amit Gupta (https://amitkumargupta.work/)
5
- ipaddr.js MIT git://github.com/whitequark/ipaddr.js.git 2.0.1 whitequark <whitequark@whitequark.org>
6
- joi BSD-3-Clause git://github.com/sideway/joi.git 17.6.0 n/a
7
- libmime MIT git://github.com/andris9/libmime.git 5.1.0 Andris Reinman <andris@kreata.ee>
8
- node-forge (BSD-3-Clause OR GPL-2.0) git+https://github.com/digitalbazaar/forge.git 1.3.1 Digital Bazaar, Inc. support@digitalbazaar.com http://digitalbazaar.com/
9
- nodemailer MIT git+https://github.com/nodemailer/nodemailer.git 6.7.8 Andris Reinman
10
- psl MIT git+ssh://git@github.com/lupomontero/psl.git 1.9.0 Lupo Montero <lupomontero@gmail.com> (https://lupomontero.com/)
11
- punycode MIT git+https://github.com/bestiejs/punycode.js.git 2.1.1 Mathias Bynens https://mathiasbynens.be/
12
- yargs MIT git+https://github.com/yargs/yargs.git 17.5.1 n/a
1
+ name license type link installed version author
2
+ ---- ------------ ---- ----------------- ------
3
+ @postalsys/vmc MIT https://registry.npmjs.org/@postalsys/vmc/-/vmc-1.0.6.tgz 1.0.6 Postal Systems OÜ
4
+ fast-xml-parser MIT git+https://github.com/NaturalIntelligence/fast-xml-parser.git 4.0.15 Amit Gupta (https://amitkumargupta.work/)
5
+ ipaddr.js MIT git://github.com/whitequark/ipaddr.js.git 2.0.1 whitequark <whitequark@whitequark.org>
6
+ joi BSD-3-Clause git://github.com/hapijs/joi.git 17.7.0 n/a
7
+ libmime MIT git://github.com/andris9/libmime.git 5.2.0 Andris Reinman <andris@kreata.ee>
8
+ nodemailer MIT git+https://github.com/nodemailer/nodemailer.git 6.9.0 Andris Reinman
9
+ psl MIT git+ssh://git@github.com/lupomontero/psl.git 1.9.0 Lupo Montero <lupomontero@gmail.com> (https://lupomontero.com/)
10
+ punycode MIT git+https://github.com/mathiasbynens/punycode.js.git 2.3.0 Mathias Bynens https://mathiasbynens.be/
11
+ yargs MIT git+https://github.com/yargs/yargs.git 17.6.2 n/a
package/man/mailauth.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH "MAILAUTH" "1" "September 2022" "v4.0.1" "Mailauth Help"
1
+ .TH "MAILAUTH" "1" "February 2023" "v4.1.0" "Mailauth Help"
2
2
  .SH "NAME"
3
3
  \fBmailauth\fR
4
4
  .QP
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailauth",
3
- "version": "4.0.2",
3
+ "version": "4.2.0",
4
4
  "description": "Email authentication library for Node.js",
5
5
  "main": "lib/mailauth.js",
6
6
  "scripts": {
@@ -32,29 +32,28 @@
32
32
  },
33
33
  "homepage": "https://github.com/postalsys/mailauth",
34
34
  "devDependencies": {
35
- "chai": "4.3.6",
36
- "eslint": "8.24.0",
35
+ "chai": "4.3.7",
36
+ "eslint": "8.33.0",
37
37
  "eslint-config-nodemailer": "1.2.0",
38
- "eslint-config-prettier": "8.5.0",
38
+ "eslint-config-prettier": "8.6.0",
39
39
  "js-yaml": "4.1.0",
40
- "license-report": "6.1.0",
40
+ "license-report": "6.3.0",
41
41
  "marked": "0.7.0",
42
42
  "marked-man": "0.7.0",
43
43
  "mbox-reader": "1.1.5",
44
- "mocha": "10.0.0",
44
+ "mocha": "10.2.0",
45
45
  "pkg": "5.8.0"
46
46
  },
47
47
  "dependencies": {
48
48
  "@postalsys/vmc": "1.0.6",
49
- "fast-xml-parser": "4.0.10",
49
+ "fast-xml-parser": "4.1.1",
50
50
  "ipaddr.js": "2.0.1",
51
- "joi": "17.6.1",
52
- "libmime": "5.1.0",
53
- "node-forge": "1.3.1",
54
- "nodemailer": "6.7.8",
51
+ "joi": "17.7.0",
52
+ "libmime": "5.2.1",
53
+ "nodemailer": "6.9.1",
55
54
  "psl": "1.9.0",
56
- "punycode": "2.1.1",
57
- "yargs": "17.5.1"
55
+ "punycode": "2.3.0",
56
+ "yargs": "17.6.2"
58
57
  },
59
58
  "engines": {
60
59
  "node": ">=16.0.0"