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:
Bianca Nenciu 2022-08-18 18:18:58 +03:00 committed by GitHub
parent e49167b311
commit b082f459c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 0 deletions

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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