From a68bdf3e47c439af0fca1b98819113e7037f7594 Mon Sep 17 00:00:00 2001 From: Zac Clay Date: Tue, 3 Nov 2026 11:24:00 -0500 Subject: [PATCH] fix: keep checking MX hosts after an unlisted host with one dot domain_is_in? checks each MX host in an any? loop. For a short host name with one dot (for example ordinary.example) that is not on the list, it used `return false`. In Ruby, `return` inside a block stops the whole method, so the other MX hosts were never checked. Use `next false` so the loop goes on to the next host. --- lib/valid_email2/address.rb | 2 +- spec/address_spec.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/valid_email2/address.rb b/lib/valid_email2/address.rb index 0a7a7b8..48c7207 100644 --- a/lib/valid_email2/address.rb +++ b/lib/valid_email2/address.rb @@ -136,7 +136,7 @@ def domain_is_in?(address_domains, domain_list) return true if domain_list.include?(address_domain) tokens = address_domain.split('.') - return false if tokens.length < 3 + next false if tokens.length < 3 # check only 6 elements deep 2.upto(6).each do |depth| diff --git a/spec/address_spec.rb b/spec/address_spec.rb index fe9820a..52ac8d5 100644 --- a/spec/address_spec.rb +++ b/spec/address_spec.rb @@ -168,6 +168,29 @@ expect(disposable_email_instance.send(:disposable_mx_server?)).to be_truthy end + + context "when the domain has several MX servers" do + let(:ordinary_mx_record) { double("MX", exchange: "ordinary.example", preference: 10, ttl:) } + let(:disposable_mx_record) { double("MX", exchange: "emailfake.com", preference: 20, ttl:) } + + def address_with_mx_records(domain, mx_records) + allow(mock_resolv_dns).to receive(:getresources) + .with(domain, Resolv::DNS::Resource::IN::MX) + .and_return(mx_records) + + described_class.new("example@#{domain}", dns_instance) + end + + it "is disposable when an ordinary MX host with one dot is listed before a disposable one" do + address = address_with_mx_records("ordinary-first.example", [ordinary_mx_record, disposable_mx_record]) + expect(address.disposable?).to be_truthy + end + + it "is disposable when a disposable MX host is listed before an ordinary one with one dot" do + address = address_with_mx_records("disposable-first.example", [disposable_mx_record, ordinary_mx_record]) + expect(address.disposable?).to be_truthy + end + end end describe "#valid_strict_mx?" do