feat(onboarding): detect email provider from domain MX records (#14571)

During account enrichment, WebsiteBrandingService now probes the signup
domain's MX records to infer whether email is hosted on Google Workspace
or Microsoft 365, adding `email_provider` (`google`/`microsoft`/`nil`)
to `brand_info`. Matching is anchored on a label boundary so lookalike
domains aren't misclassified, and lookup failures fall back to `nil`.
This lets downstream UI suggest the right mailbox integration (Gmail vs
Outlook).
This commit is contained in:
Shivam Mishra
2026-05-27 15:59:19 +05:30
committed by GitHub
parent 2628d7a7fd
commit 9c17a6f302
2 changed files with 36 additions and 1 deletions
+35 -1
View File
@@ -1,3 +1,5 @@
require 'resolv'
class WebsiteBrandingService
include SocialLinkParser
@@ -24,7 +26,8 @@ class WebsiteBrandingService
colors: extract_colors(doc),
logos: extract_logos(doc),
socials: build_socials(links),
email: @email
email: @email,
email_provider: detect_email_provider
})
rescue StandardError => e
Rails.logger.error "[WebsiteBranding] #{e.message}"
@@ -104,6 +107,37 @@ class WebsiteBrandingService
rescue URI::InvalidURIError
nil
end
GOOGLE_MX_DOMAINS = %w[google.com googlemail.com].freeze
MICROSOFT_MX_DOMAINS = %w[outlook.com].freeze
# Probes the domain's MX records to infer the mailbox provider, returning
# 'google' or 'microsoft' (matching Channel::Email#provider) or nil when unknown.
def detect_email_provider
hosts = mx_records
return 'google' if mx_hosted_by?(hosts, GOOGLE_MX_DOMAINS)
return 'microsoft' if mx_hosted_by?(hosts, MICROSOFT_MX_DOMAINS)
nil
end
# Matches on the registrable domain of the MX host (anchored on a label
# boundary) so lookalikes like "notgoogle.com" don't get misclassified.
def mx_hosted_by?(hosts, provider_domains)
hosts.any? do |host|
provider_domains.any? { |domain| host == domain || host.end_with?(".#{domain}") }
end
end
def mx_records
Resolv::DNS.open do |resolver|
resolver.timeouts = 5
resolver.getresources(@domain, Resolv::DNS::Resource::IN::MX).map { |record| record.exchange.to_s.downcase }
end
rescue StandardError => e
Rails.logger.error "[WebsiteBranding] MX probe failed for #{@domain}: #{e.message}"
[]
end
end
WebsiteBrandingService.prepend_mod_with('WebsiteBrandingService')
@@ -58,6 +58,7 @@ module Enterprise::WebsiteBrandingService
socials: brand['socials'] || [],
links: brand['links'],
email: @email,
email_provider: detect_email_provider,
industries: brand.dig('industries', 'eic') || [],
stock: brand['stock'],
is_nsfw: brand['is_nsfw'] || false