FEATURE: Limit maximum recipients for group emails (#17971)
New maximum_recipients_per_new_group_email site setting can be used to prevent spam group emails with many recipients.
This commit is contained in:
parent
e49167b311
commit
b082f459c9
|
@ -2043,6 +2043,7 @@ en:
|
|||
max_emails_per_day_per_user: "Maximum number of emails to send users per day. 0 to disable the limit"
|
||||
enable_staged_users: "Automatically create staged users when processing incoming emails."
|
||||
maximum_staged_users_per_email: "Maximum number of staged users created when processing an incoming email."
|
||||
maximum_recipients_per_new_group_email: "Block incoming emails with too many recipients."
|
||||
auto_generated_allowlist: "List of email addresses that won't be checked for auto-generated content. Example: foo@bar.com|discourse@bar.com"
|
||||
block_auto_generated_emails: "Block incoming emails identified as being auto generated."
|
||||
ignore_by_title: "Ignore incoming emails based on their title."
|
||||
|
@ -3359,6 +3360,16 @@ en:
|
|||
|
||||
If you believe this is an error, [contact a staff member](%{base_url}/about).
|
||||
|
||||
email_reject_too_many_recipients:
|
||||
title: "Email Reject Too Many Recipients"
|
||||
subject_template: "[%{email_prefix}] Email issue -- Too Many Recipients"
|
||||
text_body_template: |
|
||||
We're sorry, but your email message to %{destination} (titled %{former_title}) didn't work.
|
||||
|
||||
You attempted to email more than %{max_recipients_count} people and our system automatically tagged your email as spam.
|
||||
|
||||
If you believe this is an error, [contact a staff member](%{base_url}/about).
|
||||
|
||||
email_error_notification:
|
||||
title: "Email Error Notification"
|
||||
subject_template: "[%{email_prefix}] Email issue -- POP authentication error"
|
||||
|
|
|
@ -1202,6 +1202,9 @@ email:
|
|||
max_emails_per_day_per_user: 100
|
||||
enable_staged_users: true
|
||||
maximum_staged_users_per_email: 10
|
||||
maximum_recipients_per_new_group_email:
|
||||
default: 10
|
||||
min: 1
|
||||
auto_generated_allowlist:
|
||||
default: ""
|
||||
type: list
|
||||
|
|
|
@ -67,6 +67,7 @@ module Email
|
|||
when Email::Receiver::OldDestinationError then :email_reject_old_destination
|
||||
when Email::Receiver::ReplyNotAllowedError then :email_reject_reply_not_allowed
|
||||
when Email::Receiver::ReplyToDigestError then :email_reject_reply_to_digest
|
||||
when Email::Receiver::TooManyRecipientsError then :email_reject_too_many_recipients
|
||||
else :email_reject_unrecognized_error
|
||||
end
|
||||
|
||||
|
@ -96,6 +97,11 @@ module Email
|
|||
template_args[:number_of_days] = SiteSetting.disallow_reply_by_email_after_days
|
||||
end
|
||||
|
||||
if message_template == :email_reject_too_many_recipients
|
||||
template_args[:recipients_count] = e.recipients_count
|
||||
template_args[:max_recipients_count] = SiteSetting.maximum_recipients_per_new_group_email
|
||||
end
|
||||
|
||||
if message_template
|
||||
# inform the user about the rejection
|
||||
message = Mail::Message.new(mail_string)
|
||||
|
|
|
@ -33,6 +33,14 @@ module Email
|
|||
class OldDestinationError < ProcessingError; end
|
||||
class ReplyToDigestError < ProcessingError; end
|
||||
|
||||
class TooManyRecipientsError < ProcessingError
|
||||
attr_reader :recipients_count
|
||||
|
||||
def initialize(recipients_count:)
|
||||
@recipients_count = recipients_count
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :incoming_email
|
||||
attr_reader :raw_email
|
||||
attr_reader :mail
|
||||
|
@ -156,6 +164,11 @@ module Email
|
|||
raise UserNotFoundError unless SiteSetting.enable_staged_users
|
||||
end
|
||||
|
||||
recipients = get_all_recipients(@mail)
|
||||
if recipients.size > SiteSetting.maximum_recipients_per_new_group_email
|
||||
raise TooManyRecipientsError.new(recipients_count: recipients.size)
|
||||
end
|
||||
|
||||
body, elided = select_body
|
||||
body ||= ""
|
||||
|
||||
|
@ -230,6 +243,23 @@ module Email
|
|||
raise SilencedUserError if user.silenced?
|
||||
end
|
||||
|
||||
def get_all_recipients(mail)
|
||||
recipients = Set.new
|
||||
|
||||
%i(to cc bcc).each do |field|
|
||||
next if mail[field].blank?
|
||||
|
||||
mail[field].each do |address_field|
|
||||
begin
|
||||
address_field.decoded
|
||||
recipients << address_field.address.downcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
recipients
|
||||
end
|
||||
|
||||
def is_bounce?
|
||||
@mail.bounced? || bounce_key
|
||||
end
|
||||
|
|
|
@ -193,4 +193,26 @@ RSpec.describe Email::Processor do
|
|||
))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when group email recipients exceeds maximum_recipients_per_new_group_email site setting' do
|
||||
let(:mail) { file_from_fixtures("cc.eml", "emails").read }
|
||||
|
||||
it 'rejects the email with the right response' do
|
||||
SiteSetting.maximum_recipients_per_new_group_email = 3
|
||||
|
||||
processor = Email::Processor.new(mail)
|
||||
processor.process!
|
||||
|
||||
rejection_raw = ActionMailer::Base.deliveries.first.body.to_s
|
||||
|
||||
expect(rejection_raw).to eq(
|
||||
I18n.t("system_messages.email_reject_too_many_recipients.text_body_template",
|
||||
destination: '["someone@else.com"]',
|
||||
former_title: 'The more, the merrier',
|
||||
max_recipients_count: 3,
|
||||
base_url: Discourse.base_url,
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -883,6 +883,11 @@ RSpec.describe Email::Receiver do
|
|||
expect(Topic.last.ordered_posts[-1].post_type).to eq(Post.types[:moderator_action])
|
||||
end
|
||||
|
||||
it "rejects messages with too many recipients" do
|
||||
SiteSetting.maximum_recipients_per_new_group_email = 3
|
||||
expect { process(:cc) }.to raise_error(Email::Receiver::TooManyRecipientsError)
|
||||
end
|
||||
|
||||
describe "reply-to header" do
|
||||
before do
|
||||
SiteSetting.block_auto_generated_emails = false
|
||||
|
|
Loading…
Reference in New Issue