Fixes issue #2894 - Emails with binary body (attachment as body) get handled as if they were text messages which breaks the attachment.

This commit is contained in:
Mantas Masalskis 2020-01-28 10:42:40 +01:00 committed by Thorsten Eckel
parent 264853dcbe
commit 6692869dd8
3 changed files with 84 additions and 27 deletions

View file

@ -574,13 +574,27 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
def collect_attachments(mail)
attachments = []
# Add non-plaintext body as an attachment
if mail.html_part&.body.present? ||
(!mail.multipart? && mail.mime_type.present? && mail.mime_type != 'text/plain')
attachments.push(*get_nonplaintext_body_as_attachment(mail))
mail.parts.each do |part|
attachments.push(*gracefully_get_attachments(part, attachments, mail))
end
attachments
end
def get_nonplaintext_body_as_attachment(mail)
if !(mail.html_part&.body.present? || (!mail.multipart? && mail.mime_type.present? && mail.mime_type != 'text/plain'))
return
end
message = mail.html_part || mail
filename = message.filename.presence ||
(message.mime_type.eql?('text/html') ? 'message.html' : '-no name-')
if !mail.mime_type.starts_with?('text/') && mail.html_part.blank?
return gracefully_get_attachments(message, [], mail)
end
filename = message.filename.presence || (message.mime_type.eql?('text/html') ? 'message.html' : '-no name-')
headers_store = {
'content-alternative' => true,
@ -589,23 +603,19 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
'Charset' => message.charset,
}.reject { |_, v| v.blank? }
attachments.push({ data: body_text(message),
[{
data: body_text(message),
filename: filename,
preferences: headers_store })
preferences: headers_store
}]
end
mail.parts.each do |part|
new_attachments = get_attachments(part, attachments, mail).flatten.compact
attachments.push(*new_attachments)
def gracefully_get_attachments(part, attachments, mail)
get_attachments(part, attachments, mail).flatten.compact
rescue => e # Protect process to work with spam emails (see test/fixtures/mail15.box)
raise e if (fail_count ||= 0).positive?
(fail_count += 1) && retry
end
attachments
end
def get_attachments(file, attachments, mail)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long