From 04123e33590088706d569fc1f529fb4fdbbbce65 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 6 May 2012 22:48:23 +0200 Subject: [PATCH] Added x-header support and unit tests. --- app/models/channel/email_parser.rb | 101 ++++++++++++++++++++++++----- test/test_helper.rb | 3 + test/unit/email_parser_test.rb | 2 +- test/unit/email_process_test.rb | 69 ++++++++++++++++++++ 4 files changed, 156 insertions(+), 19 deletions(-) create mode 100644 test/unit/email_process_test.rb diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb index 49b5a263f..ee9bf35b2 100644 --- a/app/models/channel/email_parser.rb +++ b/app/models/channel/email_parser.rb @@ -78,18 +78,39 @@ class Channel::EmailParser def process(channel, msg) mail = parse( msg ) + # check if trust x-headers + if !channel[:trusted] + mail.each {|key, value| + if key =~ /^x-zammad/i + mail.delete(key) + end + } + end + + # check ignore header + return true if mail[ 'x-zammad-ignore'.to_sym ] == 'true' || mail[ 'x-zammad-ignore'.to_sym ] == true + + ticket = nil + article = nil + user = nil + # use transaction ActiveRecord::Base.transaction do - user = User.where( :email => mail[:from_email] ).first - if !user then + if mail[ 'x-zammad-customer-login'.to_sym ] + user = User.where( :login => mail[ 'x-zammad-customer-login'.to_sym ] ).first + end + if !user + user = User.where( :email => mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email] ).first + end + if !user puts 'create user...' roles = Role.where( :name => 'Customer' ) user = User.create( - :login => mail[:from_email], - :firstname => mail[:from_display_name], - :lastname => '', - :email => mail[:from_email], + :login => mail[ 'x-zammad-customer-login'.to_sym ] || mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email], + :firstname => mail[ 'x-zammad-customer-firstname'.to_sym ] || mail[:from_display_name], + :lastname => mail[ 'x-zammad-customer-lastname'.to_sym ], + :email => mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email], :password => '', :active => true, :roles => roles, @@ -114,31 +135,73 @@ class Channel::EmailParser end # create new ticket - if !ticket then - ticket = Ticket.create( + if !ticket + + # set attributes + ticket_attributes = { :group_id => channel[:group_id] || 1, :customer_id => user.id, :title => mail[:subject], - :ticket_state_id => Ticket::State.where(:name => 'new').first.id, - :ticket_priority_id => Ticket::Priority.where(:name => '2 normal').first.id, - :created_by_id => user.id - ) + :ticket_state_id => Ticket::State.where( :name => 'new' ).first.id, + :ticket_priority_id => Ticket::Priority.where( :name => '2 normal' ).first.id, + :created_by_id => user.id, + } + + # x-headers lookup + map = [ + [ 'x-zammad-group', Group, 'group_id', 'name' ], + [ 'x-zammad-state', Ticket::State, 'ticket_state_id', 'name' ], + [ 'x-zammad-priority', Ticket::Priority, 'ticket_priority_id', 'name' ], + [ 'x-zammad-owner', User, 'owner_id', 'login' ], + ] + map.each { |item| + if mail[ item[0].to_sym ] + if item[1].where( item[3].to_sym => mail[ item[0].to_sym ] ).first + ticket_attributes[ item[2].to_sym ] = item[1].where( item[3].to_sym => mail[ item[0].to_sym ] ).first.id + end + end + } + + # create ticket + ticket = Ticket.create( ticket_attributes ) end # import mail - article = Ticket::Article.create( + + # set attributes + internal = false + if mail[ 'X-Zammad-Article-Visability'.to_sym ] && mail[ 'X-Zammad-Article-Visability'.to_sym ] == 'internal' + internal = true + end + article_attributes = { :created_by_id => user.id, :ticket_id => ticket.id, - :ticket_article_type_id => Ticket::Article::Type.where(:name => 'email').first.id, - :ticket_article_sender_id => Ticket::Article::Sender.where(:name => 'Customer').first.id, + :ticket_article_type_id => Ticket::Article::Type.where( :name => 'email' ).first.id, + :ticket_article_sender_id => Ticket::Article::Sender.where( :name => 'Customer' ).first.id, :body => mail[:plain_part], :from => mail[:from], :to => mail[:to], :cc => mail[:cc], :subject => mail[:subject], :message_id => mail[:message_id], - :internal => false - ) + :internal => internal, + } + + # x-headers lookup + map = [ + [ 'x-zammad-article-type', Ticket::Article::Type, 'ticket_article_type_id', 'name' ], + [ 'x-zammad-article-sender', Ticket::Article::Sender, 'ticket_article_sender_id', 'name' ], + ] + map.each { |item| + if mail[ item[0].to_sym ] + if item[1].where( item[3].to_sym => mail[ item[0].to_sym ] ).first + article_attributes[ item[2].to_sym ] = item[1].where( item[3].to_sym => mail[ item[0].to_sym ] ).first.id + end + end + } + + # create article + article = Ticket::Article.create(article_attributes) # store mail plain Store.add( @@ -161,10 +224,12 @@ class Channel::EmailParser ) end end - return ticket, article, user end # execute ticket events Ticket::Observer::Notification.transaction + + # return new objects + return ticket, article, user end end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 8bf1192ff..259170548 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -9,5 +9,8 @@ class ActiveSupport::TestCase # -- they do not yet inherit this setting fixtures :all + # load seeds + load "#{Rails.root}/db/seeds.rb" + # Add more helper methods to be used by all tests here... end diff --git a/test/unit/email_parser_test.rb b/test/unit/email_parser_test.rb index 77c03aedc..1b950ebb8 100644 --- a/test/unit/email_parser_test.rb +++ b/test/unit/email_parser_test.rb @@ -45,7 +45,7 @@ class EmailParserTest < ActiveSupport::TestCase # check body md5 = Digest::MD5.hexdigest( data[:plain_part] ) assert_equal( file[:body_md5], md5 ) - puts data[:from] + # check params file[:params].each { |key, value| if key.to_s == 'plain_part' diff --git a/test/unit/email_process_test.rb b/test/unit/email_process_test.rb new file mode 100644 index 000000000..b99200ba7 --- /dev/null +++ b/test/unit/email_process_test.rb @@ -0,0 +1,69 @@ +# encoding: utf-8 +require 'test_helper' + +class EmailProcessTest < ActiveSupport::TestCase + test 'process' do + files = [ + { + :data => 'From: me@example.com +To: customer@example.com +Subject: some subject + +Some Text', + :success => true, + }, + { + :data => 'From: me@example.com +To: customer@example.com +Subject: some subject +X-Zammad-Ignore: true + +Some Text', + :success => false, + }, + { + :data => 'From: me@example.com +To: customer@example.com +Subject: some subject +X-Zammad-Priority: 3 high +X-Zammad-Article-Sender: system +x-Zammad-Article-Type: phone + +Some Text', + :success => true, + :result => { + 0 => { + :ticket_priority => '3 high', + }, + 1 => { + :ticket_article_sender => 'System', + :ticket_article_type => 'phone', + }, + }, + }, + ] + + files.each { |file| + parser = Channel::EmailParser.new + result = parser.process( { :trusted => true }, file[:data] ) + if file[:success] && result[1] + assert( true ) + if file[:result] + [ 0, 1, 2 ].each { |level| + if file[:result][level] + file[:result][level].each { |key, value| + assert_equal( result[level].send(key).name, value.to_s) + } + end + } + end + elsif !file[:success] && result == true + assert( true ) + elsif !file[:success] && result[1] + assert( false, 'ticket should not be created' ) + else + assert( false, 'UNKNOWN!' ) + end + } + end +end \ No newline at end of file