2018-11-05 23:45:35 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-08-20 14:05:06 -04:00
|
|
|
module Gitlab
|
|
|
|
module Email
|
2015-08-20 14:17:14 -04:00
|
|
|
class AttachmentUploader
|
2015-08-20 14:05:06 -04:00
|
|
|
attr_accessor :message
|
|
|
|
|
|
|
|
def initialize(message)
|
|
|
|
@message = message
|
|
|
|
end
|
|
|
|
|
2020-01-14 04:08:19 -05:00
|
|
|
def execute(upload_parent:, uploader_class:)
|
2015-08-20 14:05:06 -04:00
|
|
|
attachments = []
|
|
|
|
|
2020-02-18 07:09:15 -05:00
|
|
|
filter_signature_attachments(message).each do |attachment|
|
2015-08-20 14:05:06 -04:00
|
|
|
tmp = Tempfile.new("gitlab-email-attachment")
|
|
|
|
begin
|
2022-02-17 19:19:10 -05:00
|
|
|
content = attachment.body.decoded
|
|
|
|
File.open(tmp.path, "w+b") { |f| f.write content }
|
|
|
|
sanitize_exif_if_needed(content, tmp.path)
|
2015-08-20 14:05:06 -04:00
|
|
|
|
|
|
|
file = {
|
2022-08-18 11:12:17 -04:00
|
|
|
tempfile: tmp,
|
|
|
|
filename: attachment.filename,
|
2015-08-20 14:05:06 -04:00
|
|
|
content_type: attachment.content_type
|
|
|
|
}
|
|
|
|
|
2020-01-14 04:08:19 -05:00
|
|
|
uploader = UploadService.new(upload_parent, file, uploader_class).execute
|
2019-01-03 00:17:07 -05:00
|
|
|
attachments << uploader.to_h if uploader
|
2015-08-20 14:05:06 -04:00
|
|
|
ensure
|
|
|
|
tmp.close!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
attachments
|
|
|
|
end
|
2020-02-18 07:09:15 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# If this is a signed message (e.g. S/MIME or PGP), remove the signature
|
|
|
|
# from the uploaded attachments
|
|
|
|
def filter_signature_attachments(message)
|
|
|
|
attachments = message.attachments
|
2020-04-05 23:09:23 -04:00
|
|
|
content_type = normalize_mime(message.content_type)
|
2021-05-24 20:10:54 -04:00
|
|
|
protocol = normalize_mime(message.content_type_parameters&.fetch(:protocol, nil))
|
2020-02-18 07:09:15 -05:00
|
|
|
|
2020-04-05 23:09:23 -04:00
|
|
|
if content_type == 'multipart/signed' && protocol
|
|
|
|
attachments.delete_if { |attachment| protocol == normalize_mime(attachment.content_type) }
|
2020-02-18 07:09:15 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
attachments
|
|
|
|
end
|
2020-04-05 23:09:23 -04:00
|
|
|
|
|
|
|
# normalizes mime-type ignoring case and removing extra data
|
|
|
|
# also removes potential "x-" prefix from subtype, since some MUAs mix them
|
|
|
|
# e.g. "application/x-pkcs7-signature" with "application/pkcs7-signature"
|
|
|
|
def normalize_mime(content_type)
|
|
|
|
MIME::Type.simplified(content_type, remove_x_prefix: true)
|
|
|
|
end
|
2022-02-17 19:19:10 -05:00
|
|
|
|
|
|
|
# https://gitlab.com/gitlab-org/gitlab/-/issues/239343
|
|
|
|
def sanitize_exif_if_needed(content, path)
|
|
|
|
exif_sanitizer = Gitlab::Sanitizers::Exif.new
|
|
|
|
exif_sanitizer.clean_existing_path(path, content: content, skip_unallowed_types: true)
|
|
|
|
end
|
2015-08-20 14:05:06 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|