postalsys / mailauth

Command line utility and a Node.js library for email authentication
Other
126 stars 10 forks source link

Expose `getDmarcRecord` and `getSpfRecord` #27

Closed titanism closed 1 year ago

titanism commented 1 year ago

Right now getDmarcRecord could easily be exposed via exports or module.exports.

However there's no getSpfRecord, albeit one could be added similarly with a returned object including values such as qualifier.

andris9 commented 1 year ago

Having getDmarcRecord as an exportable function seems reasonable, so I extracted it into a separate file, from where you can import it. See this PR for usage example: https://github.com/postalsys/mailauth/pull/28

It is more difficult with getSpfRecord because Mailauth treats SPF differently than DMARC. With DMARC, there's just a single record to resolve, and that's it. With SPF, mailauth resolves SPF only partially. SPF uses a recursive syntax, so Mailauth starts resolving the recursive tree and matching each condition from left to right. It finishes until it finds a matching condition, or encounters *all, or reaches the end.

Example

SPF record:

v=spf1 mx a include:_spf.google.com -all

this would resolve fully into the following tree:

- v=spf1
- mx
- a
- include:_spf.google.com 
  - include:_netblocks.google.com
    - ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19
  - include:_netblocks2.google.com
    - ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 
  - include:_netblocks3.google.com
    - ip4:172.217.0.0/19 ip4:172.217.32.0/20 ip4:172.217.128.0/19 ip4:172.217.160.0/20 ip4:172.217.192.0/19 ip4:172.253.56.0/21 ip4:172.253.112.0/20 ip4:108.177.96.0/19 ip4:35.191.0.0/16 ip4:130.211.0.0/22
- -all

If the IP matches MX record, then Mailauth resolves only the first level without any recursion (from left to right, the matching mx condition is before any include conditions). So the function would not return the full recursed tree as shown above, but the first level only:

- v=spf1
- mx <- matches here, so the following includes are not resolved
- a
- include:_spf.google.com 
- -all
titanism commented 1 year ago

Awesome, thank you @andris9. Can you cut a new release and patch bump to npm?

Regarding SPF, we can mark this as closed. My use case is simply to check if the SPF record has "-all" qualifier, which I can do myself manually by checking for v=spf1 and -all included in a resolved TXT record for a domain.

andris9 commented 1 year ago

Published as v4.2.0

titanism commented 1 year ago

Thank you @andris9 🙏 The only thing we need left is https://github.com/zone-eu/mx-connect/issues/3 🎉 !!!