مراية لـ
https://github.com/postalserver/postal.git
تم المزامنة 2025-11-30 21:32:30 +00:00
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.
172 أسطر
4.4 KiB
Ruby
172 أسطر
4.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: domains
|
|
#
|
|
# id :integer not null, primary key
|
|
# server_id :integer
|
|
# uuid :string(255)
|
|
# name :string(255)
|
|
# verification_token :string(255)
|
|
# verification_method :string(255)
|
|
# verified_at :datetime
|
|
# dkim_private_key :text(65535)
|
|
# created_at :datetime
|
|
# updated_at :datetime
|
|
# dns_checked_at :datetime
|
|
# spf_status :string(255)
|
|
# spf_error :string(255)
|
|
# dkim_status :string(255)
|
|
# dkim_error :string(255)
|
|
# mx_status :string(255)
|
|
# mx_error :string(255)
|
|
# return_path_status :string(255)
|
|
# return_path_error :string(255)
|
|
# outgoing :boolean default(TRUE)
|
|
# incoming :boolean default(TRUE)
|
|
# owner_type :string(255)
|
|
# owner_id :integer
|
|
# dkim_identifier_string :string(255)
|
|
# use_for_any :boolean
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_domains_on_server_id (server_id)
|
|
# index_domains_on_uuid (uuid)
|
|
#
|
|
|
|
require "resolv"
|
|
|
|
class Domain < ApplicationRecord
|
|
|
|
include HasUUID
|
|
|
|
include HasDNSChecks
|
|
|
|
VERIFICATION_EMAIL_ALIASES = %w[webmaster postmaster admin administrator hostmaster].freeze
|
|
VERIFICATION_METHODS = %w[DNS Email].freeze
|
|
|
|
belongs_to :server, optional: true
|
|
belongs_to :owner, optional: true, polymorphic: true
|
|
has_many :routes, dependent: :destroy
|
|
has_many :track_domains, dependent: :destroy
|
|
|
|
validates :name, presence: true, format: { with: /\A[a-z0-9\-.]*\z/ }, uniqueness: { case_sensitive: false, scope: [:owner_type, :owner_id], message: "is already added" }
|
|
validates :verification_method, inclusion: { in: VERIFICATION_METHODS }
|
|
|
|
random_string :dkim_identifier_string, type: :chars, length: 6, unique: true, upper_letters_only: true
|
|
|
|
before_create :generate_dkim_key
|
|
|
|
scope :verified, -> { where.not(verified_at: nil) }
|
|
|
|
when_attribute :verification_method, changes_to: :anything do
|
|
before_save do
|
|
if verification_method == "DNS"
|
|
self.verification_token = Nifty::Utils::RandomString.generate(length: 32)
|
|
elsif verification_method == "Email"
|
|
self.verification_token = rand(999_999).to_s.ljust(6, "0")
|
|
else
|
|
self.verification_token = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
def verified?
|
|
verified_at.present?
|
|
end
|
|
|
|
def mark_as_verified
|
|
return false if verified?
|
|
|
|
self.verified_at = Time.now
|
|
save!
|
|
end
|
|
|
|
def parent_domains
|
|
parts = name.split(".")
|
|
parts[0, parts.size - 1].each_with_index.map do |_, i|
|
|
parts[i..].join(".")
|
|
end
|
|
end
|
|
|
|
def generate_dkim_key
|
|
self.dkim_private_key = OpenSSL::PKey::RSA.new(1024).to_s
|
|
end
|
|
|
|
def dkim_key
|
|
return nil unless dkim_private_key
|
|
|
|
@dkim_key ||= OpenSSL::PKey::RSA.new(dkim_private_key)
|
|
end
|
|
|
|
def to_param
|
|
uuid
|
|
end
|
|
|
|
def verification_email_addresses
|
|
parent_domains.map do |domain|
|
|
VERIFICATION_EMAIL_ALIASES.map do |a|
|
|
"#{a}@#{domain}"
|
|
end
|
|
end.flatten
|
|
end
|
|
|
|
def spf_record
|
|
"v=spf1 a mx include:#{Postal.config.dns.spf_include} ~all"
|
|
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
|
|
identifier = dkim_identifier
|
|
return if identifier.nil?
|
|
|
|
"#{identifier}._domainkey"
|
|
end
|
|
|
|
def return_path_domain
|
|
"#{Postal.config.dns.custom_return_path_prefix}.#{name}"
|
|
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
|
|
return DNSResolver.local if Postal.config.general.use_local_ns_for_domains?
|
|
|
|
@resolver ||= DNSResolver.for_domain(name)
|
|
end
|
|
|
|
def dns_verification_string
|
|
"#{Postal.config.dns.domain_verify_prefix} #{verification_token}"
|
|
end
|
|
|
|
def verify_with_dns
|
|
return false unless verification_method == "DNS"
|
|
|
|
result = resolver.txt(name)
|
|
|
|
if result.include?(dns_verification_string)
|
|
self.verified_at = Time.now
|
|
return save
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
end
|