Skip to content

Commit

Permalink
Move SMTP server from messages plugin into core
Browse files Browse the repository at this point in the history
  • Loading branch information
paroga committed Sep 30, 2017
1 parent 2264351 commit 7d594bf
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 92 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -48,6 +48,7 @@ gem 'roo-xls'
gem 'spreadsheet'
gem 'gaffe'
gem 'ruby-filemagic'
gem 'midi-smtp-server'

# we use the git version of acts_as_versioned, and need to include it in this Gemfile
gem 'acts_as_versioned', git: 'https://github.com/technoweenie/acts_as_versioned.git'
Expand Down
6 changes: 2 additions & 4 deletions Gemfile.lock
Expand Up @@ -24,9 +24,7 @@ PATH
foodsoft_messages (0.0.1)
base32
deface (~> 1.0)
gserver
mail
mini-smtp-server
rails

PATH
Expand Down Expand Up @@ -172,7 +170,6 @@ GEM
git-version-bump (0.15.1)
globalid (0.3.7)
activesupport (>= 4.1.0)
gserver (0.0.1)
haml (4.0.7)
tilt
haml-rails (0.9.0)
Expand Down Expand Up @@ -240,10 +237,10 @@ GEM
rack-contrib (~> 1.1)
railties (>= 3.0.0, < 5.1.0)
method_source (0.8.2)
midi-smtp-server (2.1.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini-smtp-server (0.0.2)
mini_portile2 (2.2.0)
minitest (5.10.1)
mono_logger (1.1.0)
Expand Down Expand Up @@ -518,6 +515,7 @@ DEPENDENCIES
localize_input!
mailcatcher
meta_request
midi-smtp-server
mysql2
prawn
prawn-table
Expand Down
45 changes: 45 additions & 0 deletions lib/foodsoft_mail_receiver.rb
@@ -0,0 +1,45 @@
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)
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]
FoodsoftConfig.select_multifoodcoop m[:foodcoop]

@@registered_classes.each do |klass|
klass_m = klass.regexp.match(m[:address])
return klass.new.received klass_m, data if klass_m
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
15 changes: 15 additions & 0 deletions lib/tasks/foodsoft.rake
Expand Up @@ -43,6 +43,21 @@ namespace :foodsoft do
rake_say "created until #{created_until}"
end
end

desc "Parse incoming email on stdin (options: RECIPIENT=foodcoop.handling)"
task :parse_reply_email => :environment do
FoodsoftMailReceiver.received ENV['RECIPIENT'], STDIN.read
end

desc "Start STMP server for incoming email (options: SMTP_SERVER_PORT=2525, SMTP_SERVER_HOST=0.0.0.0)"
task :reply_email_smtp_server => :environment do
port = ENV['SMTP_SERVER_PORT'].present? ? ENV['SMTP_SERVER_PORT'].to_i : 2525
host = ENV['SMTP_SERVER_HOST']
rake_say "Started SMTP server for incoming email on port #{port}."
server = FoodsoftMailReceiver.new port, host
server.start
server.join
end
end

# Helper
Expand Down
50 changes: 50 additions & 0 deletions plugins/messages/app/mail_receivers/messages_mail_receiver.rb
@@ -0,0 +1,50 @@
class MessagesMailReceiver

def self.regexp
/(?<message_id>\d+)\.(?<user_id>\d+)\.(?<hash>\w+)/
end

def received(match, data)
original_message = Message.find_by_id(match[:message_id])
user = User.find_by_id(match[:user_id])

raise "Message could not be found" if original_message.nil?
raise "User could not be found" if user.nil?

hash = original_message.mail_hash_for_user user
raise "Hash does not match expectations" unless hash.casecmp(match[:hash]) == 0

mail = Mail.new data

mail_part = nil
if mail.multipart?
for part in mail.parts
mail_part = part if MIME::Type.simplified(part.content_type) == "text/plain"
end
else
mail_part = mail
end

body = mail_part.body.decoded
unless mail_part.content_type_parameters.nil?
body = body.force_encoding mail_part.content_type_parameters[:charset]
end

message = user.send_messages.new body: body,
group: original_message.group,
private: original_message.private,
received_email: received_email,
subject: mail.subject.gsub("[#{FoodsoftConfig[:name]}] ", "")
if original_message.reply_to
message.reply_to_message = original_message.reply_to_message
else
message.reply_to_message = original_message
end
message.add_recipients original_message.recipients
message.add_recipients [original_message.sender]

message.save!
Resque.enqueue(MessageNotifier, FoodsoftConfig.scope, "message_deliver", message.id)
end

end
2 changes: 0 additions & 2 deletions plugins/messages/foodsoft_messages.gemspec
Expand Up @@ -20,8 +20,6 @@ Gem::Specification.new do |s|
s.add_dependency "base32"
s.add_dependency "deface", "~> 1.0"
s.add_dependency "mail"
s.add_dependency "mini-smtp-server"
s.add_dependency "gserver"

s.add_development_dependency "sqlite3"
end
1 change: 1 addition & 0 deletions plugins/messages/lib/foodsoft_messages.rb
@@ -1,4 +1,5 @@
require "foodsoft_messages/engine"
require "foodsoft_messages/mail_receiver"
require "foodsoft_messages/user_link"
require "deface"

Expand Down
3 changes: 3 additions & 0 deletions plugins/messages/lib/foodsoft_messages/mail_receiver.rb
@@ -0,0 +1,3 @@
ActiveSupport.on_load(:after_initialize) do
FoodsoftMailReceiver.register MessagesMailReceiver
end
86 changes: 0 additions & 86 deletions plugins/messages/lib/tasks/foodsoft.rake

This file was deleted.

0 comments on commit 7d594bf

Please sign in to comment.