From 99af4f187a2527888a700820ad82f1210ec3ccc0 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 6 Nov 2017 04:26:00 +0100 Subject: [PATCH] Improved filename detection of incoming postmaster emails (use subject.eml and no file-1). --- app/models/channel/email_parser.rb | 59 ++++++++++++++++++++------ test/unit/email_parser_test.rb | 68 +++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 16 deletions(-) diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb index b62c71a6f..11281df87 100644 --- a/app/models/channel/email_parser.rb +++ b/app/models/channel/email_parser.rb @@ -158,7 +158,7 @@ class Channel::EmailParser end # text attachment/body exists - if data[:body].empty? && mail.text_part + if data[:body].blank? && mail.text_part data[:body] = mail.text_part.body.decoded data[:body] = Encode.conv(mail.text_part.charset, data[:body]) data[:body] = data[:body].to_s.force_encoding('utf-8') @@ -170,7 +170,7 @@ class Channel::EmailParser end # any other attachments - if data[:body].empty? + if data[:body].blank? data[:body] = 'no visible content' data[:content_type] = 'text/plain' end @@ -296,13 +296,13 @@ class Channel::EmailParser def _get_attachment(file, attachments, mail) # check if sub parts are available - if !file.parts.empty? - a = [] + if file.parts.present? + list = [] file.parts.each do |p| attachment = _get_attachment(p, attachments, mail) - a.concat(attachment) + list.concat(attachment) end - return a + return list end # ignore text/plain attachments - already shown in view @@ -327,6 +327,12 @@ class Channel::EmailParser end end + # cleanup content id, <> will be added automatically later + if headers_store['Content-ID'] + headers_store['Content-ID'].gsub!(/^$/, '') + end + # get filename from content-disposition filename = nil @@ -361,7 +367,38 @@ class Channel::EmailParser # for some broken sm mail clients (X-MimeOLE: Produced By Microsoft Exchange V6.5) filename ||= file.header[:content_location].to_s - # generate file name + # generate file name based on content-id + if filename.blank? && headers_store['Content-ID'].present? + if headers_store['Content-ID'] =~ /(.+?)@.+?/i + filename = $1 + end + end + + # generate file name based on content type + if filename.blank? && headers_store['Content-Type'].present? + if headers_store['Content-Type'] =~ %r{^message/delivery-status$}i + filename = if headers_store['Content-Description'].present? + "#{headers_store['Content-Description']}.txt" + else + 'delivery-status.txt' + end + elsif headers_store['Content-Type'] =~ %r{^message/rfc822$}i + begin + parser = Channel::EmailParser.new + mail_local = parser.parse(file.body.to_s) + filename = if mail_local[:subject].present? + "#{mail_local[:subject]}.eml" + elsif headers_store['Content-Description'].present? + "#{headers_store['Content-Description']}.eml" + else + 'Mail.eml' + end + rescue + filename = 'Mail.eml' + end + end + end + if filename.blank? attachment_count = 0 (1..1000).each do |count| @@ -390,12 +427,6 @@ class Channel::EmailParser headers_store.delete('Content-Transfer-Encoding') headers_store.delete('Content-Disposition') - # cleanup content id, <> will be added automatically later - if headers_store['Content-ID'] - headers_store['Content-ID'].gsub!(/^$/, '') - end - # workaround for mail gem # https://github.com/zammad/zammad/issues/928 filename = Mail::Encodings.value_decode(filename) @@ -667,7 +698,7 @@ returns end end - if data.empty? || data[:from_email].blank? + if data.blank? || data[:from_email].blank? from.strip! if from =~ /^(.+?)<(.+?)@(.+?)>$/ data[:from_email] = "#{$2}@#{$3}" diff --git a/test/unit/email_parser_test.rb b/test/unit/email_parser_test.rb index 08b472ba4..b8a813d75 100644 --- a/test/unit/email_parser_test.rb +++ b/test/unit/email_parser_test.rb @@ -421,11 +421,11 @@ Managing Director: Martin Edenhofer attachments: [ { md5: '5536be23f647953dc39c1673205d6f5b', - filename: 'file-1', + filename: 'Neue Anfrage erstellt - 33284.eml', }, { md5: '4eeeae078b920f9d0708353ba0f6aa63', - filename: 'file-2', + filename: 'Call: HW-Anforderung; Best-nr.47524152.eml', }, ], params: { @@ -1191,6 +1191,70 @@ Old programmers never die. They just branch to a new address." Old programmers never die. They just branch to a new address." }, }, + { + data: IO.binread('test/fixtures/mail62.box'), + body_md5: '10e7158e65a12b5850163d4d4b8ca2f8', + attachments: [ + { + md5: '2b615b93ed76877dddbb7d0e3855916b', + filename: 'message.html', + }, + { + md5: 'a618d671348735744d4c9a4005b56799', + filename: 'image001.jpg', + cid: 'image001.jpg@01CDB132.D8A510F0', + }, + { + md5: '2cca28177acb4190cbf79cf3624cddae', + filename: 'image000.jpg', + cid: 'image000.jpg@01CDB132.D8A510F0', + }, + ], + params: { + from: 'Smith Sepp ', + from_email: 'smith@example.com', + from_display_name: 'Smith Sepp', + subject: 'Gruß aus Oberalteich', + content_type: 'text/html', + body: "
+

Herzliche Grüße aus Oberalteich sendet Herrn Smith

 

Sepp Smith - Dipl.Ing. agr. (FH)

Geschäftsführer der example Straubing-Bogen

Klosterhof 1 | 94327 Bogen-Oberalteich

Tel: 09422-505601 | Fax: 09422-505620

Internet: http://example-straubing-bogen.de

Facebook: http://facebook.de/examplesrbog

\"Beschreibung:\"Beschreibung: - European Foundation für Quality Management

 

", + }, + }, + { + data: IO.binread('test/fixtures/mail63.box'), + body_md5: 'dbed0b09656d17bf4e832b2c18381c24', + attachments: [ + { + md5: 'b8be1b421733bf2fab2eb24e11d53139', + filename: 'Delivery report.txt', + }, + { + md5: '47744d00358baaeff355ca91ede93859', + filename: 'hello 123 äöüß.eml', + }, + ], + params: { + from: 'MAILER-DAEMON@mx1.example.com (Mail Delivery System)', + from_email: 'MAILER-DAEMON@mx1.example.com', + from_display_name: 'Mail Delivery System', + subject: 'Undelivered Mail Returned to Sender', + content_type: 'text/plain', + body: "This is the mail system at host mx1.example.com. + +I'm sorry to have to inform you that your message could not +be delivered to one or more recipients. It's attached below. + +For further assistance, please send mail to postmaster. + +If you do so, please include this problem report. You can +delete your own text from the attached returned message. + + The mail system + +: user unknown +", + }, + }, ] count = 0