Fixes #3022 - Detect ServiceNow follow-ups
This commit is contained in:
parent
3f453c31e9
commit
afa6b9984a
6 changed files with 178 additions and 0 deletions
60
app/models/channel/filter/service_now_check.rb
Normal file
60
app/models/channel/filter/service_now_check.rb
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
module Channel::Filter::ServiceNowCheck
|
||||||
|
|
||||||
|
# This filter will run pre and post
|
||||||
|
def self.run(_channel, mail, ticket = nil, _article = nil, _session_user = nil)
|
||||||
|
source_id = self.source_id(from: mail[:from], subject: mail[:subject])
|
||||||
|
return if source_id.blank?
|
||||||
|
|
||||||
|
# check if we can followup by existing service now relation
|
||||||
|
if ticket.blank?
|
||||||
|
sync_entry = ExternalSync.find_by(
|
||||||
|
source: 'ServiceNow',
|
||||||
|
source_id: source_id,
|
||||||
|
object: 'Ticket',
|
||||||
|
)
|
||||||
|
return if sync_entry.blank?
|
||||||
|
|
||||||
|
mail[ 'x-zammad-ticket-id'.to_sym ] = sync_entry.o_id
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
ExternalSync.create_with(source_id: source_id).find_or_create_by(source: 'ServiceNow', object: 'Ticket', o_id: ticket.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
This function returns the source id of the service now email if given.
|
||||||
|
|
||||||
|
source_id = Channel::Filter::ServiceNowCheck.source_id(
|
||||||
|
from: 'test@servicnow.com',
|
||||||
|
subject: 'Incident INC12345 --- test',
|
||||||
|
)
|
||||||
|
|
||||||
|
returns:
|
||||||
|
|
||||||
|
source_id = 'INC12345'
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.source_id(from: '', subject: '')
|
||||||
|
|
||||||
|
# check if data is sent by service now
|
||||||
|
begin
|
||||||
|
return if Mail::AddressList.new(from).addresses.none? do |line|
|
||||||
|
line.address.end_with?('@service-now.com')
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
Rails.logger.info "Unable to parse email address in '#{from}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
# check if we can find the service now relation
|
||||||
|
source_id = nil
|
||||||
|
if subject =~ /\s(INC\d+)\s/
|
||||||
|
source_id = $1
|
||||||
|
end
|
||||||
|
|
||||||
|
source_id
|
||||||
|
end
|
||||||
|
end
|
28
db/migrate/20200401000001_service_now_config.rb
Normal file
28
db/migrate/20200401000001_service_now_config.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
class ServiceNowConfig < ActiveRecord::Migration[4.2]
|
||||||
|
def up
|
||||||
|
|
||||||
|
# return if it's a new setup
|
||||||
|
return if !Setting.find_by(name: 'system_init_done')
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Defines postmaster filter.',
|
||||||
|
name: '5400_postmaster_filter_service_now_check',
|
||||||
|
area: 'Postmaster::PreFilter',
|
||||||
|
description: 'Defines postmaster filter to identify service now mails for correct follow-ups.',
|
||||||
|
options: {},
|
||||||
|
state: 'Channel::Filter::ServiceNowCheck',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Defines postmaster filter.',
|
||||||
|
name: '5401_postmaster_filter_service_now_check',
|
||||||
|
area: 'Postmaster::PostFilter',
|
||||||
|
description: 'Defines postmaster filter to identify service now mails for correct follow-ups.',
|
||||||
|
options: {},
|
||||||
|
state: 'Channel::Filter::ServiceNowCheck',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -3449,6 +3449,24 @@ Setting.create_if_not_exists(
|
||||||
state: 'Channel::Filter::Monit',
|
state: 'Channel::Filter::Monit',
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Defines postmaster filter.',
|
||||||
|
name: '5400_postmaster_filter_service_now_check',
|
||||||
|
area: 'Postmaster::PreFilter',
|
||||||
|
description: 'Defines postmaster filter to identify service now mails for correct follow-ups.',
|
||||||
|
options: {},
|
||||||
|
state: 'Channel::Filter::ServiceNowCheck',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Defines postmaster filter.',
|
||||||
|
name: '5401_postmaster_filter_service_now_check',
|
||||||
|
area: 'Postmaster::PostFilter',
|
||||||
|
description: 'Defines postmaster filter to identify service now mails for correct follow-ups.',
|
||||||
|
options: {},
|
||||||
|
state: 'Channel::Filter::ServiceNowCheck',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'Icinga integration',
|
title: 'Icinga integration',
|
||||||
name: 'icinga_integration',
|
name: 'icinga_integration',
|
||||||
|
|
|
@ -983,6 +983,34 @@ RSpec.describe Channel::EmailParser, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'ServiceNow handling' do
|
||||||
|
context 'when emails with service now reference are sent' do
|
||||||
|
let(:mail_file) { Rails.root.join('test/data/mail/mail089.box') }
|
||||||
|
let(:mail_file_answer) { Rails.root.join('test/data/mail/mail090.box') }
|
||||||
|
let(:raw_mail_answer) { File.read(mail_file_answer) }
|
||||||
|
|
||||||
|
it 'does create a ticket with external sync reference' do
|
||||||
|
expect { described_class.new.process({}, raw_mail) }
|
||||||
|
.to change(Ticket, :count).by(1)
|
||||||
|
.and change(Ticket::Article, :count).by(1)
|
||||||
|
.and change(ExternalSync, :count).by(1)
|
||||||
|
|
||||||
|
expect(ExternalSync.last.source).to eq('ServiceNow')
|
||||||
|
expect(ExternalSync.last.source_id).to eq('INC678439')
|
||||||
|
expect(ExternalSync.last.object).to eq('Ticket')
|
||||||
|
expect(ExternalSync.last.o_id).to eq(Ticket.last.id)
|
||||||
|
expect(Ticket.last.articles.last.subject).to eq('Incident INC678439 -- zugewiesen an EXT-XXXINIS')
|
||||||
|
|
||||||
|
expect { described_class.new.process({}, raw_mail_answer) }
|
||||||
|
.to change(Ticket, :count).by(0)
|
||||||
|
.and change(Ticket::Article, :count).by(1)
|
||||||
|
.and change(ExternalSync, :count).by(0)
|
||||||
|
|
||||||
|
expect(Ticket.last.articles.last.subject).to eq('Incident INC678439 -- Arbeitsnotizen beigefügt')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'XSS protection' do
|
describe 'XSS protection' do
|
||||||
let(:article) { described_class.new.process({}, raw_mail).second }
|
let(:article) { described_class.new.process({}, raw_mail).second }
|
||||||
|
|
||||||
|
|
22
test/data/mail/mail089.box
Normal file
22
test/data/mail/mail089.box
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
From: IT example <example@service-now.com>
|
||||||
|
To: support@example.com
|
||||||
|
Message-ID: <18659453.58107.1576665116411@app129169.gva3.service-now.com>
|
||||||
|
Subject: Incident INC678439 -- zugewiesen an EXT-XXXINIS
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="----=_Part_58105_29005161.1576665006397"
|
||||||
|
X-ServiceNow-Source: Notification-5555502c4ff4aa0096d7e6101310c734
|
||||||
|
X-ServiceNow-SysEmail-Version: 2
|
||||||
|
Precedence: bulk
|
||||||
|
Auto-Submitted: auto-generated
|
||||||
|
X-ServiceNow-Generated: true
|
||||||
|
|
||||||
|
------=_Part_58105_29005161.1576665006397
|
||||||
|
Content-Type: multipart/alternative;
|
||||||
|
boundary="----=_Part_58106_4969544.1576665006398"
|
||||||
|
|
||||||
|
------=_Part_58106_4969544.1576665006398
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
|
||||||
|
Incident content
|
22
test/data/mail/mail090.box
Normal file
22
test/data/mail/mail090.box
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
From: IT example <example@service-now.com>
|
||||||
|
To: support@example.com
|
||||||
|
Message-ID: <18659453.58107.1576665116411@app129169.gva3.service-now.com>
|
||||||
|
Subject: =?UTF-8?Q?Incident_INC678439_--_Arbeitsnotizen_beigef=C3=BCgt?=
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="----=_Part_58105_29005161.1576665006397"
|
||||||
|
X-ServiceNow-Source: Notification-5555502c4ff4aa0096d7e6101310c734
|
||||||
|
X-ServiceNow-SysEmail-Version: 2
|
||||||
|
Precedence: bulk
|
||||||
|
Auto-Submitted: auto-generated
|
||||||
|
X-ServiceNow-Generated: true
|
||||||
|
|
||||||
|
------=_Part_58105_29005161.1576665006397
|
||||||
|
Content-Type: multipart/alternative;
|
||||||
|
boundary="----=_Part_58106_4969544.1576665006398"
|
||||||
|
|
||||||
|
------=_Part_58106_4969544.1576665006398
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
|
||||||
|
Incident content
|
Loading…
Reference in a new issue