diff --git a/app/models/channel/email_build.rb b/app/models/channel/email_build.rb index da063dc8a..e6c1bbc7e 100644 --- a/app/models/channel/email_build.rb +++ b/app/models/channel/email_build.rb @@ -44,7 +44,7 @@ module Channel::EmailBuild # add html part if attr[:content_type] && attr[:content_type] == 'text/html' - mail.html_part = Mail::Part.new do + html_alternative = Mail::Part.new do content_type 'text/html; charset=UTF-8' # complete check @@ -58,19 +58,46 @@ module Channel::EmailBuild end # add plain text part - mail.text_part = Mail::Part.new do + text_alternative = Mail::Part.new do content_type 'text/plain; charset=UTF-8' body attr[:body] end + # build email without any attachments + if !html_alternative && ( !attr[:attachments] || attr[:attachments].empty? ) + mail.content_type 'text/plain; charset=UTF-8' + mail.body attr[:body] + return mail + end + + # build email with attachments + alternative_bodies = Mail::Part.new { content_type 'multipart/alternative' } + alternative_bodies.add_part text_alternative + + if html_alternative + html_container = Mail::Part.new { content_type 'multipart/related' } + html_container.add_part html_alternative + alternative_bodies.add_part html_container + + # place to add inline attachments related to html alternative + end + + mail.add_part alternative_bodies + # add attachments if attr[:attachments] attr[:attachments].each do |attachment| - mail.attachments[attachment.filename] = { - :content_type => attachment.preferences['Content-Type'], - :mime_type => attachment.preferences['Mime-Type'], - :content => attachment.content - } + if attachment.class == Hash + attachment['content-id'] = nil + mail.attachments[ attachment[:filename] ] = attachment + else + mail.attachments[attachment.filename] = { + :content_type => attachment.preferences['Content-Type'], + :mime_type => attachment.preferences['Mime-Type'], + :content => attachment.content, + 'content-id' => nil, + } + end end end mail diff --git a/test/unit/email_build_test.rb b/test/unit/email_build_test.rb index a3cd255de..864872dc2 100644 --- a/test/unit/email_build_test.rb +++ b/test/unit/email_build_test.rb @@ -25,14 +25,14 @@ class EmailBuildTest < ActiveSupport::TestCase end - test 'html email check' do + test 'html email + attachment check' do html = ' -
> Welcome!
>
> Thank you for installing Zammad.
>
+
> Welcome!
>
> Thank you for installing Zammad. äöüß
>
' mail = Channel::EmailBuild.build( @@ -40,18 +40,133 @@ class EmailBuildTest < ActiveSupport::TestCase :to => 'recipient@example.com', :body => html, :content_type => 'text/html', + :attachments => [ + { + 'Mime-Type' => 'image/png', + :content => 'xxx', + :filename => 'somename.png', + }, + ], ) should = '> Welcome! > -> Thank you for installing Zammad. +> Thank you for installing Zammad. äöüß > ' assert_equal( should, mail.text_part.body.to_s ) assert_equal( html, mail.html_part.body.to_s ) + parser = Channel::EmailParser.new + data = parser.parse( mail.to_s ) + + # check body + assert_equal( should, data[:body] ) + + # 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 + if data[:attachments] + data[:attachments].each { |attachment| + if attachment[:filename] == 'message.html' + assert_equal( 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'] ) + elsif attachment[:filename] == 'somename.png' + assert_equal( nil, attachment[:preferences]['Content-ID'] ) + assert_equal( 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 = '> Welcome! +> +> Thank you for installing Zammad. äöüß +> +' + mail = Channel::EmailBuild.build( + :from => 'sender@example.com', + :to => 'recipient@example.com', + :body => text, + :attachments => [ + { + 'Mime-Type' => 'image/png', + :content => 'xxx', + :filename => 'somename.png', + }, + ], + ) + + should = '> Welcome! +> +> Thank you for installing Zammad. äöüß +> +' + assert_equal( should, mail.text_part.body.to_s ) + assert_equal( nil, mail.html_part ) + + parser = Channel::EmailParser.new + data = parser.parse( mail.to_s ) + + # check body + assert_equal( should, data[:body] ) + + # check count of attachments, 2 + assert_equal( 1, data[:attachments].length ) + + # check attachments + if data[:attachments] + data[:attachments].each { |attachment| + if attachment[:filename] == 'somename.png' + assert_equal( nil, attachment[:preferences]['Content-ID'] ) + assert_equal( 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 + without attachment check' do + text = '> Welcome! +> +> Thank you for installing Zammad. äöüß +> +' + mail = Channel::EmailBuild.build( + :from => 'sender@example.com', + :to => 'recipient@example.com', + :body => text, + ) + + should = '> Welcome! +> +> Thank you for installing Zammad. äöüß +> +' + assert_equal( should, mail.body.to_s ) + assert_equal( nil, mail.html_part ) + + parser = Channel::EmailParser.new + data = parser.parse( mail.to_s ) + + # check body + assert_equal( should, data[:body] ) + + # check count of attachments, 0 + assert_equal( 0, data[:attachments].length ) + + end test 'html2text' do html = ' @@ -85,6 +200,5 @@ you * #2' assert_equal( should, html.html2text ) - end end \ No newline at end of file