Permette di leggere i bounce dalla stessa MailIdentity SMTP, aggiornare le email in anagrafica e saltare gli indirizzi invalidi nei mailing. Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
3.4 KiB
Ruby
120 lines
3.4 KiB
Ruby
class MailIdentity < ApplicationRecord
|
|
include Auditable
|
|
|
|
encrypts :smtp_password
|
|
|
|
require "openssl"
|
|
|
|
has_many :mailings, dependent: :restrict_with_exception
|
|
|
|
ENCRYPTIONS = Catalog::MAIL_ENCRYPTIONS.keys.freeze
|
|
|
|
# Mapping host SMTP → IMAP tipici dei provider usati in produzione.
|
|
IMAP_HOST_HINTS = {
|
|
"aruba.it" => "imaps.aruba.it",
|
|
"smtps.aruba.it" => "imaps.aruba.it",
|
|
"smtp.aruba.it" => "imaps.aruba.it",
|
|
"gmail.com" => "imap.gmail.com",
|
|
"smtp.gmail.com" => "imap.gmail.com",
|
|
"outlook.com" => "outlook.office365.com",
|
|
"smtp.office365.com" => "outlook.office365.com"
|
|
}.freeze
|
|
|
|
validates :name, :from_name, :from_email, :smtp_host, :smtp_port, presence: true
|
|
validates :from_email, format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
validates :reply_to, format: { with: URI::MailTo::EMAIL_REGEXP }, allow_blank: true
|
|
validates :smtp_port, numericality: { in: 1..65535 }
|
|
validates :imap_port, numericality: { in: 1..65535 }, allow_nil: true
|
|
validates :encryption, inclusion: { in: ENCRYPTIONS }
|
|
validates :smtp_authentication, inclusion: { in: Catalog::MAIL_AUTH_METHODS.keys }
|
|
validate :encryption_matches_port
|
|
|
|
before_validation :apply_imap_defaults
|
|
|
|
scope :active, -> { where(active: true) }
|
|
scope :imap_enabled, -> { where(imap_enabled: true) }
|
|
scope :ordered, -> { order(:name) }
|
|
|
|
def from_header
|
|
%(#{from_name} <#{from_email}>)
|
|
end
|
|
|
|
def smtp_settings
|
|
settings = {
|
|
address: smtp_host,
|
|
port: smtp_port,
|
|
enable_starttls_auto: encryption == "starttls",
|
|
ssl: encryption == "tls",
|
|
openssl_verify_mode: verify_ssl? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE,
|
|
open_timeout: 15,
|
|
read_timeout: 60
|
|
}
|
|
if smtp_username.present?
|
|
settings[:user_name] = smtp_username
|
|
settings[:password] = smtp_password
|
|
settings[:authentication] = smtp_authentication.to_sym
|
|
end
|
|
settings
|
|
end
|
|
|
|
def imap_username
|
|
smtp_username.presence || from_email
|
|
end
|
|
|
|
def effective_imap_host
|
|
imap_host.presence || inferred_imap_host
|
|
end
|
|
|
|
def effective_imap_port
|
|
(imap_port.presence || 993).to_i
|
|
end
|
|
|
|
def imap_ready?
|
|
imap_enabled? && effective_imap_host.present? && effective_imap_port.positive?
|
|
end
|
|
|
|
def imap_settings
|
|
{
|
|
address: effective_imap_host,
|
|
port: effective_imap_port,
|
|
ssl: true,
|
|
user_name: imap_username,
|
|
password: smtp_password
|
|
}
|
|
end
|
|
|
|
def inferred_imap_host
|
|
host = smtp_host.to_s.downcase.strip
|
|
return if host.blank?
|
|
|
|
IMAP_HOST_HINTS.each do |needle, imap|
|
|
return imap if host == needle || host.end_with?(".#{needle}") || host.include?(needle)
|
|
end
|
|
|
|
# Fallback generico: smtp.X → imap.X, smtps.X → imaps.X
|
|
if host.start_with?("smtps.")
|
|
host.sub(/\Asmtps\./, "imaps.")
|
|
elsif host.start_with?("smtp.")
|
|
host.sub(/\Asmtp\./, "imap.")
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def apply_imap_defaults
|
|
self.imap_port = 993 if imap_port.blank?
|
|
self.imap_enabled = true if imap_enabled.nil?
|
|
self.imap_host = inferred_imap_host if imap_host.blank? && inferred_imap_host.present?
|
|
end
|
|
|
|
def encryption_matches_port
|
|
return if smtp_port.blank? || encryption.blank?
|
|
|
|
if encryption == "tls" && smtp_port == 587
|
|
errors.add(:smtp_port, "con SSL/TLS va usata la porta 465 (es. smtps.aruba.it)")
|
|
elsif encryption == "starttls" && smtp_port == 465
|
|
errors.add(:smtp_port, "con STARTTLS va usata la porta 587 (es. smtp.aruba.it)")
|
|
end
|
|
end
|
|
end
|