diff --git a/lib/email/sender.rb b/lib/email/sender.rb
index aafd834bfd0..456f2054c81 100644
--- a/lib/email/sender.rb
+++ b/lib/email/sender.rb
@@ -26,7 +26,8 @@ module Email
class Sender
def initialize(message, email_type, user = nil)
- @message = message
+ @message = message
+ @message_attachments_index = {}
@email_type = email_type
@user = user
end
@@ -240,7 +241,7 @@ module Email
# Embeds any of the secure images that have been attached inline,
# removing the redaction notice.
if SiteSetting.secure_media_allow_embed_images_in_emails
- style.inline_secure_images(@message.attachments)
+ style.inline_secure_images(@message.attachments, @message_attachments_index)
end
@message.html_part.body = style.to_s
@@ -328,6 +329,7 @@ module Email
Discourse.store.download(attached_upload).path
end
+ @message_attachments_index[original_upload.sha1] = @message.attachments.size
@message.attachments[original_upload.original_filename] = File.read(path)
email_size += File.size(path)
rescue => e
diff --git a/lib/email/styles.rb b/lib/email/styles.rb
index 5938dffaf47..c848ecf6159 100644
--- a/lib/email/styles.rb
+++ b/lib/email/styles.rb
@@ -253,7 +253,7 @@ module Email
@@plugin_callbacks.each { |block| block.call(@fragment, @opts) }
end
- def inline_secure_images(attachments)
+ def inline_secure_images(attachments, attachments_index)
stripped_media = @fragment.css('[data-stripped-secure-media]')
upload_shas = {}
stripped_media.each do |div|
@@ -269,10 +269,8 @@ module Email
upload = uploads.find { |upl| upl.sha1 == upload_shas[div['data-stripped-secure-media']] }
next if !upload
- original_filename = upload.original_filename
-
- if attachments[original_filename]
- url = attachments[original_filename].url
+ if attachments[attachments_index[upload.sha1]]
+ url = attachments[attachments_index[upload.sha1]].url
onebox_type = div['data-onebox-type']
style = if onebox_type
diff --git a/spec/components/email/sender_spec.rb b/spec/components/email/sender_spec.rb
index 34c1a2e36a5..7d6643d9f2c 100644
--- a/spec/components/email/sender_spec.rb
+++ b/spec/components/email/sender_spec.rb
@@ -498,6 +498,21 @@ describe Email::Sender do
SiteSetting.secure_media_allow_embed_images_in_emails = true
end
+ it "can inline images with duplicate names" do
+ @secure_image_2 = UploadCreator.new(file_from_fixtures("logo-dev.png", "images"), "logo.png").create_for(Discourse.system_user.id)
+ @secure_image_2.update_secure_status(override: true)
+ @secure_image_2.update(access_control_post_id: reply.id)
+
+ Jobs::PullHotlinkedImages.any_instance.expects(:execute)
+ reply.update(raw: "#{UploadMarkdown.new(@secure_image).image_markdown}\n#{UploadMarkdown.new(@secure_image_2).image_markdown}")
+ reply.rebake!
+
+ Email::Sender.new(message, :valid_type).send
+ expect(message.attachments.size).to eq(2)
+ expect(message.to_s.scan(/cid:[\w\-@.]+/).length).to eq(2)
+ expect(message.to_s.scan(/cid:[\w\-@.]+/).uniq.length).to eq(2)
+ end
+
it "does not attach images that are not marked as secure" do
Email::Sender.new(message, :valid_type).send
expect(message.attachments.length).to eq(4)
diff --git a/spec/components/email/styles_spec.rb b/spec/components/email/styles_spec.rb
index 55fe5187ef8..be5b634d54e 100644
--- a/spec/components/email/styles_spec.rb
+++ b/spec/components/email/styles_spec.rb
@@ -252,8 +252,9 @@ describe Email::Styles do
SiteSetting.secure_media = true
end
- let(:attachments) { { 'testimage.png' => stub(url: 'cid:email/test.png') } }
fab!(:upload) { Fabricate(:upload, original_filename: 'testimage.png', secure: true, sha1: '123456') }
+ let(:attachments) { [stub(url: 'cid:email/test.png')] }
+ let(:attachments_index) { { upload.sha1 => 0 } }
let(:html) { "
" }
def strip_and_inline
@@ -265,7 +266,7 @@ describe Email::Styles do
# pass in the attachments to match uploads based on sha + original filename
styler = Email::Styles.new(html)
- styler.inline_secure_images(attachments)
+ styler.inline_secure_images(attachments, attachments_index)
@frag = Nokogiri::HTML5.fragment(styler.to_s)
end
@@ -302,12 +303,8 @@ describe Email::Styles do
end
let(:siteicon) { Fabricate(:upload, original_filename: "siteicon.ico") }
- let(:attachments) do
- {
- 'testimage.png' => stub(url: 'cid:email/test.png'),
- 'siteicon.ico' => stub(url: 'cid:email/test2.ico')
- }
- end
+ let(:attachments) { [stub(url: 'cid:email/test.png'), stub(url: 'cid:email/test2.ico')] }
+ let(:attachments_index) { { upload.sha1 => 0, siteicon.sha1 => 1 } }
let(:html) do
<<~HTML