FIX: prevents duplicate attachments in incoming emails (#25986)

## What?

Depending on the email software used, when you reply to an email that has some attachments, they will be sent along, since they're part of the embedded (replied to) email.

When Discourse processes the reply as an incoming email, it will automatically add all the (valid) attachments at the end of the post. Including those that were sent as part of the "embedded reply".

This generates posts in Discourse with duplicate attachments 🙁

## How?

When processing attachments of an incoming email, before we add it to the bottom of the post, we check it against all the previous uploads in the same topic. If there already is an `Upload` record, it means that it's a duplicate and it is _therefore_ skipped.

All the inline attachments are left untouched since they're more likely new attachments added by the sender.
This commit is contained in:
Régis Hanol 2024-03-01 18:38:49 +01:00 committed by GitHub
parent ccf0fdaa81
commit 5fcb7c262d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 18 additions and 2 deletions

View File

@ -1359,6 +1359,12 @@ module Email
def add_attachments(raw, user, options = {})
raw = raw.dup
previous_upload_ids =
UploadReference
.where(target_id: Post.where(topic_id: options[:topic_id]).select(:id))
.pluck(:upload_id)
.uniq
rejected_attachments = []
attachments.each do |attachment|
tmp = Tempfile.new(["discourse-email-attachment", File.extname(attachment.filename)])
@ -1384,10 +1390,10 @@ module Email
end
elsif raw[/\[image:[^\]]*\]/i]
raw.sub!(/\[image:[^\]]*\]/i, UploadMarkdown.new(upload).to_markdown)
else
elsif !previous_upload_ids.include?(upload.id)
raw << "\n\n#{UploadMarkdown.new(upload).to_markdown}\n\n"
end
else
elsif !previous_upload_ids.include?(upload.id)
raw << "\n\n#{UploadMarkdown.new(upload).to_markdown}\n\n"
end
else

BIN
spec/fixtures/emails/logo_1.eml vendored Normal file

Binary file not shown.

BIN
spec/fixtures/emails/logo_2.eml vendored Normal file

Binary file not shown.

View File

@ -756,6 +756,16 @@ RSpec.describe Email::Receiver do
MD
end
it "tries not to repeat duplicate attachments" do
SiteSetting.authorized_extensions = "jpg"
expect { process(:logo_1) }.to change { UploadReference.count }.by(1)
expect(topic.posts.last.raw).to match %r{upload://}
expect { process(:logo_2) }.not_to change { UploadReference.count }
expect(topic.posts.last.raw).not_to match %r{upload://}
end
it "works with removed attachments" do
SiteSetting.authorized_extensions = "jpg"