FEATURE: Add attachments to outgoing emails
This feature is off by default and can can be configured with the `email_total_attachment_size_limit_kb` site setting. Co-authored-by: Maja Komel <maja.komel@gmail.com>
This commit is contained in:
parent
0e1d6151b9
commit
7e0eeed292
|
@ -1812,6 +1812,7 @@ en:
|
|||
enable_forwarded_emails: "[BETA] Allow users to create a topic by forwarding an email in."
|
||||
always_show_trimmed_content: "Always show trimmed part of incoming emails. WARNING: might reveal email addresses."
|
||||
private_email: "Don't include content from posts or topics in email title or email body. NOTE: also disables digest emails."
|
||||
email_total_attachment_size_limit_kb: "Max total size of files attached to outgoing emails. Set to 0 to disable sending of attachments."
|
||||
|
||||
manual_polling_enabled: "Push emails using the API for email replies."
|
||||
pop3_polling_enabled: "Poll via POP3 for email replies."
|
||||
|
|
|
@ -1021,6 +1021,9 @@ email:
|
|||
enable_forwarded_emails: false
|
||||
always_show_trimmed_content: false
|
||||
private_email: false
|
||||
email_total_attachment_size_limit_kb:
|
||||
default: 0
|
||||
max: 51200
|
||||
|
||||
files:
|
||||
max_image_size_kb:
|
||||
|
|
|
@ -100,6 +100,8 @@ module Email
|
|||
# guards against deleted posts
|
||||
return skip(SkippedEmailLog.reason_types[:sender_post_deleted]) unless post
|
||||
|
||||
add_attachments(post)
|
||||
|
||||
topic = post.topic
|
||||
first_post = topic.ordered_posts.first
|
||||
|
||||
|
@ -239,6 +241,38 @@ module Email
|
|||
|
||||
private
|
||||
|
||||
def add_attachments(post)
|
||||
max_email_size = SiteSetting.email_total_attachment_size_limit_kb.kilobytes
|
||||
return if max_email_size == 0
|
||||
|
||||
email_size = 0
|
||||
post.uploads.each do |upload|
|
||||
next if FileHelper.is_supported_image?(upload.original_filename)
|
||||
next if email_size + upload.filesize > max_email_size
|
||||
|
||||
begin
|
||||
path = if upload.local?
|
||||
Discourse.store.path_for(upload)
|
||||
else
|
||||
Discourse.store.download(upload).path
|
||||
end
|
||||
|
||||
@message.attachments[upload.original_filename] = File.read(path)
|
||||
email_size += File.size(path)
|
||||
rescue => e
|
||||
Discourse.warn_exception(
|
||||
e,
|
||||
message: "Failed to attach file to email",
|
||||
env: {
|
||||
post_id: post.id,
|
||||
upload_id: upload.id,
|
||||
filename: upload.original_filename
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def header_value(name)
|
||||
header = @message.header[name]
|
||||
return nil unless header
|
||||
|
|
|
@ -351,6 +351,69 @@ describe Email::Sender do
|
|||
end
|
||||
end
|
||||
|
||||
context "with attachments" do
|
||||
fab!(:small_pdf) do
|
||||
SiteSetting.authorized_extensions = 'pdf'
|
||||
UploadCreator.new(file_from_fixtures("small.pdf", "pdf"), "small.pdf")
|
||||
.create_for(Discourse.system_user.id)
|
||||
end
|
||||
fab!(:large_pdf) do
|
||||
SiteSetting.authorized_extensions = 'pdf'
|
||||
UploadCreator.new(file_from_fixtures("large.pdf", "pdf"), "large.pdf")
|
||||
.create_for(Discourse.system_user.id)
|
||||
end
|
||||
fab!(:csv_file) do
|
||||
SiteSetting.authorized_extensions = 'csv'
|
||||
UploadCreator.new(file_from_fixtures("words.csv", "csv"), "words.csv")
|
||||
.create_for(Discourse.system_user.id)
|
||||
end
|
||||
fab!(:image) do
|
||||
SiteSetting.authorized_extensions = 'png'
|
||||
UploadCreator.new(file_from_fixtures("logo.png", "images"), "logo.png")
|
||||
.create_for(Discourse.system_user.id)
|
||||
end
|
||||
fab!(:post) { Fabricate(:post) }
|
||||
fab!(:reply) do
|
||||
raw = <<~RAW
|
||||
Hello world!
|
||||
#{DiscourseMarkdown.attachment_markdown(small_pdf)}
|
||||
#{DiscourseMarkdown.attachment_markdown(large_pdf)}
|
||||
#{DiscourseMarkdown.image_markdown(image)}
|
||||
#{DiscourseMarkdown.attachment_markdown(csv_file)}
|
||||
RAW
|
||||
reply = Fabricate(:post, raw: raw, topic: post.topic, user: Fabricate(:user))
|
||||
reply.link_post_uploads
|
||||
reply
|
||||
end
|
||||
fab!(:notification) { Fabricate(:posted_notification, user: post.user, post: reply) }
|
||||
let(:message) do
|
||||
UserNotifications.user_posted(
|
||||
post.user,
|
||||
post: reply,
|
||||
notification_type: notification.notification_type,
|
||||
notification_data_hash: notification.data_hash
|
||||
)
|
||||
end
|
||||
|
||||
it "adds only non-image uploads as attachments to the email" do
|
||||
SiteSetting.email_total_attachment_size_limit_kb = 10_000
|
||||
Email::Sender.new(message, :valid_type).send
|
||||
|
||||
expect(message.attachments.length).to eq(3)
|
||||
expect(message.attachments.map(&:filename))
|
||||
.to contain_exactly(*[small_pdf, large_pdf, csv_file].map(&:original_filename))
|
||||
end
|
||||
|
||||
it "respects the size limit and attaches only files that fit into the max email size" do
|
||||
SiteSetting.email_total_attachment_size_limit_kb = 40
|
||||
Email::Sender.new(message, :valid_type).send
|
||||
|
||||
expect(message.attachments.length).to eq(2)
|
||||
expect(message.attachments.map(&:filename))
|
||||
.to contain_exactly(*[small_pdf, csv_file].map(&:original_filename))
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a deleted post' do
|
||||
|
||||
it 'should skip sending the email' do
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue