diff --git a/lib/spf.js b/lib/spf.js index 508dcde..c9ed630 100644 --- a/lib/spf.js +++ b/lib/spf.js @@ -38,6 +38,9 @@ class SPF { this.mech_ip4 = this.mech_ip this.mech_ip6 = this.mech_ip + + // Used for tests only + this._found_mx_addrs = []; } const_translate(value) { @@ -486,17 +489,15 @@ class SPF { } } - let pending = 0 let addresses = [] // RFC 4408 Section 10.1 if (mxes.length > this.LIMIT) return this.SPF_PERMERROR + let cidr; for (const element of mxes) { - pending++ const mx = element.exchange // Calculate which IP method to use let resolve_method - let cidr if (this.ip_ver === 'ipv4') { cidr = cidr4 resolve_method = 'resolve4' @@ -519,49 +520,45 @@ class SPF { } } - pending-- - if (addrs) { - this.log_debug(`mech_mx: mx=${mx} addresses=${addrs.join(',')}`) - addresses = addrs.concat(addresses) - } - if (pending === 0) { - if (!addresses.length) return this.SPF_NONE - // All queries run; see if our IP matches - if (cidr) { - // CIDR match type - for (const address of addresses) { - const range = ipaddr.parse(address) - if (this.ipaddr.match(range, cidr)) { - this.log_debug( - `mech_mx: ${this.ip} => ${address}/${cidr}: MATCH!`, - ) - return this.return_const(qualifier) - } else { - this.log_debug( - `mech_mx: ${this.ip} => ${address}/${cidr}: NO MATCH`, - ) - } - } - // No matches - return this.SPF_NONE + this.log_debug(`mech_mx: mx=${mx} addresses=${addrs.join(',')}`) + addresses = addrs.concat(addresses) + } + + if (!addresses.length) return this.SPF_NONE + this._found_mx_addrs = addresses; + + // All queries run; see if our IP matches + if (cidr) { + // CIDR match type + for (const address of addresses) { + const range = ipaddr.parse(address) + if (this.ipaddr.match(range, cidr)) { + this.log_debug( + `mech_mx: ${this.ip} => ${address}/${cidr}: MATCH!`, + ) + return this.return_const(qualifier) } else { - if (addresses.includes(this.ip)) { - this.log_debug( - `mech_mx: ${this.ip} => ${addresses.join(',')}: MATCH!`, - ) - return this.return_const(qualifier) - } else { - this.log_debug( - `mech_mx: ${this.ip} => ${addresses.join(',')}: NO MATCH`, - ) - return this.SPF_NONE - } + this.log_debug( + `mech_mx: ${this.ip} => ${address}/${cidr}: NO MATCH`, + ) } } - // In case we didn't run any queries... - if (pending === 0) return this.SPF_NONE + // No matches + return this.SPF_NONE + } else { + if (addresses.includes(this.ip)) { + this.log_debug( + `mech_mx: ${this.ip} => ${addresses.join(',')}: MATCH!`, + ) + return this.return_const(qualifier) + } else { + this.log_debug( + `mech_mx: ${this.ip} => ${addresses.join(',')}: NO MATCH`, + ) + return this.SPF_NONE + } } - if (pending === 0) this.SPF_NONE + return this.SPF_NONE } async mech_ptr(qualifier, args) { diff --git a/test/spf.js b/test/spf.js index a260fa3..0a14e68 100644 --- a/test/spf.js +++ b/test/spf.js @@ -53,6 +53,15 @@ describe('SPF', function () { } }) + it('resolves more than one IP in mech_mx', async function () { + this.timeout = 4000 + this.SPF.domain = 'gmail.com' + this.SPF.ip_ver = 'ipv4' + + const rc = await this.SPF.mech_mx() + assert.equal((this.SPF._found_mx_addrs.length > 1), true) + }) + it('check_host, gmail.com, fail', async function () { this.timeout = 3000 this.SPF.count = 0