مراية لـ
https://github.com/postalserver/postal.git
تم المزامنة 2025-12-01 05:43:04 +00:00
176 أسطر
4.4 KiB
Ruby
176 أسطر
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) }
|
|
|
|
before_save :update_verification_token_on_method_change
|
|
|
|
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.postal.use_local_ns_for_domain_verification?
|
|
|
|
@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
|
|
|
|
private
|
|
|
|
def update_verification_token_on_method_change
|
|
return unless verification_method_changed?
|
|
|
|
if verification_method == "DNS"
|
|
self.verification_token = SecureRandom.alphanumeric(32)
|
|
elsif verification_method == "Email"
|
|
self.verification_token = rand(999_999).to_s.ljust(6, "0")
|
|
else
|
|
self.verification_token = nil
|
|
end
|
|
end
|
|
|
|
end
|