From b19ac485bfe89723689f9808a993502b91963c8e Mon Sep 17 00:00:00 2001 From: Ryan Lue Date: Mon, 11 Mar 2019 08:28:18 +0100 Subject: [PATCH] Refactoring: Migrate email-process unit sub-tests to RSpec. --- spec/factories/ticket.rb | 9 +- spec/lib/mail/encodings_spec.rb | 18 ++ spec/models/channel/email_parser_spec.rb | 239 ++++++++++------ spec/models/ticket_spec.rb | 12 + spec/models/trigger_spec.rb | 113 +++++++- .../mail/mail078.box} | 58 +--- ...s_bounce_delivery_permanent_failed_test.rb | 219 --------------- test/unit/email_process_bounce_follow_test.rb | 256 ------------------ 8 files changed, 311 insertions(+), 613 deletions(-) create mode 100644 spec/lib/mail/encodings_spec.rb rename test/{unit/email_process_bounce_delivery_temporary_failed_test.rb => data/mail/mail078.box} (50%) delete mode 100644 test/unit/email_process_bounce_delivery_permanent_failed_test.rb delete mode 100644 test/unit/email_process_bounce_follow_test.rb diff --git a/spec/factories/ticket.rb b/spec/factories/ticket.rb index 7c73f92fe..7511eec3f 100644 --- a/spec/factories/ticket.rb +++ b/spec/factories/ticket.rb @@ -1,10 +1,15 @@ FactoryBot.define do factory :ticket do + transient do + state_name 'new' + priority_name '2 normal' + end + title { 'Test Ticket' } group customer - state { Ticket::State.lookup(name: 'new') } - priority { Ticket::Priority.lookup(name: '2 normal') } + state { Ticket::State.lookup(name: state_name) } + priority { Ticket::Priority.lookup(name: priority_name) } updated_by_id { 1 } created_by_id { 1 } diff --git a/spec/lib/mail/encodings_spec.rb b/spec/lib/mail/encodings_spec.rb new file mode 100644 index 000000000..d498af65e --- /dev/null +++ b/spec/lib/mail/encodings_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe Mail::Encodings do + # Regression test for https://github.com/zammad/zammad/issues/2456 + # (Mail lib was originally broken, so we patched it. + # Then, upstream was fixed, whereas our patch broke.) + describe '.value_decode' do + it 'decodes us-ascii encoded strings' do + expect(Mail::Encodings.value_decode('=?us-ascii?Q?Test?=')) + .to eql('Test') + end + + it 'decodes utf-8 encoded strings' do + expect(Mail::Encodings.value_decode('=?UTF-8?Q? Personal=C3=A4nderung?=')) + .to eql(' Personaländerung') + end + end +end diff --git a/spec/models/channel/email_parser_spec.rb b/spec/models/channel/email_parser_spec.rb index 8d771734e..3ebe49d18 100644 --- a/spec/models/channel/email_parser_spec.rb +++ b/spec/models/channel/email_parser_spec.rb @@ -1,50 +1,68 @@ require 'rails_helper' RSpec.describe Channel::EmailParser, type: :model do - let(:subject) { described_class.new } - let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail001.box') } - let(:raw_mail) { File.read(mail_file) } + describe '#parse' do + # regression test for issue 2390 - Add a postmaster filter to not show emails with potential issue + describe 'handling HTML links in message content' do + context 'with under 5,000 links' do + it 'parses message content as normal' do + expect(described_class.new.parse(<<~RAW)[:body]).to start_with(' + #{Array.new(10) { 'Dummy Link' }.join(' ')} + + RAW end end - context 'with a large number (42+) of unrecognized email addresses' do - let(:raw_mail) { <<~RAW } - From: #{Faker::Internet.unique.email} - To: #{Array.new(22) { Faker::Internet.unique.email }.join(', ')} - Cc: #{Array.new(22) { Faker::Internet.unique.email }.join(', ')} - Subject: test max sender identify + context 'with 5,000+ links' do + it 'replaces message content with error message' do + expect(described_class.new.parse(<<~RAW)).to include('body' => Channel::EmailParser::EXCESSIVE_LINKS_MSG) + From: nicole.braun@zammad.com + Content-Type: text/html - Some Text - RAW + + #{Array.new(5001) { 'Dummy Link' }.join(' ')} + + RAW + end + end + end + end - it 'never creates more than 41 users per email' do - expect { Channel::EmailParser.new.process({}, raw_mail) } - .to change { User.count }.by(41) + describe '#process' do + let(:raw_mail) { File.read(mail_file) } + + describe 'auto-creating new users' do + context 'with one unrecognized email address' do + it 'creates one new user' do + expect { Channel::EmailParser.new.process({}, <<~RAW) }.to change { User.count }.by(1) + From: #{Faker::Internet.unique.email} + RAW + end + end + + context 'with a large number of unrecognized recipient addresses' do + it 'never creates more than 40 users' do + expect { Channel::EmailParser.new.process({}, <<~RAW) }.to change { User.count }.by(40) + From: nicole.braun@zammad.org + To: #{Array.new(20) { Faker::Internet.unique.email }.join(', ')} + Cc: #{Array.new(21) { Faker::Internet.unique.email }.join(', ')} + RAW end end end - context 'for associating emails to tickets' do + describe 'associating emails to tickets' do + let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail001.box') } + let(:ticket_ref) { Setting.get('ticket_hook') + Setting.get('ticket_hook_divider') + ticket.number } + let(:ticket) { create(:ticket) } + context 'when email subject contains ticket reference' do + let(:raw_mail) { File.read(mail_file).sub(/(?<=^Subject: ).*$/, ticket_ref) } + it 'adds message to ticket' do expect { described_class.new.process({}, raw_mail) } .to change { ticket.articles.length } @@ -56,7 +74,7 @@ RSpec.describe Channel::EmailParser, type: :model do context 'when body contains ticket reference' do context 'in visible text' do - let(:raw_mail) { File.read(mail_file).sub(/Hallo =\nMartin,(?=)/, test_string) } + let(:raw_mail) { File.read(mail_file).sub(/Hallo =\nMartin,(?=)/, ticket_ref) } it 'adds message to ticket' do expect { described_class.new.process({}, raw_mail) } @@ -65,7 +83,7 @@ RSpec.describe Channel::EmailParser, type: :model do end context 'as part of a larger word' do - let(:raw_mail) { File.read(mail_file).sub(/(?<=Hallo) =\n(?=Martin,)/, test_string) } + let(:raw_mail) { File.read(mail_file).sub(/(?<=Hallo) =\n(?=Martin,)/, ticket_ref) } it 'creates a separate ticket' do expect { described_class.new.process({}, raw_mail) } @@ -74,7 +92,7 @@ RSpec.describe Channel::EmailParser, type: :model do end context 'in html attributes' do - let(:raw_mail) { File.read(mail_file).sub(%r{}m, %(
)) } + let(:raw_mail) { File.read(mail_file).sub(%r{
}m, %(
)) } it 'creates a separate ticket' do expect { described_class.new.process({}, raw_mail) } @@ -85,7 +103,7 @@ RSpec.describe Channel::EmailParser, type: :model do end end - context 'for sender/recipient address formatting' do + describe 'sender/recipient address formatting' do # see https://github.com/zammad/zammad/issues/2198 context 'when sender address contains spaces (#2198)' do let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail071.box') } @@ -93,7 +111,7 @@ RSpec.describe Channel::EmailParser, type: :model do it 'removes them before creating a new user' do expect { described_class.new.process({}, raw_mail) } - .to change { User.where(email: sender_email).count }.to(1) + .to change { User.exists?(email: sender_email) } end it 'marks new user email as invalid' do @@ -113,7 +131,7 @@ RSpec.describe Channel::EmailParser, type: :model do it 'removes them before creating a new user' do expect { described_class.new.process({}, raw_mail) } - .to change { User.where(email: sender_email).count }.to(1) + .to change { User.exists?(email: sender_email) } end it 'marks new user email as invalid' do @@ -127,7 +145,7 @@ RSpec.describe Channel::EmailParser, type: :model do end end - context 'for charset handling' do + describe 'charset handling' do # see https://github.com/zammad/zammad/issues/2224 context 'when header specifies Windows-1258 charset (#2224)' do let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail072.box') } @@ -139,46 +157,10 @@ RSpec.describe Channel::EmailParser, type: :model do end end - context 'mail with links' do - - def mock_mail(number_of_links) - link = '
Dummy Link ' - - mail = Mail.new - mail.html_part = "#{link * number_of_links}" - mail - end - - let(:mail_10) { mock_mail(10).to_s } - let(:mail_5k) { mock_mail(5001).to_s } - - # regression test for issue 2390 - Add a postmaster filter to not show emails with potential issue - it '(>5k links) are replaced by a warning message' do - expect( described_class.new.parse(mail_5k)[:body] ) - .to eql( Channel::EmailParser::EXCESSIVE_LINKS_MSG ) - end - - it '(10 links) are not touched' do - expect( described_class.new.parse(mail_10)[:body] ) - .to start_with( ' true) end end end + + context 'for “delivery failed” notifications (a.k.a. bounce messages)' do + let(:ticket) { article.ticket } + let(:article) { create(:ticket_article, sender_name: 'Agent', message_id: message_id) } + let(:message_id) { raw_mail[/(?<=^(References|Message-ID): )\S*/] } + + context 'with future retries (delayed)' do + let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail078.box') } + + context 'on a closed ticket' do + before { ticket.update(state: Ticket::State.find_by(name: 'closed')) } + + it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do + article = Channel::EmailParser.new.process({}, raw_mail).second + expect(article.preferences) + .to include('send-auto-response' => false, 'is-auto-response' => true) + end + + it 'returns a Mail object with an x-zammad-out-of-office header' do + output_mail = Channel::EmailParser.new.process({}, raw_mail).last + expect(output_mail).to include('x-zammad-out-of-office': true) + end + + it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .to change { ticket.articles.count }.by(1) + end + + it 'does not re-open the ticket' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .not_to change { ticket.reload.state.name }.from('closed') + end + end + end + + context 'with no future retries (undeliverable): sample input 1' do + let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box') } + + context 'for original message sent by Agent' do + it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do + article = Channel::EmailParser.new.process({}, raw_mail).second + expect(article.preferences) + .to include('send-auto-response' => false, 'is-auto-response' => true) + end + + it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .to change { ticket.articles.count }.by(1) + end + + it 'does not alter the ticket state' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .not_to change { ticket.reload.state.name }.from('open') + end + end + + context 'for original message sent by Customer' do + let(:article) { create(:ticket_article, sender_name: 'Customer', message_id: message_id) } + + it 'sets #preferences on resulting ticket to { "send-auto-responses" => false, "is-auto-reponse" => true }' do + article = Channel::EmailParser.new.process({}, raw_mail).second + expect(article.preferences) + .to include('send-auto-response' => false, 'is-auto-response' => true) + end + + it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .to change { ticket.articles.count }.by(1) + end + + it 'does not alter the ticket state' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .not_to change { ticket.reload.state.name }.from('new') + end + end + end + + context 'with no future retries (undeliverable): sample input 2' do + let(:mail_file) { Rails.root.join('test', 'data', 'mail', 'mail055.box') } + + it 'finds the article referenced in the bounce message headers, then adds the bounce message to its ticket' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .to change { ticket.articles.count }.by(1) + end + + it 'does not alter the ticket state' do + expect { Channel::EmailParser.new.process({}, raw_mail) } + .not_to change { ticket.reload.state.name }.from('open') + end + end + end end end diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index 17f3ec62f..e4f436c97 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -256,6 +256,18 @@ RSpec.describe Ticket, type: :model do end describe 'Attributes:' do + describe '#state' do + context 'for brand new tickets' do + context 'when a non-customer article is added' do + let(:article) { create(:ticket_article, ticket: ticket, sender_name: 'Agent') } + + it 'switches to "open"' do + expect { article }.to change { ticket.state.name }.from('new').to('open') + end + end + end + end + describe '#pending_time' do subject(:ticket) { create(:ticket, pending_time: Time.zone.now + 2.days) } diff --git a/spec/models/trigger_spec.rb b/spec/models/trigger_spec.rb index 4bd451db7..b8c959394 100644 --- a/spec/models/trigger_spec.rb +++ b/spec/models/trigger_spec.rb @@ -4,10 +4,10 @@ require 'models/application_model_examples' RSpec.describe Trigger, type: :model do it_behaves_like 'ApplicationModel', can_assets: { selectors: %i[condition perform] } - subject(:trigger) { create(:trigger) } + before { Trigger.destroy_all } # Default DB state includes three sample triggers + subject!(:trigger) { create(:trigger, condition: condition, perform: perform) } describe '#assets (for supplying model data to front-end framework)' do - subject(:trigger) { create(:trigger, condition: condition, perform: perform) } let(:condition) { { 'ticket.state_id' => { operator: 'is', value: 1 } } } let(:perform) { { 'ticket.priority_id' => { value: 1 } } } @@ -17,4 +17,113 @@ RSpec.describe Trigger, type: :model do .and include(Ticket::Priority.first.assets({})) end end + + describe 'Send-email triggers' do + let(:perform) do + { + 'notification.email' => { + 'recipient' => 'ticket_customer', + 'subject' => 'foo', + 'body' => 'bar' + } + } + end + + context 'for condition "ticket created"' do + let(:condition) do + { 'ticket.action' => { 'operator' => 'is', 'value' => 'create' } } + end + + context 'when ticket is created directly' do + let!(:ticket) { create(:ticket) } + + it 'fires (without altering ticket state)' do + expect { Observer::Transaction.commit } + .to change { Ticket::Article.count }.by(1) + .and not_change { ticket.reload.state.name }.from('new') + end + end + + context 'when ticket is created via Channel::EmailParser.process' do + before { create(:email_address, groups: [Group.first]) } + let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail001.box')) } + + it 'fires (without altering ticket state)' do + expect { Channel::EmailParser.new.process({}, raw_email) } + .to change { Ticket.count }.by(1) + .and change { Ticket::Article.count }.by(2) + + expect(Ticket.last.state.name).to eq('new') + end + end + end + + context 'for condition "ticket updated"' do + let(:condition) do + { 'ticket.action' => { 'operator' => 'is', 'value' => 'update' } } + end + + let!(:ticket) { create(:ticket).tap { Observer::Transaction.commit } } + + context 'when new article is created directly' do + context 'with empty #preferences hash' do + let!(:article) { create(:ticket_article, ticket: ticket) } + + it 'fires (without altering ticket state)' do + expect { Observer::Transaction.commit } + .to change { ticket.reload.articles.count }.by(1) + .and not_change { ticket.reload.state.name }.from('new') + end + end + + context 'with #preferences { "send-auto-response" => false }' do + let!(:article) do + create(:ticket_article, + ticket: ticket, + preferences: { 'send-auto-response' => false }) + end + + it 'does not fire' do + expect { Observer::Transaction.commit } + .not_to change { ticket.reload.articles.count } + end + end + end + + context 'when new article is created via Channel::EmailParser.process' do + context 'with a regular message' do + let!(:article) do + create(:ticket_article, + ticket: ticket, + message_id: raw_email[/(?<=^References: )\S*/], + subject: raw_email[/(?<=^Subject: Re: ).*$/]) + end + + let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail005.box')) } + + it 'fires (without altering ticket state)' do + expect { Channel::EmailParser.new.process({}, raw_email) } + .to not_change { Ticket.count } + .and change { ticket.reload.articles.count }.by(2) + .and not_change { ticket.reload.state.name }.from('new') + end + end + + context 'with delivery-failed "bounce message"' do + let!(:article) do + create(:ticket_article, + ticket: ticket, + message_id: raw_email[/(?<=^Message-ID: )\S*/]) + end + + let(:raw_email) { File.read(Rails.root.join('test', 'data', 'mail', 'mail055.box')) } + + it 'does not fire' do + expect { Channel::EmailParser.new.process({}, raw_email) } + .to change { ticket.reload.articles.count }.by(1) + end + end + end + end + end end diff --git a/test/unit/email_process_bounce_delivery_temporary_failed_test.rb b/test/data/mail/mail078.box similarity index 50% rename from test/unit/email_process_bounce_delivery_temporary_failed_test.rb rename to test/data/mail/mail078.box index 11d5359ae..36869f995 100644 --- a/test/unit/email_process_bounce_delivery_temporary_failed_test.rb +++ b/test/data/mail/mail078.box @@ -1,52 +1,21 @@ -require 'test_helper' - -class EmailProcessBounceDeliveryTemporaryFailed < ActiveSupport::TestCase - - test 'process with temp faild bounce email' do - - ticket = Ticket.create!( - title: 'temp failed check - ms', - group: Group.lookup(name: 'Users'), - customer_id: 2, - state: Ticket::State.lookup(name: 'closed'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create!( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'temp failed check', - message_id: '<20150830145601.30.608881@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.lookup(name: 'Agent'), - type: Ticket::Article::Type.lookup(name: 'email'), - updated_by_id: 1, - created_by_id: 1, - ) - travel 1.second - - # temp faild bounce email - email_raw_string = "Content-Type: multipart/report; boundary=\"000000000000ca4a1a057417a375\"; report-type=delivery-status +Content-Type: multipart/report; boundary="000000000000ca4a1a057417a375"; report-type=delivery-status From: Mail Delivery Subsystem To: service@example.de Auto-Submitted: auto-replied Subject: Delivery Status Notification (Delay) -References: #{article.message_id} -In-Reply-To: #{article.message_id} +References: <20150830145601.30.608881@example.com> +In-Reply-To: <20150830145601.30.608881@example.com> Message-ID: <5b7e8af4.1c69fb81.3ac1b.e296.GMRIR@mx.example.com> Date: Thu, 23 Aug 2018 03:22:44 -0700 (PDT) --000000000000ca4a1a057417a375 -Content-Type: multipart/related; boundary=\"000000000000ca53d4057417a37c\" +Content-Type: multipart/related; boundary="000000000000ca53d4057417a37c" --000000000000ca53d4057417a37c -Content-Type: multipart/alternative; boundary=\"000000000000ca53de057417a37d\" +Content-Type: multipart/alternative; boundary="000000000000ca53de057417a37d" --000000000000ca53de057417a37d -Content-Type: text/plain; charset=\"UTF-8\" +Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable @@ -72,7 +41,7 @@ Content-Type: message/delivery-status Reporting-MTA: dns; example.com Received-From-MTA: dns; service@example.de Arrival-Date: Wed, 22 Aug 2018 02:00:03 -0700 (PDT) -X-Original-Message-ID: #{article.message_id} +X-Original-Message-ID: <20150830145601.30.608881@example.com> Final-Recipient: rfc822; bob.smith@example.de Action: delayed @@ -89,21 +58,10 @@ Content-Type: message/rfc822 Date: Wed, 22 Aug 2018 11:00:03 +0200 From: example Helpdesk To: bob.smith@example.de -Message-ID: #{article.message_id} +Message-ID: <20150830145601.30.608881@example.com> Subject: Ihre Anfrage () [Ticket#638810] Content-Type: text/plain; charset=UTF-8 ABC --000000000000ca4a1a057417a375-- -" - - ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(true, mail['x-zammad-out-of-office'.to_sym]) - ticket = Ticket.find(ticket.id) - assert_equal(ticket.id, ticket_p.id) - assert_equal('closed', ticket.state.name) - - end - -end diff --git a/test/unit/email_process_bounce_delivery_permanent_failed_test.rb b/test/unit/email_process_bounce_delivery_permanent_failed_test.rb deleted file mode 100644 index cfe11907d..000000000 --- a/test/unit/email_process_bounce_delivery_permanent_failed_test.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'test_helper' - -class EmailProcessBounceDeliveryPermanentFailedTest < ActiveSupport::TestCase - - test 'process with bounce trigger email loop check - article based blocker' do - roles = Role.where(name: %w[Customer]) - customer1 = User.create_or_update( - login: 'ticket-bounce-trigger1@example.com', - firstname: 'Notification', - lastname: 'Customer1', - email: 'ticket-bounce-trigger1@example.com', - active: true, - roles: roles, - preferences: {}, - updated_by_id: 1, - created_by_id: 1, - ) - - 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}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your inquiry (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - Trigger.create_or_update( - name: 'auto reply followup', - condition: { - 'ticket.action' => { - 'operator' => 'is', - 'value' => 'update', - }, - }, - perform: { - 'notification.email' => { - 'body' => 'some text
#{ticket.customer.lastname}
#{ticket.title}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your follow up (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - - ticket = Ticket.create!( - title: 'bounce check', - group: Group.lookup(name: 'Users'), - customer: customer1, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create!( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check', - message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal('new', ticket.state.name) - assert_equal(2, ticket.articles.count) - - article = Ticket::Article.create!( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: customer1.email, - subject: 'bounce check 2', - message_id: '<20150830145601.30.608881@edenhofer.zammad.com>', - body: 'some message bounce check 2', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal(4, ticket.articles.count) - - travel 1.second - email_raw_string = File.read(Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box')) - ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(ticket.id, ticket_p.id) - assert_equal('open', ticket_p.state.name) - assert_equal(5, ticket_p.articles.count) - travel_back - ticket.destroy - end - - test 'process with bounce trigger email loop check - bounce based blocker' do - roles = Role.where(name: %w[Customer]) - customer2 = User.create_or_update( - login: 'ticket-bounce-trigger2@example.com', - firstname: 'Notification', - lastname: 'Customer2', - email: 'ticket-bounce-trigger2@example.com', - active: true, - roles: roles, - preferences: {}, - updated_by_id: 1, - created_by_id: 1, - ) - - 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}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your inquiry (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - Trigger.create_or_update( - name: 'auto reply followup', - condition: { - 'ticket.action' => { - 'operator' => 'is', - 'value' => 'update', - }, - }, - perform: { - 'notification.email' => { - 'body' => 'some text
#{ticket.customer.lastname}
#{ticket.title}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your follow up (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - - ticket = Ticket.create!( - title: 'bounce check', - group: Group.lookup(name: 'Users'), - customer: customer2, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create!( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check', - message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal('new', ticket.state.name) - assert_equal(2, ticket.articles.count) - - article = Ticket::Article.create!( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check 2', - message_id: '<20170526150141.232.13312@example.zammad.loc>', - body: 'some message bounce check 2', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal(4, ticket.articles.count) - - travel 1.second - email_raw_string = File.read(Rails.root.join('test', 'data', 'mail', 'mail055.box')) - ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(ticket.id, ticket_p.id) - assert_equal('open', ticket_p.state.name) - assert_equal(5, ticket_p.articles.count) - travel_back - ticket.destroy - end - -end diff --git a/test/unit/email_process_bounce_follow_test.rb b/test/unit/email_process_bounce_follow_test.rb deleted file mode 100644 index 76d21212c..000000000 --- a/test/unit/email_process_bounce_follow_test.rb +++ /dev/null @@ -1,256 +0,0 @@ -require 'test_helper' - -class EmailProcessBounceFollowUpTest < ActiveSupport::TestCase - - test 'process with bounce follow up check' do - - ticket = Ticket.create( - title: 'bounce check', - group: Group.lookup(name: 'Users'), - customer_id: 2, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check', - message_id: '<20150830145601.30.608881@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Customer').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - travel 1.second - email_file_path = Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box') - email_raw_string = File.read(email_file_path) - ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(ticket.id, ticket_p.id) - assert_equal('new', ticket_p.state.name) - travel_back - ticket.destroy - - end - - test 'process with bounce trigger email loop check - article based blocker' do - roles = Role.where(name: %w[Customer]) - customer1 = User.create_or_update( - login: 'ticket-bounce-trigger1@example.com', - firstname: 'Notification', - lastname: 'Customer1', - email: 'ticket-bounce-trigger1@example.com', - active: true, - roles: roles, - preferences: {}, - updated_by_id: 1, - created_by_id: 1, - ) - - 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}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your inquiry (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - Trigger.create_or_update( - name: 'auto reply followup', - condition: { - 'ticket.action' => { - 'operator' => 'is', - 'value' => 'update', - }, - }, - perform: { - 'notification.email' => { - 'body' => 'some text
#{ticket.customer.lastname}
#{ticket.title}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your follow up (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - - ticket = Ticket.create( - title: 'bounce check', - group: Group.lookup(name: 'Users'), - customer: customer1, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check', - message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal('new', ticket.state.name) - assert_equal(2, ticket.articles.count) - - article = Ticket::Article.create( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: customer1.email, - subject: 'bounce check 2', - message_id: '<20150830145601.30.608881@edenhofer.zammad.com>', - body: 'some message bounce check 2', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal(4, ticket.articles.count) - - travel 1.second - email_file_path = Rails.root.join('test', 'data', 'mail', 'mail033-undelivered-mail-returned-to-sender.box') - email_raw_string = File.read(email_file_path) - ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(ticket.id, ticket_p.id) - assert_equal('open', ticket_p.state.name) - assert_equal(5, ticket_p.articles.count) - travel_back - ticket.destroy - end - - test 'process with bounce trigger email loop check - bounce based blocker' do - roles = Role.where(name: %w[Customer]) - customer2 = User.create_or_update( - login: 'ticket-bounce-trigger2@example.com', - firstname: 'Notification', - lastname: 'Customer2', - email: 'ticket-bounce-trigger2@example.com', - active: true, - roles: roles, - preferences: {}, - updated_by_id: 1, - created_by_id: 1, - ) - - 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}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your inquiry (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - Trigger.create_or_update( - name: 'auto reply followup', - condition: { - 'ticket.action' => { - 'operator' => 'is', - 'value' => 'update', - }, - }, - perform: { - 'notification.email' => { - 'body' => 'some text
#{ticket.customer.lastname}
#{ticket.title}
#{article.body}', - 'recipient' => 'ticket_customer', - 'subject' => 'Thanks for your follow up (#{ticket.title})!', - }, - }, - disable_notification: true, - active: true, - created_by_id: 1, - updated_by_id: 1, - ) - - ticket = Ticket.create( - title: 'bounce check', - group: Group.lookup(name: 'Users'), - customer: customer2, - state: Ticket::State.lookup(name: 'new'), - priority: Ticket::Priority.lookup(name: '2 normal'), - updated_by_id: 1, - created_by_id: 1, - ) - article = Ticket::Article.create( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check', - message_id: '<20150830145601.30.6088xx@edenhofer.zammad.com>', - body: 'some message bounce check', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal('new', ticket.state.name) - assert_equal(2, ticket.articles.count) - - article = Ticket::Article.create( - ticket_id: ticket.id, - from: 'some_sender@example.com', - to: 'some_recipient@example.com', - subject: 'bounce check 2', - message_id: '<20170526150141.232.13312@example.zammad.loc>', - body: 'some message bounce check 2', - internal: false, - sender: Ticket::Article::Sender.where(name: 'Agent').first, - type: Ticket::Article::Type.where(name: 'email').first, - updated_by_id: 1, - created_by_id: 1, - ) - Observer::Transaction.commit - assert_equal(4, ticket.articles.count) - - travel 1.second - email_file_path = Rails.root.join('test', 'data', 'mail', 'mail055.box') - email_raw_string = File.read(email_file_path) - ticket_p, article_p, user_p = Channel::EmailParser.new.process({}, email_raw_string) - assert_equal(ticket.id, ticket_p.id) - assert_equal('open', ticket_p.state.name) - assert_equal(5, ticket_p.articles.count) - travel_back - ticket.destroy - end - -end