مراية لـ
https://github.com/postalserver/postal.git
تم المزامنة 2026-01-16 21:23:37 +00:00
refactor: refactor DNS resolution
This commit also adds some of tests for the Domain model. It was during the writing of these tests that the DNS resolution refactoring requirement became apparent.
هذا الالتزام موجود في:
@@ -43,8 +43,8 @@ module HasDNSChecks
|
||||
#
|
||||
|
||||
def check_spf_record
|
||||
result = resolver.getresources(name, Resolv::DNS::Resource::IN::TXT)
|
||||
spf_records = result.map(&:data).grep(/\Av=spf1/)
|
||||
result = resolver.txt(name)
|
||||
spf_records = result.grep(/\Av=spf1/)
|
||||
if spf_records.empty?
|
||||
self.spf_status = "Missing"
|
||||
self.spf_error = "No SPF record exists for this domain"
|
||||
@@ -73,8 +73,7 @@ module HasDNSChecks
|
||||
|
||||
def check_dkim_record
|
||||
domain = "#{dkim_record_name}.#{name}"
|
||||
result = resolver.getresources(domain, Resolv::DNS::Resource::IN::TXT)
|
||||
records = result.map(&:data)
|
||||
records = resolver.txt(domain)
|
||||
if records.empty?
|
||||
self.dkim_status = "Missing"
|
||||
self.dkim_error = "No TXT records were returned for #{domain}"
|
||||
@@ -104,8 +103,7 @@ module HasDNSChecks
|
||||
#
|
||||
|
||||
def check_mx_records
|
||||
result = resolver.getresources(name, Resolv::DNS::Resource::IN::MX)
|
||||
records = result.map(&:exchange)
|
||||
records = resolver.mx(name).map(&:last)
|
||||
if records.empty?
|
||||
self.mx_status = "Missing"
|
||||
self.mx_error = "There are no MX records for #{name}"
|
||||
@@ -134,8 +132,7 @@ module HasDNSChecks
|
||||
#
|
||||
|
||||
def check_return_path_record
|
||||
result = resolver.getresources(return_path_domain, Resolv::DNS::Resource::IN::CNAME)
|
||||
records = result.map { |r| r.name.to_s.downcase }
|
||||
records = resolver.cname(return_path_domain)
|
||||
if records.empty?
|
||||
self.return_path_status = "Missing"
|
||||
self.return_path_error = "There is no return path record at #{return_path_domain}"
|
||||
|
||||
@@ -77,7 +77,9 @@ class Domain < ApplicationRecord
|
||||
verified_at.present?
|
||||
end
|
||||
|
||||
def verify
|
||||
def mark_as_verified
|
||||
return false if verified?
|
||||
|
||||
self.verified_at = Time.now
|
||||
save!
|
||||
end
|
||||
@@ -94,6 +96,8 @@ class Domain < ApplicationRecord
|
||||
end
|
||||
|
||||
def dkim_key
|
||||
return nil unless dkim_private_key
|
||||
|
||||
@dkim_key ||= OpenSSL::PKey::RSA.new(dkim_private_key)
|
||||
end
|
||||
|
||||
@@ -114,28 +118,37 @@ class Domain < ApplicationRecord
|
||||
end
|
||||
|
||||
def dkim_record
|
||||
return if dkim_key.nil?
|
||||
|
||||
public_key = dkim_key.public_key.to_s.gsub(/-+[A-Z ]+-+\n/, "").gsub(/\n/, "")
|
||||
"v=DKIM1; t=s; h=sha256; p=#{public_key};"
|
||||
end
|
||||
|
||||
def dkim_identifier
|
||||
return nil unless dkim_identifier_string
|
||||
|
||||
Postal.config.dns.dkim_identifier + "-#{dkim_identifier_string}"
|
||||
end
|
||||
|
||||
def dkim_record_name
|
||||
"#{dkim_identifier}._domainkey"
|
||||
identifier = dkim_identifier
|
||||
return if identifier.nil?
|
||||
|
||||
"#{identifier}._domainkey"
|
||||
end
|
||||
|
||||
def return_path_domain
|
||||
"#{Postal.config.dns.custom_return_path_prefix}.#{name}"
|
||||
end
|
||||
|
||||
def nameservers
|
||||
@nameservers ||= get_nameservers
|
||||
end
|
||||
|
||||
# Returns a DNSResolver instance that can be used to perform DNS lookups needed for
|
||||
# the verification and DNS checking for this domain.
|
||||
#
|
||||
# @return [DNSResolver]
|
||||
def resolver
|
||||
@resolver ||= Postal.config.general.use_local_ns_for_domains? ? Resolv::DNS.new : Resolv::DNS.new(nameserver: nameservers)
|
||||
return DNSResolver.local if Postal.config.general.use_local_ns_for_domains?
|
||||
|
||||
@resolver ||= DNSResolver.for_domain(name)
|
||||
end
|
||||
|
||||
def dns_verification_string
|
||||
@@ -145,32 +158,14 @@ class Domain < ApplicationRecord
|
||||
def verify_with_dns
|
||||
return false unless verification_method == "DNS"
|
||||
|
||||
result = resolver.getresources(name, Resolv::DNS::Resource::IN::TXT)
|
||||
if result.map { |d| d.data.to_s.strip }.include?(dns_verification_string)
|
||||
result = resolver.txt(name)
|
||||
|
||||
if result.include?(dns_verification_string)
|
||||
self.verified_at = Time.now
|
||||
save
|
||||
else
|
||||
false
|
||||
return save
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_nameservers
|
||||
local_resolver = Resolv::DNS.new
|
||||
ns_records = []
|
||||
parts = name.split(".")
|
||||
(parts.size - 1).times do |n|
|
||||
d = parts[n, parts.size - n + 1].join(".")
|
||||
ns_records = local_resolver.getresources(d, Resolv::DNS::Resource::IN::NS).map { |s| s.name.to_s }
|
||||
break if ns_records.present?
|
||||
end
|
||||
return [] if ns_records.blank?
|
||||
|
||||
ns_records = ns_records.map { |r| local_resolver.getresources(r, Resolv::DNS::Resource::IN::A).map { |s| s.address.to_s } }.flatten
|
||||
return [] if ns_records.blank?
|
||||
|
||||
ns_records
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -54,8 +54,7 @@ class TrackDomain < ApplicationRecord
|
||||
end
|
||||
|
||||
def check_dns
|
||||
result = domain.resolver.getresources(full_name, Resolv::DNS::Resource::IN::CNAME)
|
||||
records = result.map { |r| r.name.to_s.downcase }
|
||||
records = domain.resolver.cname(full_name)
|
||||
if records.empty?
|
||||
self.dns_status = "Missing"
|
||||
self.dns_error = "There is no record at #{full_name}"
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم