Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

haraka-net-utils

Package Overview
Dependencies
Maintainers
4
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

haraka-net-utils - npm Package Compare versions

Comparing version 1.6.0 to 1.7.0

lib/get_mx.js

66

CHANGELOG.md

@@ -7,5 +7,14 @@ # Changelog

### [1.7.0] - 2024-04-29
- feat: added HarakaMx #89
- feat: add add_line_processor, aka line_socket.setup_line_processor
- fix(get_public_ip): set timeout in stun request, fixes #84
- test: added get_implicit_mx tests #89
- change: get_mx: don't filter implicit MX errors #89
### [1.6.0] - 2024-04-17
- feat: normalizeDomain, for punycode/IDN names
<!-- prettier-ignore -->
- feat: get_mx now _also_ returns implicit MX records

@@ -66,3 +75,3 @@ - feat: added get_implicit_mx

#### [1.3.5] - 2022-05-27
### [1.3.5] - 2022-05-27

@@ -74,15 +83,15 @@ - chore(ci): use shared GHA workflows

#### [1.3.4] - 2022-01-05
### [1.3.4] - 2022-01-05
- promisify get_ips_by_host (backwards compatible)
#### [1.3.3] - 2020-01-05
### [1.3.3] - 2020-01-05
- refactored is_local_host function to return a promise instead of using a callback #65
#### [1.3.2] - 2021-12-20
### [1.3.2] - 2021-12-20
- add is_local_host function #63
#### [1.3.1] - 2021-10-13
### [1.3.1] - 2021-10-13

@@ -93,7 +102,7 @@ - get_mx: wrap dns.resolveMx in a try haraka/Haraka#2985

#### 1.3.0 - 2021-01-23
### 1.3.0 - 2021-01-23
- Support passing an array to ip_in_list #60
#### 1.2.4 - 2021-01-14
### 1.2.4 - 2021-01-14

@@ -103,15 +112,15 @@ - add "any" IP to is_local_ip

#### 1.2.3 - 2020-12-19
### 1.2.3 - 2020-12-19
- fix: restore the tests wrapping the resolveMX iterable
#### 1.2.2 - 2020-12-15
### 1.2.2 - 2020-12-15
- get_mx: do not include implicit MX
#### [1.2.1] - 2020-11-17
### [1.2.1] - 2020-11-17
- bump ipaddr.js to 2.0.0 #56
#### [1.2.0] - 2020-06-23
### [1.2.0] - 2020-06-23

@@ -122,3 +131,3 @@ - added get_mx

#### 1.1.5 - 2020-04-11
### 1.1.5 - 2020-04-11

@@ -128,27 +137,27 @@ - ipv6_bogus: handle parsing broken ipv6 addresses #49

#### 1.1.4 - 2019-04-04
### 1.1.4 - 2019-04-04
- stop is_private_ip from checking if the IP is bound to a local network interface
#### 1.1.3 - 2019-03-01
### 1.1.3 - 2019-03-01
- is_local_ip checks local network interfaces too
#### 1.1.2 - 2018-11-03
### 1.1.2 - 2018-11-03
- add is_local_ip
#### 1.1.1 - 2018-07-19
### 1.1.1 - 2018-07-19
- ip_in_list doesn't throw on empty list
#### 1.1.0 - 2018-04-11
### 1.1.0 - 2018-04-11
- add get_primary_host_name haraka/Haraka#2380
#### 1.0.14 - 2018-01-25
### 1.0.14 - 2018-01-25
- restore tls_ini_section_with_defaults function (deprecated since Haraka 2.0.17)
#### 1.0.13 - 2018-01-19
### 1.0.13 - 2018-01-19

@@ -162,11 +171,11 @@ - get_public_ip: assign timer before calling connect #29

#### 1.0.10 - 2017-07-27
### 1.0.10 - 2017-07-27
- added vs-stun as optional dep (from Haraka) #21
#### 1.0.9 - 2017-06-16
### 1.0.9 - 2017-06-16
- lint fixes for compat with eslint 4 #18
#### 1.0.8 - 2017-03-08
### 1.0.8 - 2017-03-08

@@ -178,7 +187,7 @@ - skip loading expired x509 (TLS) certs

#### 1.0.7 - 2017-03-08
### 1.0.7 - 2017-03-08
- handle undefined tls.ini section
#### 1.0.6 - 2017-03-04
### 1.0.6 - 2017-03-04

@@ -189,11 +198,11 @@ - add tls_ini_section_with_defaults()

#### 1.0.5 - 2016-11-20
### 1.0.5 - 2016-11-20
- add enableSNI TLS option
#### 1.0.4 - 2016-10-25
### 1.0.4 - 2016-10-25
- initialize TLS opts in (section != main) as booleans
#### 1.0.3 - 2016-10-25
### 1.0.3 - 2016-10-25

@@ -210,3 +219,3 @@ - added tls.ini loading

[1.3.6]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.6
[1.3.7]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.3.7
[1.3.7]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.7
[1.4.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.4.0

@@ -220,1 +229,2 @@ [1.4.1]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.4.1

[1.6.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.6.0
[1.7.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.7.0
'use strict'
// node.js built-ins
const { Resolver } = require('dns').promises
const { Resolver } = require('node:dns').promises
const dns = new Resolver({ timeout: 25000, tries: 1 })
const net = require('net')
const os = require('os')
const punycode = require('punycode.js')
const net = require('node:net')
const os = require('node:os')

@@ -262,93 +260,3 @@ // npm modules

exports.get_public_ip_async = async function () {
if (this.public_ip !== undefined) return this.public_ip // cache
// manual config override, for the cases where we can't figure it out
const smtpIni = exports.config.get('smtp.ini').main
if (smtpIni.public_ip) {
this.public_ip = smtpIni.public_ip
return this.public_ip
}
// Initialise cache value to null to prevent running
// should we hit a timeout or the module isn't installed.
this.public_ip = null
try {
this.stun = require('@msimerson/stun')
} catch (e) {
e.install = 'Please install stun: "npm install -g stun"'
console.error(`${e.msg}\n${e.install}`)
return
}
const timeout = 10
const timer = setTimeout(() => {
return new Error('STUN timeout')
}, timeout * 1000)
// Connect to STUN Server
const res = await this.stun.request(get_stun_server())
this.public_ip = res.getXorAddress().address
clearTimeout(timer)
return this.public_ip
}
exports.get_public_ip = async function (cb) {
if (!cb) return exports.get_public_ip_async()
const nu = this
if (nu.public_ip !== undefined) return cb(null, nu.public_ip) // cache
// manual config override, for the cases where we can't figure it out
const smtpIni = exports.config.get('smtp.ini').main
if (smtpIni.public_ip) {
nu.public_ip = smtpIni.public_ip
return cb(null, nu.public_ip)
}
// Initialise cache value to null to prevent running
// should we hit a timeout or the module isn't installed.
nu.public_ip = null
try {
nu.stun = require('@msimerson/stun')
} catch (e) {
e.install = 'Please install stun: "npm install -g stun"'
console.error(`${e.msg}\n${e.install}`)
return cb(e)
}
const timeout = 10
const timer = setTimeout(() => {
return cb(new Error('STUN timeout'))
}, timeout * 1000)
// Connect to STUN Server
nu.stun.request(get_stun_server(), (error, res) => {
if (timer) clearTimeout(timer)
if (error) return cb(error)
nu.public_ip = res.getXorAddress().address
cb(null, nu.public_ip)
})
}
function get_stun_server() {
// STUN servers by Google
const servers = [
'stun.l.google.com:19302',
'stun1.l.google.com:19302',
'stun2.l.google.com:19302',
'stun3.l.google.com:19302',
'stun4.l.google.com:19302',
]
return servers[Math.floor(Math.random() * servers.length)]
}
exports.get_ipany_re = function (prefix, suffix, modifier) {
if (prefix === undefined) prefix = ''
if (suffix === undefined) suffix = ''
if (modifier === undefined) modifier = 'mg'
/* eslint-disable prefer-template */
exports.get_ipany_re = function (prefix = '', suffix = '', modifier = 'mg') {
return new RegExp(

@@ -450,125 +358,32 @@ prefix +

function normalizeDomain(raw_domain) {
let domain = raw_domain
if (/@/.test(domain)) {
domain = domain.split('@').pop()
// console.log(`\treduced ${raw_domain} to ${domain}.`)
}
if (/^xn--/.test(domain)) {
// is punycode IDN with ACE, ASCII Compatible Encoding
} else if (domain !== punycode.toASCII(domain)) {
domain = punycode.toASCII(domain)
console.log(`\tACE encoded '${raw_domain}' to '${domain}'`)
}
return domain
for (const l of ['get_mx', 'get_implicit_mx', 'resolve_mx_hosts']) {
exports[l] = require('./lib/get_mx')[l]
}
function fatal_mx_err(err) {
// Possible DNS errors
// NODATA
// FORMERR
// BADRESP
// NOTFOUND
// BADNAME
// TIMEOUT
// CONNREFUSED
// NOMEM
// DESTRUCTION
// NOTIMP
// EREFUSED
// SERVFAIL
exports.get_public_ip = require('./lib/get_public_ip').get_public_ip
switch (err.code) {
case 'ENODATA':
case 'ENOTFOUND':
// likely a hostname with no MX record, drop through
return false
default:
return err
}
}
exports.get_public_ip_async = require('./lib/get_public_ip').get_public_ip_async
exports.get_mx = async (raw_domain, cb) => {
const domain = normalizeDomain(raw_domain)
exports.HarakaMx = require('./lib/HarakaMx')
try {
const exchanges = await dns.resolveMx(domain)
if (exchanges && exchanges.length) {
exchanges.map((e) => (e.from_dns = domain))
if (cb) return cb(null, exchanges)
return exchanges
}
} catch (err) {
// console.error(err.message)
if (fatal_mx_err(err)) {
if (cb) return cb(err, [])
throw err
}
}
exports.add_line_processor = (socket) => {
const line_regexp = /^([^\n]*\n)/ // utils.line_regexp
let current_data = ''
// no MX or non-fatal DNS failure
try {
const exchanges = await this.get_implicit_mx(domain)
if (cb) return cb(null, exchanges)
return exchanges
} catch (err) {
if (fatal_mx_err(err)) {
if (cb) return cb(err, [])
throw err
socket.on('data', (data) => {
current_data += data
let results
while ((results = line_regexp.exec(current_data))) {
const this_line = results[1]
current_data = current_data.slice(this_line.length)
socket.emit('line', this_line)
}
}
}
})
exports.get_implicit_mx = async (domain) => {
// console.log(`No MX for ${domain}, trying AAAA & A records`)
const promises = [dns.resolve6(domain), dns.resolve4(domain)]
const r = await Promise.allSettled(promises)
return r
.filter((a) => a.status === 'fulfilled')
.flatMap((a) =>
a.value.map((ip) => ({ priority: 0, exchange: ip, from_dns: domain })),
)
}
exports.resolve_mx_hosts = async (mxes) => {
// for the given list of MX exchanges, resolve the hostnames to IPs
const promises = []
for (const mx of mxes) {
if (!mx.exchange) {
promises.push(mx)
continue
socket.on('end', () => {
if (current_data.length) {
socket.emit('line', current_data)
}
if (net.isIP(mx.exchange)) {
promises.push(mx) // already resolved
continue
}
// resolve AAAA and A since mx.exchange is a hostname
promises.push(
dns
.resolve6(mx.exchange)
.then((ips) =>
ips.map((ip) => ({ ...mx, exchange: ip, from_dns: mx.exchange })),
),
)
promises.push(
dns
.resolve4(mx.exchange)
.then((ips) =>
ips.map((ip) => ({ ...mx, exchange: ip, from_dns: mx.exchange })),
),
)
}
const settled = await Promise.allSettled(promises)
return settled.filter((s) => s.status === 'fulfilled').flatMap((s) => s.value)
current_data = ''
})
}
{
"name": "haraka-net-utils",
"version": "1.6.0",
"version": "1.7.0",
"description": "haraka network utilities",
"main": "index.js",
"files": [
"CHANGELOG.md"
"CHANGELOG.md",
"lib"
],

@@ -39,8 +40,8 @@ "scripts": {

"devDependencies": {
"@haraka/eslint-config": "^1.1.3"
"@haraka/eslint-config": "^1.1.5"
},
"dependencies": {
"haraka-config": "^1.1.0",
"haraka-config": "^1.2.4",
"haraka-tld": "^1.2.1",
"ipaddr.js": "^2.1.0",
"ipaddr.js": "^2.2.0",
"punycode.js": "^2.3.1",

@@ -47,0 +48,0 @@ "openssl-wrapper": "^0.3.4",

@@ -123,2 +123,46 @@ [![CI][ci-img]][ci-url]

### HarakaMx
An object class representing a MX. HarakaMx objects may contain the following properties:
```js
{
exchange: '', // required: a FQDN or IP address
path: '', // the file path to a socket
priority: 0, // integer, a MX priority.
port: 25, // integer: an alternate port
bind: '', // an outbound IP address to bind to
bind_helo: '', // an outbound helo hostname
using_lmtp: false, // boolean, specify LMTP delivery
auth_user: '', // an AUTH username (required if AUTH is desired)
auth_pass: '', // an AUTH password (required if AUTH is desired)
auth_type: '', // an AUTH type that should be used with the MX.
from_dns: '', // the DNS name from which the MX was queried
}
```
Create a HarakaMx object in The Usual Way:
```js
const nu = require('haraka-net-utils')
const myMx = new nu.HarakaMx(parameter)
```
The parameter can be one of:
- A string in any of the following formats:
- hostname
- hostname:port
- IPv4
- IPv4:port
- [IPv6]
- [IPv6]: port
- A [URL](https://nodejs.org/docs/latest-v20.x/api/url.html) string
- smtp://mail.example.com:25
- lmtp://int-mail.example.com:24
- smtp://user:pass@host.example.com:587
- An object, containing at least an exchange, and any of the other properties listed at the top of this section.
An optional second parameter is an alias for from_dns.
[ci-img]: https://github.com/haraka/haraka-net-utils/actions/workflows/ci.yml/badge.svg

@@ -125,0 +169,0 @@ [ci-url]: https://github.com/haraka/haraka-net-utils/actions/workflows/ci.yml

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc