Skip to content

Commit

Permalink
Release v1.0.3 (#3)
Browse files Browse the repository at this point in the history
- fixed issue with promises #2 
- removed redundant time out
- added several new tests
  • Loading branch information
msimerson authored Jan 30, 2025
1 parent 7a0b75f commit ea1762d
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 135 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

### Unreleased

### [1.0.3] - 2025-01-30

- fixed issue with promises
- remove redundant time out
- added several new tests

### [1.0.2] - 2025-01-29

- style(prettier) & lint
Expand All @@ -13,3 +19,5 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
- import from haraka/Haraka

[1.0.2]: https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/releases/tag/v1.0.2
[1.0.3]: https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/releases/tag/v1.0.3
[1.0.1]: https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/releases/tag/v1.0.1
4 changes: 2 additions & 2 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

This handcrafted artisinal software is brought to you by:

| <img height="80" src="https://avatars.githubusercontent.com/u/261635?v=4"><br><a href="https://github.com/msimerson">msimerson</a> (<a href="https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/commits?author=msimerson">1</a>) |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <img height="80" src="https://avatars.githubusercontent.com/u/261635?v=4"><br><a href="https://github.com/msimerson">msimerson</a> (<a href="https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/commits?author=msimerson">2</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/203240?v=4"><br><a href="https://github.com/lnedry">lnedry</a> (<a href="https://github.com/haraka/haraka-plugin-mail_from.is_resolvable/commits?author=lnedry">1</a>) |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |

<sub>this file is generated by [.release](https://github.com/msimerson/.release).
Contribute to this project to get your GitHub profile included here.</sub>
153 changes: 80 additions & 73 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,104 @@ const net = require('node:net')
const net_utils = require('haraka-net-utils')

exports.register = function () {
this.load_ini()
this.load_ini()
}

exports.load_ini = function () {
this.cfg = this.config.get('mail_from.is_resolvable.ini', {
booleans: [
'-main.allow_mx_ip',
'+reject.no_mx',
],
}, () => {
this.load_ini()
})
this.cfg = this.config.get(
'mail_from.is_resolvable.ini',
{
booleans: ['-main.allow_mx_ip', '+reject.no_mx'],
},
() => {
this.load_ini()
},
)

// compat. Sunset 4.0
if (this.cfg.main.reject_no_mx) {
this.cfg.reject.no_mx = this.cfg.main.reject_no_mx
}
// compat. Sunset 4.0
if (this.cfg.main.reject_no_mx) {
this.cfg.reject.no_mx = this.cfg.main.reject_no_mx
}

this.re_bogus_ip = new RegExp(this.cfg.main.re_bogus_ip ||
'^(?:0\\.0\\.0\\.0|255\\.255\\.255\\.255|127\\.)' )
this.re_bogus_ip = new RegExp(
this.cfg.main.re_bogus_ip ||
'^(?:0\\.0\\.0\\.0|255\\.255\\.255\\.255|127\\.)',
)
}

exports.hook_mail = async function (next, connection, params) {
const mail_from = params[0]
const {results} = connection.transaction
const mail_from = params[0]
const { results } = connection.transaction

// ignore MAIL FROM without an @
if (!mail_from.host) {
results.add(this, {skip: 'null host'})
return next()
}
// ignore MAIL FROM without an @
if (!mail_from.host) {
results.add(this, { skip: 'null host' })
return next()
}

const domain = mail_from.host
const domain = mail_from.host

connection.logdebug(this, `resolving MX for domain ${domain}`)
connection.logdebug(this, `resolving MX for domain ${domain}`)

let exchanges
try {
exchanges = await net_utils.get_mx(domain)
}
catch (err) {
results.add(this, {err: err.message})
return next(DENYSOFT, `Temp. resolver error (${err.code})`)
}
let exchanges
try {
exchanges = await net_utils.get_mx(domain)
} catch (err) {
results.add(this, { err: err.message })
return next(DENYSOFT, `Temp. resolver error (${err.code})`)
}

connection.logdebug(this, `${domain}: MX => ${JSON.stringify(exchanges)}`)
connection.logdebug(this, `${domain}: MX => ${JSON.stringify(exchanges)}`)

if (!exchanges || !exchanges.length) {
results.add(this, {fail: 'has_fwd_dns', emit: true})
return next(
((this.cfg.reject.no_mx) ? DENY : DENYSOFT),
'No MX for your FROM address'
)
}
if (!exchanges || !exchanges.length) {
results.add(this, { fail: 'has_fwd_dns', emit: true })
return next(
this.cfg.reject.no_mx ? DENY : DENYSOFT,
'No MX for your FROM address',
)
}

if (this.cfg.main.allow_mx_ip) {
for (const mx of exchanges) {
if ((net.isIPv4(mx.exchange) && !this.re_bogus_ip.test(mx.exchange)) ||
(net.isIPv6(mx.exchange) && !net_utils.ipv6_bogus(mx.exchange))) {
results.add(this, {pass: 'implicit_mx', emit: true})
return next()
}
}
if (this.cfg.main.allow_mx_ip) {
for (const mx of exchanges) {
if (
(net.isIPv4(mx.exchange) && !this.re_bogus_ip.test(mx.exchange)) ||
(net.isIPv6(mx.exchange) && !net_utils.ipv6_bogus(mx.exchange))
) {
results.add(this, { pass: 'implicit_mx', emit: true })
return next()
}
}
}

// filter out the implicit MX and resolve the remaining MX hostnames
const mx_hostnames = exchanges.filter(a => (a.exchange && !net.isIP(a.exchange)))
if (mx_hostnames.length) {
try {
const resolved = await net_utils.resolve_mx_hosts(mx_hostnames)
connection.logdebug(this, `resolved MX => ${JSON.stringify(resolved)}`)
if (resolved.length) {
for (const mx of resolved) {
if ((net.isIPv4(mx.exchange) && !this.re_bogus_ip.test(mx.exchange)) ||
(net.isIPv6(mx.exchange) && !net_utils.ipv6_bogus(mx.exchange))) {
results.add(this, {pass: 'has_fwd_dns', emit: true})
return next()
}
}
}
}
catch (err) {
// resolve_mx_hosts ignores errors so this is unlikely to happen
results.add(this, {err: err.message})
return next(DENYSOFT, `Temp. resolver error (${err.code})`)
// filter out the implicit MX and resolve the remaining MX hostnames
const mx_hostnames = exchanges.filter(
(a) => a.exchange && !net.isIP(a.exchange),
)
if (mx_hostnames.length) {
try {
const resolved = await net_utils.resolve_mx_hosts(mx_hostnames)
connection.logdebug(this, `resolved MX => ${JSON.stringify(resolved)}`)
if (resolved.length) {
for (const mx of resolved) {
if (
(net.isIPv4(mx.exchange) && !this.re_bogus_ip.test(mx.exchange)) ||
(net.isIPv6(mx.exchange) && !net_utils.ipv6_bogus(mx.exchange))
) {
results.add(this, { pass: 'has_fwd_dns', emit: true })
return next()
}
}
}
} catch (err) {
// resolve_mx_hosts ignores errors so this is unlikely to happen
results.add(this, { err: err.message })
return next(DENYSOFT, `Temp. resolver error (${err.code})`)
}
}

results.add(this, {fail: 'has_fwd_dns', emit: true})
return next(
((this.cfg.reject.no_mx) ? DENY : DENYSOFT),
'No valid MX for your FROM address'
)
results.add(this, { fail: 'has_fwd_dns', emit: true })
return next(
this.cfg.reject.no_mx ? DENY : DENYSOFT,
'No valid MX for your FROM address',
)
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "haraka-plugin-mail_from.is_resolvable",
"version": "1.0.2",
"version": "1.0.3",
"description": "Haraka plugin that checks that the domain used in MAIL FROM is resolvable to an MX record",
"main": "index.js",
"files": [
Expand Down Expand Up @@ -35,7 +35,7 @@
"@haraka/eslint-config": "^2.0.2",
"address-rfc2821": "^2.1.2",
"haraka-test-fixtures": "^1.3.8",
"sinon": "^19.0.2"
"sinon": "^19.0.2"
},
"prettier": {
"singleQuote": true,
Expand Down
Loading

0 comments on commit ea1762d

Please sign in to comment.