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:
parent
264853dcbe
commit
6692869dd8
3 changed files with 84 additions and 27 deletions
|
@ -574,40 +574,50 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
|
||||||
def collect_attachments(mail)
|
def collect_attachments(mail)
|
||||||
attachments = []
|
attachments = []
|
||||||
|
|
||||||
# Add non-plaintext body as an attachment
|
attachments.push(*get_nonplaintext_body_as_attachment(mail))
|
||||||
if mail.html_part&.body.present? ||
|
|
||||||
(!mail.multipart? && mail.mime_type.present? && mail.mime_type != 'text/plain')
|
|
||||||
message = mail.html_part || mail
|
|
||||||
|
|
||||||
filename = message.filename.presence ||
|
|
||||||
(message.mime_type.eql?('text/html') ? 'message.html' : '-no name-')
|
|
||||||
|
|
||||||
headers_store = {
|
|
||||||
'content-alternative' => true,
|
|
||||||
'original-format' => message.mime_type.eql?('text/html'),
|
|
||||||
'Mime-Type' => message.mime_type,
|
|
||||||
'Charset' => message.charset,
|
|
||||||
}.reject { |_, v| v.blank? }
|
|
||||||
|
|
||||||
attachments.push({ data: body_text(message),
|
|
||||||
filename: filename,
|
|
||||||
preferences: headers_store })
|
|
||||||
end
|
|
||||||
|
|
||||||
mail.parts.each do |part|
|
mail.parts.each do |part|
|
||||||
|
attachments.push(*gracefully_get_attachments(part, attachments, mail))
|
||||||
new_attachments = get_attachments(part, attachments, mail).flatten.compact
|
|
||||||
attachments.push(*new_attachments)
|
|
||||||
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
|
end
|
||||||
|
|
||||||
attachments
|
attachments
|
||||||
end
|
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
|
||||||
|
|
||||||
|
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,
|
||||||
|
'original-format' => message.mime_type.eql?('text/html'),
|
||||||
|
'Mime-Type' => message.mime_type,
|
||||||
|
'Charset' => message.charset,
|
||||||
|
}.reject { |_, v| v.blank? }
|
||||||
|
|
||||||
|
[{
|
||||||
|
data: body_text(message),
|
||||||
|
filename: filename,
|
||||||
|
preferences: headers_store
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
def get_attachments(file, attachments, mail)
|
def get_attachments(file, attachments, mail)
|
||||||
return file.parts.map { |p| get_attachments(p, attachments, mail) } if file.parts.any?
|
return file.parts.map { |p| get_attachments(p, attachments, mail) } if file.parts.any?
|
||||||
return [] if [mail.text_part&.body&.encoded, mail.html_part&.body&.encoded].include?(file.body.encoded)
|
return [] if [mail.text_part&.body&.encoded, mail.html_part&.body&.encoded].include?(file.body.encoded)
|
||||||
|
|
20
test/data/mail/mail086.box
Normal file
20
test/data/mail/mail086.box
Normal file
File diff suppressed because one or more lines are too long
27
test/data/mail/mail086.yml
Normal file
27
test/data/mail/mail086.yml
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue