# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ require 'rails_helper' RSpec.describe SignatureDetection do describe '.find_signature' do context 'when given an array of hashes' do let(:messages) do raw_message_files.map do |f| { content: File.read(f), content_type: content_type } end end context 'with plain text messages in their :content keys (sample input 1)' do let(:content_type) { 'text/plain' } let(:raw_message_files) do [ Rails.root.join('test/data/email_signature_detection/client_a_1.txt'), Rails.root.join('test/data/email_signature_detection/client_a_2.txt'), Rails.root.join('test/data/email_signature_detection/client_a_3.txt') ] end it 'returns the first 5–10-line substring they share in common' do expect(described_class.find_signature(messages)).to eq(<<~SIG.chomp) Mit freundlichen Grüßen Bob Smith Berechtigungen und dez. Department ________________________________ Musik AG Berechtigungen und dez. Department (ITPBM) Kastanien 2 SIG end end context 'with plain text messages in their :content keys (sample input 2)' do let(:content_type) { 'text/plain' } let(:raw_message_files) do [ Rails.root.join('test/data/email_signature_detection/client_b_1.txt'), Rails.root.join('test/data/email_signature_detection/client_b_2.txt'), Rails.root.join('test/data/email_signature_detection/client_b_3.txt') ] end it 'returns the first 5–10-line substring they share in common' do expect(described_class.find_signature(messages)).to eq(<<~SIG.chomp) Freundliche Grüße Günter Lässig Lokale Daten Music GmbH Baustraße 123, 12345 Max City Telefon 0123 5432114 Telefax 0123 5432139 SIG end end context 'with HTML messages in their :content keys' do let(:content_type) { 'text/html' } let(:raw_message_files) do [ Rails.root.join('test/data/email_signature_detection/client_c_1.html'), Rails.root.join('test/data/email_signature_detection/client_c_2.html'), Rails.root.join('test/data/email_signature_detection/client_c_3.html') ] end it 'converts messages (via #html2text) then returns the first 5–10-line substring they share in common' do expect(described_class.find_signature(messages)).to eq(<<~SIG.chomp) ChristianSmith Technik Tel: +49 12 34 56 78 441 Fax: +49 12 34 56 78 499 Email: Christian.Smith@example.com Web: www.example.com ABC KFZ- und Flugzeug B.V. & Co. KG Hauptverwaltung SIG end end end context 'when input messages do not share 5-line common substrings' do let(:messages) do Array.new(2) { { content: <<~RAW, content_type: 'text/plain' } } Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut ut tincidunt nunc. Sed mattis aliquam tellus sit amet lacinia. Mauris fermentum dictum aliquet. Nam ex risus, gravida et ornare ut, mollis non sapien. RAW end it 'doesn’t break' do expect { described_class.find_signature(messages) }.not_to raise_error end end context 'when message contains exchange warning (#3571)' do let(:content_type) { 'text/html' } let(:messages) do [ { content: '
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

actual content

actual content 2

 

actual quote

actual quote

 

 

', content_type: 'text/html' }, { content: '
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

333 content

4452134123 content 2

 

123124123 quote

123141 144234

 

 

', content_type: 'text/html' }, { content: '
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

333 content

4452134123 content 2

 

9999 quote

999 144234

 

 

', content_type: 'text/html' }, ] end it 'does not detect the warning information as signature' do expect(described_class.find_signature(messages)).to be_nil end end end describe '.find_signature_line' do context 'when given a plain text message' do let(:content_type) { 'text/plain' } let(:content) { Rails.root.join('test/data/email_signature_detection/client_a_1.txt').read } context 'and a substring it contains' do let(:signature) { <<~SIG.chomp } Mit freundlichen Grüßen Bob Smith Berechtigungen und dez. Department ________________________________ Musik AG Berechtigungen und dez. Department (ITPBM) Kastanien 2 SIG it 'returns the line of the message where the signature begins' do expect(described_class.find_signature_line(signature, content, content_type)).to eq(10) end end end context 'when given an HTML message' do let(:content_type) { 'text/html' } let(:content) { Rails.root.join('test/data/email_signature_detection/example1.html').read } context 'and a substring it contains' do let(:signature) { <<~SIG.chomp } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Bob Smith ABC Organisation EXAMPLE IT-Service GmbH Dorten 5 F&E 12345 Da / Germany Phone: +49 (0) 1234 567 890 / +49 (0) 1234 567 891 Fax:     +49 (0) 1234 567 892 SIG it 'converts messages (via #html2text) then returns the line of the message where the signature begins' do expect(described_class.find_signature_line(signature, content, content_type)).to eq(11) end end end end describe '.rebuild_all_articles' do context 'when a user exists with a recorded signature' do let!(:customer) { create(:customer, preferences: { signature_detection: "\nbar" }) } context 'and multiple articles exist for that customer' do let!(:articles) do [create(:ticket_article, created_by_id: customer.id, body: "foo\nfoo\nbar"), create(:ticket_article, created_by_id: customer.id, body: "foo\nbar")] end it 'updates the signature-line data of all articles' do expect { described_class.rebuild_all_articles } .to change { articles.first.reload.preferences[:signature_detection] }.to(3) .and change { articles.second.reload.preferences[:signature_detection] }.to(2) end end end end end