tracks/app/models/message_gateway.rb
Reinier Balt 25600e39f7 refactor adding attachments in message_gateway
and remove gsub magic with correct tempfile parameter
2015-08-04 13:02:56 +02:00

144 lines
4.4 KiB
Ruby

require 'tempfile'
class MessageGateway < ActionMailer::Base
def receive(email)
user = get_receiving_user_from_email_address(email)
return false if user.nil?
return false unless check_sender_is_in_mailmap(user, email)
context = user.prefs.sms_context
todo_params = get_todo_params(email)
todo_builder = TodoFromRichMessage.new(user, context.id, todo_params[:description], todo_params[:notes])
todo = todo_builder.construct
saved = todo.save!
if saved
Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
saved = attach_email_to_todo(todo, email)
if saved
Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
end
end
todo
end
private
def attach_email_to_todo(todo, email)
attachment = todo.attachments.build
# create temp file
tmp = Tempfile.new(['attachment', '.eml'], universal_newline: true)
tmp.write email.raw_source
# add temp file to attachment. paperclip will copy the file to the right location
Rails.logger.info "Saved received email to #{tmp.path}"
attachment.file = tmp
tmp.close
saved = attachment.save!
# delete temp file
tmp.unlink
end
def get_todo_params(email)
params = {}
if email.multipart?
params[:description] = get_text_or_nil(email.subject)
params[:notes] = get_first_text_plain_part(email)
else
if email.subject.blank?
params[:description] = get_decoded_text_or_nil(email.body)
params[:notes] = nil
else
params[:description] = get_text_or_nil(email.subject)
params[:notes] = get_decoded_text_or_nil(email.body)
end
end
params
end
def get_receiving_user_from_email_address(email)
SITE_CONFIG['email_dispatch'] == 'single_user' ? get_receiving_user_from_env_setting : get_receiving_user_from_mail_header(email)
end
def get_receiving_user_from_env_setting
Rails.logger.info "All received email goes to #{ENV['TRACKS_MAIL_RECEIVER']}"
user = User.where(:login => ENV['TRACKS_MAIL_RECEIVER']).first
Rails.logger.info "WARNING: Unknown user set for TRACKS_MAIL_RECEIVER (#{ENV['TRACKS_MAIL_RECEIVER']})" if user.nil?
return user
end
def get_receiving_user_from_mail_header(email)
user = get_receiving_user_from_sms_email( get_address(email) )
Rails.logger.info(user.nil? ? "User unknown": "Email belongs to #{user.login}")
return user
end
def get_address(email)
return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0]
end
def get_receiving_user_from_sms_email(address)
Rails.logger.info "Looking for user with email #{address}"
user = User.where("preferences.sms_email" => address.strip).includes(:preference).first
user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first if user.nil?
return user
end
def check_sender_is_in_mailmap(user, email)
if user.present? and !sender_is_in_mailmap?(user,email)
Rails.logger.warn "#{email.from[0]} not found in mailmap for #{user.login}"
return false
end
return true
end
def sender_is_in_mailmap?(user,email)
if SITE_CONFIG['mailmap'].is_a? Hash and SITE_CONFIG['email_dispatch'] == 'to'
# Look for the sender in the map of allowed senders
SITE_CONFIG['mailmap'][user.preference.sms_email].include? email.from[0]
else
# We can't check the map if it's not defined, or if the lookup is the
# wrong way round, so just allow it
true
end
end
def get_text_or_nil(text)
return text ? text.strip : nil
end
def get_decoded_text_or_nil(text)
return text ? text.decoded.strip : nil
end
def get_first_text_plain_part(email)
# get all parts from multipart/alternative attachments
parts = get_all_parts(email.parts)
# remove all parts that are not text/plain
parts.reject{|part| !part.content_type.start_with?("text/plain") }
return parts.count > 0 ? parts[0].decoded.strip : ""
end
def get_all_parts(parts)
# return a flattened array of parts. If a multipart attachment is found, recurse over its parts
all_parts = parts.inject([]) do |set, elem|
if elem.content_type.start_with?("multipart/alternative")
# recurse to handle multiparts in this multipart
set += get_all_parts(elem.parts)
else
set << elem
end
end
end
end