M365 Checker

GitHub logo
| Ruby |

While building Erudite I had to write a report, in said report I discuss the dominance Microsoft and their services hold on the Education sector. As a vouch I wrote a script that did a best-guess on whether the university FOI email addresses were associated with Microsoft. The script is on GitHub, but it’s tiny, so I’ll save you the hassle :).

require 'resolv'
require 'json'
require 'timeout'

def safe_dns_lookup(seconds = 5)
  Timeout.timeout(seconds) { yield }
rescue Timeout::Error
  []
end

def likely_using_m365?(domain)
  # Check MX Records
  mx_records = safe_dns_lookup { Resolv::DNS.open { |dns| dns.getresources(domain, Resolv::DNS::Resource::IN::MX) } }
  mx_points_to_m365 = mx_records.any? { |mx| mx.exchange.to_s.include?('protection.outlook.com') }

  # Check Autodiscover CNAME
  autodiscover_record = safe_dns_lookup { Resolv::DNS.open { |dns| dns.getresources("autodiscover.#{domain}", Resolv::DNS::Resource::IN::CNAME) } }
  autodiscover_points_to_m365 = autodiscover_record.any? { |cname| cname.name.to_s.include?('autodiscover.outlook.com') }

  # Check TXT Records (SPF)
  txt_records = safe_dns_lookup { Resolv::DNS.open { |dns| dns.getresources(domain, Resolv::DNS::Resource::IN::TXT) } }
  spf_points_to_m365 = txt_records.any? { |txt| txt.strings.join.include?('spf.protection.outlook.com') }

  # Determine if domain is likely using M365
  mx_points_to_m365 || autodiscover_points_to_m365 || spf_points_to_m365
end

# Reduced for readability, but you get the idea
input = {
  "emails" => [
    "[email protected]",
  ]
}

results = {
  "likely_using_m365" => [],
  "not_using_m365" => []
}

input["emails"].each do |email|
  if likely_using_m365?(domain)
    results["likely_using_m365"] << email
  else
    results["not_using_m365"] << email
  end
end

puts "Likely:  #{results["likely_using_m365"].size} vs Unlikely: #{results["not_using_m365"].size}"