2017-08-19 15:45:48 +02:00
|
|
|
require 'mail'
|
|
|
|
require 'midi-smtp-server'
|
|
|
|
|
|
|
|
class FoodsoftMailReceiver < MidiSmtpServer::Smtpd
|
|
|
|
@@registered_classes = Set.new
|
|
|
|
|
|
|
|
def self.register(klass)
|
|
|
|
@@registered_classes.add klass
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.received(recipient, data)
|
2017-10-02 16:24:10 +02:00
|
|
|
find_handler(recipient).call(data)
|
2017-08-19 15:45:48 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def start
|
|
|
|
super
|
2017-10-02 16:24:10 +02:00
|
|
|
@handlers = []
|
2017-08-19 15:45:48 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2023-01-06 16:27:41 +01:00
|
|
|
def on_rcpt_to_event(_ctx, rcpt_to)
|
2017-10-02 16:24:10 +02:00
|
|
|
recipient = rcpt_to.gsub(/^\s*<\s*(.*)\s*>\s*$/, '\1')
|
|
|
|
@handlers << self.class.find_handler(recipient)
|
|
|
|
rcpt_to
|
2023-05-12 13:01:12 +02:00
|
|
|
rescue StandardError => e
|
|
|
|
logger.info("Can not accept mail for '#{rcpt_to}': #{e}")
|
2017-10-02 16:24:10 +02:00
|
|
|
raise MidiSmtpServer::Smtpd550Exception
|
|
|
|
end
|
|
|
|
|
2017-08-19 15:45:48 +02:00
|
|
|
def on_message_data_event(ctx)
|
2023-01-06 16:27:41 +01:00
|
|
|
@handlers.each do |handler|
|
|
|
|
handler.call(ctx[:message][:data])
|
2017-10-02 16:24:10 +02:00
|
|
|
end
|
2023-05-12 13:01:12 +02:00
|
|
|
rescue StandardError => e
|
|
|
|
ExceptionNotifier.notify_exception(e, data: ctx)
|
|
|
|
raise e
|
2023-01-06 16:27:41 +01:00
|
|
|
ensure
|
|
|
|
@handlers.clear
|
2017-10-02 16:24:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.find_handler(recipient)
|
2023-01-06 16:27:41 +01:00
|
|
|
m = /(?<foodcoop>[^@.]+)\.(?<address>[^@]+)(@(?<hostname>[^@]+))?/.match recipient
|
2023-05-12 13:01:12 +02:00
|
|
|
raise 'recipient is missing or has an invalid format' if m.nil?
|
2017-10-02 16:24:10 +02:00
|
|
|
raise "Foodcoop '#{m[:foodcoop]}' could not be found" unless FoodsoftConfig.allowed_foodcoop? m[:foodcoop]
|
2021-03-01 15:27:26 +01:00
|
|
|
|
2017-10-02 16:24:10 +02:00
|
|
|
FoodsoftConfig.select_multifoodcoop m[:foodcoop]
|
|
|
|
|
|
|
|
@@registered_classes.each do |klass|
|
|
|
|
if match = klass.regexp.match(m[:address])
|
|
|
|
handler = klass.new match
|
2023-01-06 16:27:41 +01:00
|
|
|
return ->(data) { handler.received(data) }
|
2017-08-19 15:45:48 +02:00
|
|
|
end
|
|
|
|
end
|
2017-10-02 16:24:10 +02:00
|
|
|
|
2023-05-12 13:01:12 +02:00
|
|
|
raise 'invalid format for recipient'
|
2017-08-19 15:45:48 +02:00
|
|
|
end
|
|
|
|
end
|