mailinglist.rb/lib/protocols/smtp.rb
Arthur POULET cbf43f741d
Fix distribution cache
The cache was not working properly as it intercepted all the emails
except for the first receiver.
2023-06-21 19:40:18 +02:00

70 lines
1.6 KiB
Ruby

require "net/smtp"
# High level Interface to distribute Protocols::Mail objects.
# It is robust against network loss.
class Protocols::Smtp
def initialize
reset_smtp_client!
end
class DistributedCache < Array
def initialize(max_size: 4096)
@max_size = max_size
super()
end
def <<(message_id)
prepend(message_id) if !message_id.nil?
slice! @max_size
end
end
def cache
(@cache ||= DistributedCache.new)
end
# @param mail [Protocols::Mail]
def distribute(mail)
if cache.include?(mail.cache_id)
$logger.warn "Already distributed #{mail.message_id}"
return
end
$logger.info "SEND #{mail.from}\t -> #{mail.to}:\t#{mail.subject}"
smtp_raw = mail.to_smtp
$logger.debug smtp_raw.join("=====")
send_message_safe(*smtp_raw)
cache << mail.cache_id
rescue StandardError => e
$logger.warn "FAILED #{mail.from}\t -> #{mail.to}:\t#{mail.subject}"
$logger.debug e
end
# :nodoc:
private def reset_smtp_client!
@smtp = Net::SMTP.new(
ENV["SMTP_HOST"], ENV["SMTP_PORT"], tls: ENV["SMTP_TLS"] == "true",
).start(
user: ENV["SMTP_USER"],
secret: ENV["SMTP_PASSWORD"],
authtype: :login,
)
end
# :nodoc:
private def send_message_safe(*raw, max_tries: 3)
return $logger.error("send_message_safe reached max_tries_limit") if max_tries == 0
begin
@smtp.send_message(*raw)
rescue EOFError, Net::SMTPServerBusy => e
$logger.warn e.message
reset_smtp_client!
send_message_safe(*raw, max_tries: max_tries - 1)
rescue => e
$logger.error e.full_message
reset_smtp_client!
end
end
end