From 9301d03b37826d6aeddc5267e6aa03b0ca225dbf Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 3 May 2016 13:03:10 +0200 Subject: [PATCH] Only send notifications if not bulk mail has initiated. --- app/models/channel/email_parser.rb | 3 +- app/models/ticket.rb | 44 ++++++- app/models/transaction/trigger.rb | 2 +- test/fixtures/ticket_trigger/mail1.box | 17 +++ test/fixtures/ticket_trigger/mail2.box | 18 +++ test/unit/ticket_trigger_test.rb | 166 +++++++++++++++++++++++++ 6 files changed, 245 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/ticket_trigger/mail1.box create mode 100644 test/fixtures/ticket_trigger/mail2.box diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb index 3ed371242..9bc86c2fb 100644 --- a/app/models/channel/email_parser.rb +++ b/app/models/channel/email_parser.rb @@ -9,7 +9,8 @@ class Channel::EmailParser =begin - mail = parse(msg_as_string) + parser = Channel::EmailParser.new + mail = parser.parse(msg_as_string) mail = { from: 'Some Name ', diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 22b0053bb..1caf3e1c6 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -635,11 +635,11 @@ condition example perform changes on ticket - ticket.perform_changes({}, 'trigger') + ticket.perform_changes({}, 'trigger', item) =end - def perform_changes(perform, log) + def perform_changes(perform, log, item = nil) logger.debug "Perform #{log} #{perform.inspect} on Ticket.find(#{id})" changed = false perform.each do |key, value| @@ -662,8 +662,14 @@ perform changes on ticket recipient_string = '' recipient_already = {} recipients.each {|user| + + # send notifications only to email adresses next if !user.email next if user.email !~ /@/ + + # do not sent notifications to this recipients + next if user.email =~ /(mailer-daemon|postmaster|abuse|root)@.+?\..+?/i + email = user.email.downcase.strip next if recipient_already[email] recipient_already[email] = true @@ -679,6 +685,39 @@ perform changes on ticket next if !email_address next if !email_address.channel_id + # check if notification should be send because of customer emails + if item && item[:article_id] + article = Ticket::Article.lookup(id: item[:article_id]) + if article + type = Ticket::Article::Type.lookup(id: article.type_id) + sender = Ticket::Article::Sender.lookup(id: article.sender_id) + if sender && sender.name == 'Customer' && type && type.name == 'email' + + # get attachment + list = Store.list( + object: 'Ticket::Article::Mail', + o_id: article.id, + ) + if list && list[0] + file = Store.find(list[0].id) + if file + content = file.content + if content + parser = Channel::EmailParser.new + mail = parser.parse(content) + + # check headers + next if mail['x-loop'.to_sym] =~ /yes/i + next if mail['precedence'.to_sym] =~ /bulk/i + next if mail['auto-submitted'.to_sym] =~ /auto-generated/i + next if mail['x-auto-response-suppress'.to_sym] =~ /yes/i + end + end + end + end + end + end + objects = { ticket: self, article: articles.last, @@ -703,7 +742,6 @@ perform changes on ticket ) Ticket::Article.create( ticket_id: id, - #from: 'some_sender@example.com', to: recipient_string, subject: subject, content_type: 'text/html', diff --git a/app/models/transaction/trigger.rb b/app/models/transaction/trigger.rb index 1824097b8..d2dfb9f6d 100644 --- a/app/models/transaction/trigger.rb +++ b/app/models/transaction/trigger.rb @@ -70,7 +70,7 @@ class Transaction::Trigger next if !match end - ticket.perform_changes(trigger.perform, 'trigger') + ticket.perform_changes(trigger.perform, 'trigger', @item) } end diff --git a/test/fixtures/ticket_trigger/mail1.box b/test/fixtures/ticket_trigger/mail1.box new file mode 100644 index 000000000..338639a84 --- /dev/null +++ b/test/fixtures/ticket_trigger/mail1.box @@ -0,0 +1,17 @@ +From: Martin Edenhofer +To: me@example.com +Content-Type: text/plain; + charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable +Subject: =?iso-8859-1?Q?aa=E4=F6=FC=DFad_asd?= +X-Universally-Unique-Identifier: d12c15d2-e6d6-4ccd-86c7-abc2c3d0a2a2 +Date: Fri, 4 May 2012 14:01:03 +0200 +Message-Id: +Mime-Version: 1.0 (Apple Message framework v1257) + +=E4=F6=FC=DF ad asd + +-Martin + +-- +Old programmers never die. They just branch to a new address. diff --git a/test/fixtures/ticket_trigger/mail2.box b/test/fixtures/ticket_trigger/mail2.box new file mode 100644 index 000000000..12ac6f392 --- /dev/null +++ b/test/fixtures/ticket_trigger/mail2.box @@ -0,0 +1,18 @@ +From: Martin Edenhofer +To: me@example.com +Content-Type: text/plain; + charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable +Subject: =?iso-8859-1?Q?aa=E4=F6=FC=DFad_asd?= +X-Universally-Unique-Identifier: d12c15d2-e6d6-4ccd-86c7-abc2c3d0a2a2 +Date: Fri, 4 May 2012 14:01:03 +0200 +Precedence: bulk +Message-Id: +Mime-Version: 1.0 (Apple Message framework v1257) + +=E4=F6=FC=DF ad asd + +-Martin + +-- +Old programmers never die. They just branch to a new address. diff --git a/test/unit/ticket_trigger_test.rb b/test/unit/ticket_trigger_test.rb index cb55bc8ec..3047073a6 100644 --- a/test/unit/ticket_trigger_test.rb +++ b/test/unit/ticket_trigger_test.rb @@ -334,4 +334,170 @@ class TicketTriggerTest < ActiveSupport::TestCase Trigger.destroy_all end + test '3 auto replys' do + roles = Role.where(name: 'Customer') + customer1 = User.create_or_update( + login: 'postmaster@example.com', + firstname: 'Notification', + lastname: 'Customer1', + email: 'postmaster@example.com', + password: 'customerpw', + active: true, + roles: roles, + updated_at: '2015-02-05 16:37:00', + updated_by_id: 1, + created_by_id: 1, + ) + customer2 = User.create_or_update( + login: 'ticket-auto-reply-customer2@example.com', + firstname: 'Notification', + lastname: 'Customer2', + email: 'ticket-auto-reply-customer2@example.com', + password: 'customerpw', + active: true, + organization_id: nil, + roles: roles, + updated_at: '2015-02-05 16:37:00', + updated_by_id: 1, + created_by_id: 1, + ) + + trigger1 = Trigger.create_or_update( + name: 'auto reply - new ticket', + condition: { + 'ticket.action' => { + 'operator' => 'is', + 'value' => 'create', + }, + }, + perform: { + 'notification.email' => { + 'body' => 'some text
#{ticket.customer.lastname}
#{ticket.title}', + 'recipient' => 'ticket_customer', + 'subject' => 'Thanks for your inquiry (#{ticket.title})!', + }, + }, + disable_notification: true, + active: true, + created_by_id: 1, + updated_by_id: 1, + ) + + trigger2 = Trigger.create_or_update( + name: 'not matching', + condition: { + 'ticket.action' => { + 'operator' => 'is', + 'value' => 'create', + }, + 'ticket.state_id' => { + 'operator' => 'is', + 'value' => Ticket::State.lookup(name: 'closed').id.to_s, + } + }, + perform: { + 'notification.email' => { + 'body' => '2some text
#{ticket.customer.lastname}
#{ticket.title}', + 'recipient' => 'ticket_customer', + 'subject' => '2Thanks for your inquiry (#{ticket.title})!', + }, + }, + disable_notification: true, + active: true, + created_by_id: 1, + updated_by_id: 1, + ) + + # ticket #1 + ticket1 = Ticket.create( + title: 'test auto reply 1', + group: Group.lookup(name: 'Users'), + customer_id: customer1.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: 1, + created_by_id: 1, + ) + assert(ticket1, 'ticket1 created') + + assert_equal('test auto reply 1', ticket1.title, 'ticket1.title verify') + assert_equal('Users', ticket1.group.name, 'ticket1.group verify') + assert_equal('new', ticket1.state.name, 'ticket1.state verify') + assert_equal(0, ticket1.articles.count, 'ticket1.articles verify') + + Observer::Transaction.commit + + ticket1 = Ticket.lookup(id: ticket1.id) + assert_equal('test auto reply 1', ticket1.title, 'ticket1.title verify') + assert_equal('Users', ticket1.group.name, 'ticket1.group verify') + assert_equal('new', ticket1.state.name, 'ticket1.state verify') + assert_equal(0, ticket1.articles.count, 'ticket1.articles verify') + + ticket1.priority = Ticket::Priority.lookup(name: '2 normal') + ticket1.save + + Observer::Transaction.commit + + assert_equal('test auto reply 1', ticket1.title, 'ticket1.title verify') + assert_equal('Users', ticket1.group.name, 'ticket1.group verify') + assert_equal('new', ticket1.state.name, 'ticket1.state verify') + assert_equal('2 normal', ticket1.priority.name, 'ticket1.priority verify') + assert_equal(0, ticket1.articles.count, 'ticket1.articles verify') + + # ticket #2 + ticket2 = Ticket.create( + title: 'test auto reply 2', + group: Group.lookup(name: 'Users'), + customer_id: customer2.id, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: 1, + created_by_id: 1, + ) + assert(ticket2, 'ticket2 created') + + assert_equal('test auto reply 2', ticket2.title, 'ticket2.title verify') + assert_equal('Users', ticket2.group.name, 'ticket2.group verify') + assert_equal('new', ticket2.state.name, 'ticket2.state verify') + assert_equal(0, ticket2.articles.count, 'ticket2.articles verify') + + Observer::Transaction.commit + + ticket2 = Ticket.lookup(id: ticket2.id) + assert_equal('test auto reply 2', ticket2.title, 'ticket2.title verify') + assert_equal('Users', ticket2.group.name, 'ticket2.group verify') + assert_equal('new', ticket2.state.name, 'ticket2.state verify') + assert_equal(1, ticket2.articles.count, 'ticket2.articles verify') + article1 = ticket2.articles.last + assert_match('Thanks for your inquiry (test auto reply 2)!', article1.subject) + assert_equal('text/html', article1.content_type) + + ticket2.priority = Ticket::Priority.lookup(name: '2 normal') + ticket2.save + + Observer::Transaction.commit + + assert_equal('test auto reply 2', ticket2.title, 'ticket2.title verify') + assert_equal('Users', ticket2.group.name, 'ticket2.group verify') + assert_equal('new', ticket2.state.name, 'ticket2.state verify') + assert_equal('2 normal', ticket2.priority.name, 'ticket2.priority verify') + assert_equal(1, ticket2.articles.count, 'ticket2.articles verify') + + # process mail without Precedence header + content = IO.binread('test/fixtures/ticket_trigger/mail1.box') + ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, content) + + assert_equal('new', ticket_p.state.name) + assert_equal(2, ticket_p.articles.count) + + # process mail with Precedence header (no auto response) + content = IO.binread('test/fixtures/ticket_trigger/mail2.box') + ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, content) + + assert_equal('new', ticket_p.state.name) + assert_equal(1, ticket_p.articles.count) + + Trigger.destroy_all + end + end