Browse Source

Maintenance: Port 'email_build' minitest to rspec.

Bola Ahmed Buari 2 years ago
parent
commit
006a573e35
2 changed files with 527 additions and 403 deletions
  1. 527 0
      spec/models/channel/email_build_spec.rb
  2. 0 403
      test/unit/email_build_test.rb

+ 527 - 0
spec/models/channel/email_build_spec.rb

@@ -0,0 +1,527 @@
+# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
+
+require 'rails_helper'
+
+RSpec.describe Channel::EmailBuild, type: :model do
+  describe '#build' do
+    let(:html_body) do
+      <<~MSG_HTML.chomp
+        <!DOCTYPE html>
+        <html>
+          <head>
+            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+          </head>
+          <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
+            <div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>
+          </body>
+        </html>
+      MSG_HTML
+    end
+
+    let(:plain_text_body) do
+      <<~MSG_TEXT.chomp
+        > Welcome!
+        >
+        > Thank you for installing Zammad. äöüß
+        >
+      MSG_TEXT
+    end
+    let(:parser)      { Channel::EmailParser.new }
+    let(:parsed_data) { parser.parse(mail.to_s) }
+
+    let(:html_part_attachment) do
+      parsed_data[:attachments]
+        .find { |attachment| attachment[:filename] == 'message.html' }
+    end
+
+    let(:file_attachment) do
+      parsed_data[:attachments]
+        .find { |attachment| attachment[:filename] == filename }
+    end
+
+    shared_examples 'adding the email html part as an attachment' do
+      it 'adds the html part as an attachment' do
+        expect(html_part_attachment).to be_a_kind_of Hash
+      end
+
+      it 'adds the html part as an attachment' do
+        expect(html_part_attachment).to include(
+          'filename'    => 'message.html',
+          'preferences' => include('content-alternative' => true, 'Charset' => 'UTF-8',
+                                   'Mime-Type' => 'text/html', 'original-format' => true)
+        )
+      end
+
+      it 'does not include content-id property in attachment preferences' do
+        expect(html_part_attachment).not_to include(
+          'preferences' => include('Content-ID')
+        )
+      end
+    end
+
+    shared_examples 'adding a text file as an attachment' do
+      it 'adds the text file as an attachment' do
+        expect(file_attachment).to include(
+          'filename'    => filename,
+          'preferences' => include('Charset' => 'UTF-8', 'Mime-Type' => mime_type,
+                                   'Content-Type' => "text/plain; charset=UTF-8; filename=#{filename}")
+        )
+      end
+
+      it 'does not include content* properties in attachment preferences' do
+        expect(file_attachment).not_to include(
+          'preferences' => include('Content-ID', 'content-alternative')
+        )
+      end
+    end
+
+    shared_examples 'adding a file as an attachment' do |file_type|
+      it "adds a #{file_type} as an attachment'" do
+        expect(file_attachment).to include(
+          'data'        => content, 'filename' => filename,
+          'preferences' => include('Charset' => 'UTF-8', 'Mime-Type' => mime_type,
+                                   'Content-Type' => preferences_content_type)
+        )
+      end
+
+      it 'does not include content* properties in attachment preferences' do
+        expect(file_attachment).not_to include(
+          'preferences' => include('content-alternative')
+        )
+      end
+    end
+
+    shared_examples 'not adding email content as attachment' do
+      it 'does not add email content as an attachment' do
+        expect(html_part_attachment).to be_nil
+      end
+    end
+
+    context 'with email only' do
+      let(:mail) do
+        described_class.build(
+          from:         'sender@example.com',
+          to:           'recipient@example.com',
+          body:         mail_body,
+          content_type: content_type
+        )
+      end
+
+      let(:expected_text) do
+        <<~MSG_TEXT.chomp
+          > Welcome!\r
+          >\r
+          > Thank you for installing Zammad. äöüß\r
+          >\r
+        MSG_TEXT
+      end
+
+      context 'when email contains only html' do
+        let(:mail_body) { html_body }
+        let(:content_type) { 'text/html' }
+
+        let(:expected_html) do
+          <<~MSG_HTML.chomp
+            <!DOCTYPE html>\r
+            <html>\r
+              <head>\r
+                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\r
+              </head>\r
+              <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">\r
+                <div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>\r
+              </body>\r
+            </html>
+          MSG_HTML
+        end
+
+        let(:expected_body) { '<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>' }
+
+        it 'builds a mail with a text part' do
+          expect(mail.text_part.body.to_s).to eq expected_text
+        end
+
+        it 'builds a mail with a html part' do
+          expect(mail.html_part.body.to_s).to eq expected_html
+        end
+
+        it 'builds a mail that is parsed correctly' do
+          expect(parsed_data).to include(body: expected_body, content_type: 'text/html')
+        end
+
+        it_behaves_like 'adding the email html part as an attachment'
+      end
+
+      context 'when email contains only plain text' do
+        let(:mail_body)    { plain_text_body }
+        let(:content_type) { 'text/plain' }
+
+        it 'builds a mail with a text part' do
+          expect(mail.body.to_s).to eq expected_text
+        end
+
+        it 'does not build a html part' do
+          expect(mail.html_part).to be_nil
+        end
+
+        it 'builds a mail that is parsed correctly' do
+          expect(parsed_data).to  include(body: plain_text_body, content_type: 'text/plain')
+        end
+
+        it 'does not have an attachment' do
+          expect(parsed_data[:attachments].first).to be_nil
+        end
+
+        it_behaves_like 'not adding email content as attachment'
+      end
+    end
+
+    context 'with email and attachment' do
+      let(:mail) do
+        described_class.build(
+          from:         'sender@example.com',
+          to:           'recipient@example.com',
+          body:         mail_body,
+          content_type: content_type,
+          attachments:  attachments
+        )
+      end
+
+      let(:filename)  { 'somename.txt' }
+      let(:mime_type) { 'text/plain' }
+      let(:content)   { 'Some text' }
+
+      let(:direct_attachment) do
+        [{
+          'Mime-Type' => mime_type,
+          :content    => content,
+          :filename   => filename
+        }]
+      end
+      let(:ticket) { create(:ticket, title: 'some article text attachment test', group: group) }
+      let(:group)  { Group.lookup(name: 'Users') }
+
+      let(:article) do
+        create(:ticket_article,
+               ticket: ticket,
+               body:   'some message article helper test1 <div><img style="width: 85.5px; height: 49.5px" src="cid:15.274327094.140938@zammad.example.com">asdasd<img src="cid:15.274327094.140939@zammad.example.com"><br>')
+      end
+
+      let(:store_attributes) do
+        {
+          object:      'Ticket::Article',
+          o_id:        article.id,
+          data:        content,
+          filename:    filename,
+          preferences: {
+            'Mime-Type' => mime_type
+          }
+        }
+      end
+
+      let(:store) { create(:store, **store_attributes) }
+
+      shared_context 'with attachment checks' do
+        context 'when attachment is a text file' do
+
+          it_behaves_like 'adding a text file as an attachment'
+        end
+
+        context 'when attachment is a image file' do
+          let(:filename)                 { 'somename.png' }
+          let(:mime_type)                { 'image/png' }
+          let(:preferences_content_type) { "#{mime_type}; filename=#{filename}" }
+          let(:content)                  { 'xxxxxxx' }
+
+          it_behaves_like 'adding a file as an attachment', 'image'
+        end
+
+        context 'when attachment is a calendar file' do
+          let(:filename)  { 'schedule.ics' }
+          let(:mime_type)                { 'text/calendar' }
+          let(:preferences_content_type) { "#{mime_type}; charset=UTF-8; filename=#{filename}" }
+          let(:content)                  { 'xxxxxxx' }
+
+          it_behaves_like 'adding a file as an attachment', 'calendar'
+        end
+
+      end
+
+      context 'with html email' do
+        let(:mail_body)    { html_body }
+        let(:content_type) { 'text/html' }
+
+        context 'with direct attachment' do
+          let(:attachments) { direct_attachment }
+
+          it 'has two attachments' do
+            expect(parsed_data[:attachments].size).to eq 2
+          end
+
+          it_behaves_like 'adding the email html part as an attachment'
+
+          include_context 'with attachment checks'
+        end
+
+        context 'with attachement from store' do
+          let(:attachments) { [ store  ] }
+          let(:filename)    { 'text_file.txt' }
+          let(:mime_type)   { 'text/plain' }
+
+          it 'has two attachments' do
+            expect(parsed_data[:attachments].size).to eq 2
+          end
+
+          it_behaves_like 'adding the email html part as an attachment'
+
+          include_context 'with attachment checks'
+        end
+      end
+
+      context 'with plain text email' do
+        let(:mail_body)    { plain_text_body }
+        let(:content_type) { 'text/plain' }
+
+        context 'with direct attachment' do
+          let(:attachments) { direct_attachment }
+          let(:filename)  { 'somename.txt' }
+          let(:mime_type) { 'text/plain' }
+
+          it 'has only one attachment' do
+            expect(parsed_data[:attachments].size).to eq 1
+          end
+
+          it_behaves_like 'not adding email content as attachment'
+
+          include_context 'with attachment checks'
+        end
+
+        context 'with attachement from store' do
+          let(:attachments) { [ store  ] }
+          let(:filename)  { 'text_file.txt' }
+          let(:mime_type) { 'text/plain' }
+          let(:mail_body) do
+            <<~MSG_TEXT.chomp
+              > Welcome!
+              >
+              > Email Content
+            MSG_TEXT
+          end
+          let(:content) { 'Text Content' }
+
+          it 'has only one attachment' do
+            expect(parsed_data[:attachments].size).to eq 1
+          end
+
+          # #2362 - Attached text files get prepended on e-mail reply instead of appended
+          it 'Email Content should appear before the Text Content within the raw email' do
+            expect(mail.to_s).to match(%r{Email Content[\s\S]*Text Content})
+          end
+
+          it_behaves_like 'not adding email content as attachment'
+
+          include_context 'with attachment checks'
+        end
+      end
+    end
+  end
+
+  describe '#recipient_line' do
+    let(:email)                    { 'some.body@example.com' }
+    let(:generated_recipient_line) { described_class.recipient_line(realname, email) }
+
+    context 'with quote in the realname' do
+      let(:realname) { 'Somebody @ "Company"' }
+
+      it 'escapes the quotes' do
+        expected_recipient_line = '"Somebody @ \"Company\"" <some.body@example.com>'
+        expect(generated_recipient_line).to eq expected_recipient_line
+      end
+    end
+
+    context 'with a simple realname with no special characters' do
+      let(:realname) { 'Somebody' }
+
+      it 'wraps the realname with quotes and wraps the email with <>' do
+        expected_recipient_line = 'Somebody <some.body@example.com>'
+        expect(generated_recipient_line).to eq expected_recipient_line
+      end
+    end
+
+    context 'with special characters (|) in the realname' do
+      let(:realname) { 'Somebody | Some Org' }
+
+      it 'wraps the realname with quotes and wraps the email with <>' do
+        expected_recipient_line = '"Somebody | Some Org" <some.body@example.com>'
+        expect(generated_recipient_line).to eq expected_recipient_line
+      end
+    end
+
+    context 'with special characters (spaces) in the realname' do
+      let(:realname) { 'Test Admin Agent via Support' }
+
+      it 'wraps the realname with quotes and wraps the email with <>' do
+        expected_recipient_line = '"Test Admin Agent via Support" <some.body@example.com>'
+        expect(generated_recipient_line).to eq expected_recipient_line
+      end
+    end
+  end
+
+  # https://github.com/zammad/zammad/issues/165
+  describe '#html_mail_client_fixes' do
+    let(:generated_html) { described_class.html_mail_client_fixes(html) }
+
+    shared_examples 'adding styles to the element' do
+      it 'adds style to the element' do
+        expect(generated_html).to eq expected_html
+      end
+
+      it { expect(generated_html).not_to eq html }
+    end
+
+    context 'when html element is a blockquote' do
+      let(:html) do
+        <<~HTML.chomp
+          <blockquote type="cite">some
+          text
+          </blockquote>
+          123
+          <blockquote type="cite">some
+          text
+          </blockquote>
+        HTML
+      end
+      let(:expected_html) do
+        <<~HTML.chomp
+          <blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
+          text
+          </blockquote>
+          123
+          <blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
+          text
+          </blockquote>
+        HTML
+      end
+
+      it_behaves_like 'adding styles to the element'
+    end
+
+    context 'when html element is a p' do
+      let(:html) do
+        <<~HTML.chomp
+          <p>some
+          text
+          </p>
+          <p>123</p>
+        HTML
+      end
+      let(:expected_html) do
+        <<~HTML.chomp
+          <p style="margin: 0;">some
+          text
+          </p>
+          <p style="margin: 0;">123</p>
+        HTML
+      end
+
+      it_behaves_like 'adding styles to the element'
+    end
+
+    context 'when html element is a hr' do
+      let(:html) do
+        <<~HTML.chomp
+          <p>sometext</p><hr><p>123</p>
+        HTML
+      end
+      let(:expected_html) do
+        <<~HTML.chomp
+          <p style="margin: 0;">sometext</p><hr style="margin-top: 6px; margin-bottom: 6px; border: 0; border-top: 1px solid #dfdfdf;"><p style="margin: 0;">123</p>
+        HTML
+      end
+
+      it_behaves_like 'adding styles to the element'
+
+      context 'when hr is a closing tag' do
+        let(:html) do
+          <<~HTML.chomp
+            <p>sometext</p></hr>
+          HTML
+        end
+        let(:expected_html) do
+          <<~HTML.chomp
+            <p style="margin: 0;">sometext</p><hr style="margin-top: 6px; margin-bottom: 6px; border: 0; border-top: 1px solid #dfdfdf;">
+          HTML
+        end
+
+        it_behaves_like 'adding styles to the element'
+      end
+    end
+
+    context 'when html element does not contian p, hr or blockquote' do
+      let(:html) do
+        <<~HTML.chomp
+          <div>
+            <h2>Testing</h2>
+            <ul>
+              <li><a href="#"><b>Test</b> <span>1</span></a></li>
+              <li><a href="#"><b>Test</b> <span>2</span></a></li>
+              <li><a href="#"><b>Test</b> <span>3</span></a></li>
+            </ul>
+          </div>
+        HTML
+      end
+
+      it 'does not add style to the element' do
+        expect(generated_html).to eq html
+      end
+    end
+  end
+
+  describe '#html_complete_check' do
+    let(:generated_html) { described_class.html_complete_check(html) }
+
+    context 'when html element includes an html tag' do
+      let(:html) { '<!DOCTYPE html><html><b>test</b></html>' }
+
+      it 'returns the html as it is' do
+        expect(generated_html).to eq html
+      end
+    end
+
+    context 'when html does not include an html tag' do
+      let(:html) { '<b>test</b>' }
+
+      it 'adds DOCTYPE tag to the element' do
+        expect(generated_html).to start_with '<!DOCTYPE'
+      end
+
+      it 'adds an html tag' do
+        expect(generated_html).to match '<html>'
+      end
+
+      it 'adds the original element' do
+        expect(generated_html).to match html
+      end
+    end
+
+    # Issue #1230, missing backslashes
+    # 'Test URL: \\storage\project\100242-Inc'
+    context 'when html includes a backslash' do
+      let(:html) { '<b>Test URL</b>: \\\\storage\\project\\100242-Inc' }
+
+      it 'keeps the backslashes' do
+        expect(generated_html).to include html
+      end
+    end
+
+    context 'with a configured html_email_css_font setting' do
+      let(:html)     { '<b>test</b>' }
+      let(:css_font) { "font-family:'Helvetica Neue', sans-serif; font-size: 12px;" }
+
+      before { Setting.set('html_email_css_font', css_font) }
+
+      it 'includes the configured css font' do
+        expect(generated_html).to match css_font
+      end
+    end
+  end
+end

+ 0 - 403
test/unit/email_build_test.rb

@@ -1,403 +0,0 @@
-# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
-
-require 'test_helper'
-
-class EmailBuildTest < ActiveSupport::TestCase
-  test 'document complete check' do
-
-    html   = '<b>test</b>'
-    result = Channel::EmailBuild.html_complete_check(html)
-
-    assert(result.start_with?('<!DOCTYPE'), 'test 1')
-    assert(result !~ %r{^.+?<!DOCTYPE}, 'test 1')
-    assert(result.include?('<html>'), 'test 1')
-    assert(result.include?('font-family'), 'test 1')
-    assert(result.include?('<b>test</b>'), 'test 1')
-
-    html   = 'invalid <!DOCTYPE html><html><b>test</b></html>'
-    result = Channel::EmailBuild.html_complete_check(html)
-
-    assert(result !~ %r{^<!DOCTYPE}, 'test 2')
-    assert(result =~ %r{^.+?<!DOCTYPE}, 'test 2')
-    assert(result.include?('<html>'), 'test 2')
-    assert(result !~ %r{font-family}, 'test 2')
-    assert(result.include?('<b>test</b>'), 'test 2')
-
-    # Issue #1230, missing backslashes
-    # 'Test URL: \\storage\project\100242-Inc'
-    html = '<b>Test URL</b>: \\\\storage\\project\\100242-Inc'
-    result = Channel::EmailBuild.html_complete_check(html)
-    assert(result.include?(html), 'backslashes must be kept')
-
-  end
-
-  test 'html email + attachment check' do
-    html = <<~MSG_HTML.chomp
-      <!DOCTYPE html>
-      <html>
-        <head>
-          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-        </head>
-        <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
-          <div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>
-        </body>
-      </html>
-    MSG_HTML
-    mail = Channel::EmailBuild.build(
-      from:         'sender@example.com',
-      to:           'recipient@example.com',
-      body:         html,
-      content_type: 'text/html',
-      attachments:  [
-        {
-          'Mime-Type' => 'image/png',
-          :content    => 'xxx',
-          :filename   => 'somename.png'
-        }
-      ],
-    )
-
-    text_should = <<~MSG_TEXT.chomp
-      > Welcome!\r
-      >\r
-      > Thank you for installing Zammad. äöüß\r
-      >\r
-    MSG_TEXT
-    assert_equal(text_should, mail.text_part.body.to_s)
-
-    html_should = <<~MSG_HTML.chomp
-      <!DOCTYPE html>\r
-      <html>\r
-        <head>\r
-          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\r
-        </head>\r
-        <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">\r
-          <div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>\r
-        </body>\r
-      </html>
-    MSG_HTML
-    assert_equal(html_should, mail.html_part.body.to_s)
-
-    parser = Channel::EmailParser.new
-    data = parser.parse(mail.to_s)
-
-    # check body
-    should = '<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>'
-    assert_equal(should, data[:body])
-    assert_equal('text/html', data[:content_type])
-
-    # check count of attachments, only 2, because 3 part is text message and is already in body
-    assert_equal(2, data[:attachments].length)
-
-    # check attachments
-    data[:attachments]&.each do |attachment|
-      case attachment[:filename]
-      when 'message.html'
-        assert_nil(attachment[:preferences]['Content-ID'])
-        assert_equal(true, attachment[:preferences]['content-alternative'])
-        assert_equal('text/html', attachment[:preferences]['Mime-Type'])
-        assert_equal('UTF-8', attachment[:preferences]['Charset'])
-      when 'somename.png'
-        assert_nil(attachment[:preferences]['Content-ID'])
-        assert_nil(attachment[:preferences]['content-alternative'])
-        assert_equal('image/png', attachment[:preferences]['Mime-Type'])
-        assert_equal('UTF-8', attachment[:preferences]['Charset'])
-      else
-        assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
-      end
-    end
-  end
-
-  test 'plain email + attachment check' do
-    text = <<~MSG_TEXT.chomp
-      > Welcome!
-      >
-      > Thank you for installing Zammad. äöüß
-      >
-    MSG_TEXT
-    mail = Channel::EmailBuild.build(
-      from:        'sender@example.com',
-      to:          'recipient@example.com',
-      body:        text,
-      attachments: [
-        {
-          'Mime-Type' => 'image/png',
-          :content    => 'xxx',
-          :filename   => 'somename.png'
-        }
-      ],
-    )
-
-    text_should = <<~MSG_TEXT.chomp
-      > Welcome!\r
-      >\r
-      > Thank you for installing Zammad. äöüß\r
-      >\r
-    MSG_TEXT
-    assert_equal(text_should, mail.text_part.body.to_s)
-    assert_nil(mail.html_part)
-    assert_equal('image/png; filename=somename.png', mail.attachments[0].content_type)
-
-    parser = Channel::EmailParser.new
-    data = parser.parse(mail.to_s)
-
-    # check body
-    assert_equal(text, data[:body])
-
-    # check count of attachments, 2
-    assert_equal(1, data[:attachments].length)
-
-    # check attachments
-    data[:attachments]&.each do |attachment|
-      if attachment[:filename] == 'somename.png'
-        assert_nil(attachment[:preferences]['Content-ID'])
-        assert_nil(attachment[:preferences]['content-alternative'])
-        assert_equal('image/png', attachment[:preferences]['Mime-Type'])
-        assert_equal('UTF-8', attachment[:preferences]['Charset'])
-      else
-        assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
-      end
-    end
-  end
-
-  test 'plain email + attachment check 2' do
-    ticket1 = Ticket.create!(
-      title:         'some article helper test1',
-      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,
-    )
-    assert(ticket1, 'ticket created')
-
-    # create inbound article #1
-    article1 = Ticket::Article.create!(
-      ticket_id:     ticket1.id,
-      from:          'some_sender@example.com',
-      to:            'some_recipient@example.com',
-      subject:       'some subject',
-      message_id:    'some@id',
-      content_type:  'text/html',
-      body:          'some message article helper test1 <div><img style="width: 85.5px; height: 49.5px" src="cid:15.274327094.140938@zammad.example.com">asdasd<img src="cid:15.274327094.140939@zammad.example.com"><br>',
-      internal:      false,
-      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
-      type:          Ticket::Article::Type.find_by(name: 'email'),
-      updated_by_id: 1,
-      created_by_id: 1,
-    )
-
-    store1 = Store.create!(
-      object:        'Ticket::Article',
-      o_id:          article1.id,
-      data:          'content_file1_normally_should_be_an_ics_calendar_file',
-      filename:      'schedule.ics',
-      preferences:   {
-        'Mime-Type' => 'text/calendar'
-      },
-      created_by_id: 1,
-    )
-
-    text = <<~MSG_TEXT.chomp
-      > Welcome!
-      >
-      > Thank you for installing Zammad. äöüß
-      >
-    MSG_TEXT
-    mail = Channel::EmailBuild.build(
-      from:        'sender@example.com',
-      to:          'recipient@example.com',
-      body:        text,
-      attachments: [
-        store1
-      ],
-    )
-
-    text_should = <<~MSG_TEXT.chomp
-      > Welcome!\r
-      >\r
-      > Thank you for installing Zammad. äöüß\r
-      >\r
-    MSG_TEXT
-    assert_equal(text_should, mail.text_part.body.to_s)
-    assert_nil(mail.html_part)
-    assert_equal('text/calendar; filename=schedule.ics', mail.attachments[0].content_type)
-
-    parser = Channel::EmailParser.new
-    data = parser.parse(mail.to_s)
-
-    # check body
-    assert_equal(text, data[:body])
-
-    # check count of attachments, 2
-    assert_equal(1, data[:attachments].length)
-
-    # check attachments
-    data[:attachments]&.each do |attachment|
-      if attachment[:filename] == 'schedule.ics'
-        assert(attachment[:preferences]['Content-ID'])
-        assert_nil(attachment[:preferences]['content-alternative'])
-        assert_equal('text/calendar', attachment[:preferences]['Mime-Type'])
-        assert_equal('UTF-8', attachment[:preferences]['Charset'])
-      else
-        assert(false, "invalid attachment, should not be there, #{attachment.inspect}")
-      end
-    end
-  end
-
-  test 'plain email + without attachment check' do
-    text = <<~MSG_TEXT.chomp
-      > Welcome!
-      >
-      > Thank you for installing Zammad. äöüß
-      >
-    MSG_TEXT
-    mail = Channel::EmailBuild.build(
-      from: 'sender@example.com',
-      to:   'recipient@example.com',
-      body: text,
-    )
-
-    text_should = <<~MSG_TEXT.chomp
-      > Welcome!\r
-      >\r
-      > Thank you for installing Zammad. äöüß\r
-      >\r
-    MSG_TEXT
-    assert_equal(text_should, mail.body.to_s)
-    assert_nil(mail.html_part)
-
-    parser = Channel::EmailParser.new
-    data = parser.parse(mail.to_s)
-
-    # check body
-    assert_equal(text, data[:body])
-
-    # check count of attachments, 0
-    assert_equal(0, data[:attachments].length)
-
-  end
-
-  test 'email - html email client fixes' do
-
-    # https://github.com/martini/zammad/issues/165
-    html_raw = '<blockquote type="cite">some
-text
-</blockquote>
-
-123
-
-<blockquote type="cite">some
-text
-</blockquote>'
-    html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
-    assert_not_equal(html_with_fixes, html_raw)
-
-    html_should = '<blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
-text
-</blockquote>
-
-123
-
-<blockquote type="cite" style="border-left: 2px solid blue; margin: 0 0 16px; padding: 8px 12px 8px 12px;">some
-text
-</blockquote>'
-    assert_equal(html_should, html_with_fixes)
-
-    html_raw = '<p>some
-text
-</p>
-<p>123</p>'
-    html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
-    assert_not_equal(html_with_fixes, html_raw)
-
-    html_should = '<p style="margin: 0;">some
-text
-</p>
-<p style="margin: 0;">123</p>'
-    assert_equal(html_should, html_with_fixes)
-
-    html_raw = '<p>sometext</p><hr><p>123</p>'
-    html_with_fixes = Channel::EmailBuild.html_mail_client_fixes(html_raw)
-    assert_not_equal(html_with_fixes, html_raw)
-
-    html_should = '<p style="margin: 0;">sometext</p><hr style="margin-top: 6px; margin-bottom: 6px; border: 0; border-top: 1px solid #dfdfdf;"><p style="margin: 0;">123</p>'
-    assert_equal(html_should, html_with_fixes)
-  end
-
-  test 'from checks' do
-
-    quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody @ "Company"', 'some.body@example.com')
-    assert_equal('"Somebody @ \"Company\"" <some.body@example.com>', quoted_in_one_line)
-
-    quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody', 'some.body@example.com')
-    assert_equal('Somebody <some.body@example.com>', quoted_in_one_line)
-
-    quoted_in_one_line = Channel::EmailBuild.recipient_line('Somebody | Some Org', 'some.body@example.com')
-    assert_equal('"Somebody | Some Org" <some.body@example.com>', quoted_in_one_line)
-
-    quoted_in_one_line = Channel::EmailBuild.recipient_line('Test Admin Agent via Support', 'some.body@example.com')
-    assert_equal('"Test Admin Agent via Support" <some.body@example.com>', quoted_in_one_line)
-
-  end
-
-  # #2362 - Attached text files get prepended on e-mail reply instead of appended
-  test 'plain email + text attachment' do
-    ticket1 = Ticket.create!(
-      title:         'some article text attachment test',
-      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,
-    )
-    assert(ticket1, 'ticket created')
-
-    article1 = Ticket::Article.create!(
-      ticket_id:     ticket1.id,
-      from:          'some_sender@example.com',
-      to:            'some_recipient@example.com',
-      subject:       'some subject',
-      message_id:    'some@id',
-      content_type:  'text/html',
-      body:          'some message article helper test1 <div><img style="width: 85.5px; height: 49.5px" src="cid:15.274327094.140938@zammad.example.com">asdasd<img src="cid:15.274327094.140939@zammad.example.com"><br>',
-      internal:      false,
-      sender:        Ticket::Article::Sender.find_by(name: 'Customer'),
-      type:          Ticket::Article::Type.find_by(name: 'email'),
-      updated_by_id: 1,
-      created_by_id: 1,
-    )
-
-    text = <<~MSG_TEXT.chomp
-      > Welcome!
-      >
-      > Email Content
-    MSG_TEXT
-
-    store1 = Store.create!(
-      object:        'Ticket::Article',
-      o_id:          article1.id,
-      data:          'Text Content',
-      filename:      'text_file.txt',
-      preferences:   {
-        'Mime-Type' => 'text/plain'
-      },
-      created_by_id: 1,
-    )
-
-    mail = Channel::EmailBuild.build(
-      from:        'sender@example.com',
-      to:          'recipient@example.com',
-      body:        text,
-      attachments: [
-        store1
-      ],
-    )
-    File.write('append_test.eml', mail.to_s)
-
-    # Email Content should appear before the Text Content within the raw email
-    assert_match(%r{Email Content[\s\S]*Text Content}, mail.to_s)
-  end
-end