mirror of
https://github.com/discourse/discourse.git
synced 2024-12-18 12:08:32 +08:00
dede942007
This PR introduces a few important changes to secure media redaction in emails. First of all, two new site settings have been introduced: * `secure_media_allow_embed_images_in_emails`: If enabled we will embed secure images in emails instead of redacting them. * `secure_media_max_email_embed_image_size_kb`: The cap to the size of the secure image we will embed, defaulting to 1mb, so the email does not become too big. Max is 10mb. Works in tandem with `email_total_attachment_size_limit_kb`. `Email::Sender` will now attach images to the email based on these settings. The sender will also call `inline_secure_images` in `Email::Styles` after secure media is redacted and attachments are added to replace redaction messages with attached images. I went with attachment and `cid` URLs because base64 image support is _still_ flaky in email clients. All redaction of secure media is now handled in `Email::Styles` and calls out to `PrettyText.strip_secure_media` to do the actual stripping and replacing with placeholders. `app/mailers/group_smtp_mailer.rb` and `app/mailers/user_notifications.rb` no longer do any stripping because they are earlier in the pipeline than `Email::Styles`. Finally the redaction notice has been restyled and includes a link to the media that the user can click, which will show it to them if they have the necessary permissions. ![image](https://user-images.githubusercontent.com/920448/92341012-b9a2c380-f0ff-11ea-860e-b376b4528357.png)
122 lines
3.7 KiB
Ruby
122 lines
3.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_dependency 'email/message_builder'
|
|
|
|
class GroupSmtpMailer < ActionMailer::Base
|
|
include Email::BuildEmailHelper
|
|
|
|
def send_mail(from_group, to_address, post)
|
|
raise 'SMTP is disabled' if !SiteSetting.enable_smtp
|
|
|
|
incoming_email = IncomingEmail.joins(:post)
|
|
.where('imap_uid IS NOT NULL')
|
|
.where(topic_id: post.topic_id, posts: { post_number: 1 })
|
|
.limit(1).first
|
|
|
|
context_posts = Post
|
|
.where(topic_id: post.topic_id)
|
|
.where("post_number < ?", post.post_number)
|
|
.where(user_deleted: false)
|
|
.where(hidden: false)
|
|
.where(post_type: Post.types[:regular])
|
|
.order(created_at: :desc)
|
|
.limit(SiteSetting.email_posts_context)
|
|
.to_a
|
|
|
|
delivery_options = {
|
|
address: from_group.smtp_server,
|
|
port: from_group.smtp_port,
|
|
domain: from_group.email_username.split('@').last,
|
|
user_name: from_group.email_username,
|
|
password: from_group.email_password,
|
|
authentication: GlobalSetting.smtp_authentication,
|
|
enable_starttls_auto: from_group.smtp_ssl
|
|
}
|
|
|
|
user_name = post.user.username
|
|
if SiteSetting.enable_names && SiteSetting.display_name_on_email_from
|
|
user_name = post.user.name unless post.user.name.blank?
|
|
end
|
|
|
|
build_email(to_address,
|
|
message: post.raw,
|
|
url: post.url(without_slug: SiteSetting.private_email?),
|
|
post_id: post.id,
|
|
topic_id: post.topic_id,
|
|
context: context(context_posts),
|
|
username: post.user.username,
|
|
group_name: from_group.name,
|
|
allow_reply_by_email: true,
|
|
only_reply_by_email: true,
|
|
private_reply: post.topic.private_message?,
|
|
participants: participants(post),
|
|
include_respond_instructions: true,
|
|
template: 'user_notifications.user_posted_pm',
|
|
use_topic_title_subject: true,
|
|
topic_title: incoming_email&.subject || post.topic.title,
|
|
add_re_to_subject: true,
|
|
locale: SiteSetting.default_locale,
|
|
delivery_method_options: delivery_options,
|
|
from: from_group.email_username,
|
|
from_alias: I18n.t('email_from', user_name: user_name, site_name: Email.site_title),
|
|
html_override: html_override(post, context_posts: context_posts)
|
|
)
|
|
end
|
|
|
|
private
|
|
|
|
def context(context_posts)
|
|
return "" if SiteSetting.private_email?
|
|
|
|
context = +""
|
|
|
|
if context_posts.size > 0
|
|
context << +"-- \n*#{I18n.t('user_notifications.previous_discussion')}*\n"
|
|
context_posts.each { |post| context << email_post_markdown(post, true) }
|
|
end
|
|
|
|
context
|
|
end
|
|
|
|
def email_post_markdown(post, add_posted_by = false)
|
|
result = +"#{post.raw}\n\n"
|
|
if add_posted_by
|
|
result << "#{I18n.t('user_notifications.posted_by', username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n"
|
|
end
|
|
result
|
|
end
|
|
|
|
def html_override(post, context_posts: nil)
|
|
UserNotificationRenderer.render(
|
|
template: 'email/notification',
|
|
format: :html,
|
|
locals: {
|
|
context_posts: context_posts,
|
|
reached_limit: nil,
|
|
post: post,
|
|
in_reply_to_post: post.reply_to_post,
|
|
classes: Rtl.new(nil).css_class,
|
|
first_footer_classes: ''
|
|
}
|
|
)
|
|
end
|
|
|
|
def participants(post)
|
|
list = []
|
|
|
|
post.topic.allowed_groups.each do |g|
|
|
list.push("[#{g.name} (#{g.users.count})](#{Discourse.base_url}/groups/#{g.name})")
|
|
end
|
|
|
|
post.topic.allowed_users.each do |u|
|
|
if SiteSetting.prioritize_username_in_ux?
|
|
list.push("[#{u.username}](#{Discourse.base_url}/u/#{u.username_lower})")
|
|
else
|
|
list.push("[#{u.name.blank? ? u.username : u.name}](#{Discourse.base_url}/u/#{u.username_lower})")
|
|
end
|
|
end
|
|
|
|
list.join(', ')
|
|
end
|
|
end
|