Do not accept invalid addresses in SMTP RCPT TO

This gives the MTA the chance to inform the original sender
about the transmission error via a delivery report.
This commit is contained in:
Patrick Gansterer 2017-10-02 16:24:10 +02:00
parent e017a1196e
commit b35357d4b3
2 changed files with 110 additions and 22 deletions

View file

@ -10,36 +10,45 @@ class FoodsoftMailReceiver < MidiSmtpServer::Smtpd
end
def self.received(recipient, data)
find_handler(recipient).call(data)
end
def start
super
@handlers = []
end
private
def on_rcpt_to_event(ctx, rcpt_to)
recipient = rcpt_to.gsub(/^\s*<\s*(.*)\s*>\s*$/, '\1')
@handlers << self.class.find_handler(recipient)
rcpt_to
rescue => error
raise MidiSmtpServer::Smtpd550Exception
end
def on_message_data_event(ctx)
@handlers.each do |handler|
handler.call(ctx[:message][:data])
end
@handlers.clear
end
def self.find_handler(recipient)
m = /(?<foodcoop>[^@\.]+)\.(?<address>[^@]+)(@(?<hostname>[^@]+))?/.match recipient
raise "recipient is missing or has an invalid format" if m.nil?
raise "Foodcoop '#{m[:foodcoop]}' could not be found" unless FoodsoftConfig.foodcoops.include? m[:foodcoop]
raise "Foodcoop '#{m[:foodcoop]}' could not be found" unless FoodsoftConfig.allowed_foodcoop? m[:foodcoop]
FoodsoftConfig.select_multifoodcoop m[:foodcoop]
@@registered_classes.each do |klass|
klass_m = klass.regexp.match(m[:address])
return klass.new(klass_m).received(data) if klass_m
if match = klass.regexp.match(m[:address])
handler = klass.new match
return lambda { |data| handler.received(data) }
end
end
raise "invalid format for recipient"
end
def start
super
end
private
def on_message_data_event(ctx)
puts ctx[:envelope][:to]
ctx[:envelope][:to].each do |to|
begin
m = /<(?<recipient>[^<>]+)>/.match(to)
raise "invalid format for RCPT TO" if m.nil?
FoodsoftMailReceiver.received(m[:recipient], ctx[:message][:data])
rescue => error
Rails.logger.warn "Can't deliver mail to #{to}: #{error.message}"
end
end
end
end