Skip to content

Commit

Permalink
FIX: Prevent critical emails bypassing disable, and improve email tes…
Browse files Browse the repository at this point in the history
…t logic

- The test_email job is removed, because it was always being run synchronously (not in sidekiq)
- 34b29f6 added a bypass for critical emails, to match the spec. This removes the bypass, and removes the spec.
- This adapts the specs for 72ffabf, so that they check for emails being sent
- This reimplements c279792, allowing test emails to be sent even when emails are disabled
  • Loading branch information
davidtaylorhq authored and tgxworld committed Mar 22, 2019
1 parent 48d0465 commit a9d5ffb
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 87 deletions.
12 changes: 4 additions & 8 deletions app/controllers/admin/email_controller.rb
Expand Up @@ -10,14 +10,10 @@ def index
def test
params.require(:email_address)
begin
Jobs::TestEmail.new.execute(to_address: params[:email_address])
if SiteSetting.disable_emails == "yes"
render json: { sent_test_email_message: I18n.t("admin.email.sent_test_disabled") }
elsif SiteSetting.disable_emails == "non-staff" && !User.find_by_email(params[:email_address])&.staff?
render json: { sent_test_email_message: I18n.t("admin.email.sent_test_disabled_for_non_staff") }
else
render json: { sent_test_email_message: I18n.t("admin.email.sent_test") }
end
message = TestMailer.send_test(params[:email_address])
Email::Sender.new(message, :test_message).send

render json: { sent_test_email_message: I18n.t("admin.email.sent_test") }
rescue => e
render json: { errors: [e.message] }, status: 422
end
Expand Down
20 changes: 0 additions & 20 deletions app/jobs/regular/test_email.rb

This file was deleted.

4 changes: 1 addition & 3 deletions app/jobs/regular/user_email.rb
Expand Up @@ -54,9 +54,7 @@ def execute(args)
)

if message
Email::Sender.new(message, type, user).send(
is_critical: self.class == Jobs::CriticalUserEmail
)
Email::Sender.new(message, type, user).send

if (b = user.user_stat.bounce_score) > SiteSetting.bounce_score_erode_on_send
# erode bounce score each time we send an email
Expand Down
2 changes: 0 additions & 2 deletions config/locales/server.en.yml
Expand Up @@ -2174,8 +2174,6 @@ en:
admin:
email:
sent_test: "sent!"
sent_test_disabled: "cannot send because emails are disabled"
sent_test_disabled_for_non_staff: "cannot send because emails are disabled for non-staff"

user:
deactivated: "Was deactivated due to too many bounced emails to '%{email}'."
Expand Down
10 changes: 5 additions & 5 deletions lib/email/sender.rb
Expand Up @@ -11,6 +11,7 @@
require 'net/smtp'

SMTP_CLIENT_ERRORS = [Net::SMTPFatalError, Net::SMTPSyntaxError]
BYPASS_DISABLE_TYPES = ["admin_login", "test_message"]

module Email
class Sender
Expand All @@ -21,11 +22,10 @@ def initialize(message, email_type, user = nil)
@user = user
end

def send(is_critical: false)
if SiteSetting.disable_emails == "yes" &&
@email_type.to_s != "admin_login" &&
!is_critical
def send
bypass_disable = BYPASS_DISABLE_TYPES.include?(@email_type.to_s)

if SiteSetting.disable_emails == "yes" && !bypass_disable
return
end

Expand All @@ -35,7 +35,7 @@ def send(is_critical: false)
return skip(SkippedEmailLog.reason_types[:sender_message_blank]) if @message.blank?
return skip(SkippedEmailLog.reason_types[:sender_message_to_blank]) if @message.to.blank?

if SiteSetting.disable_emails == "non-staff"
if SiteSetting.disable_emails == "non-staff" && !bypass_disable
return unless User.find_by_email(to_address)&.staff?
end

Expand Down
19 changes: 14 additions & 5 deletions spec/components/email/sender_spec.rb
Expand Up @@ -12,15 +12,24 @@
before { SiteSetting.disable_emails = "yes" }

it "doesn't deliver mail when mails are disabled" do
Mail::Message.any_instance.expects(:deliver_now).never
message = Mail::Message.new(to: moderator.email , body: "hello")
expect(Email::Sender.new(message, :hello).send).to eq(nil)
message = UserNotifications.email_login(moderator)
Email::Sender.new(message, :email_login).send

expect(ActionMailer::Base.deliveries).to eq([])
end

it "delivers mail when mails are disabled but the email_type is admin_login" do
Mail::Message.any_instance.expects(:deliver_now).once
message = Mail::Message.new(to: moderator.email , body: "hello")
message = UserNotifications.admin_login(moderator)
Email::Sender.new(message, :admin_login).send

expect(ActionMailer::Base.deliveries.first.to).to eq([moderator.email])
end

it "delivers mail when mails are disabled but the email_type is test_message" do
message = TestMailer.send_test(moderator.email)
Email::Sender.new(message, :test_message).send

expect(ActionMailer::Base.deliveries.first.to).to eq([moderator.email])
end
end

Expand Down
25 changes: 0 additions & 25 deletions spec/jobs/test_email_spec.rb

This file was deleted.

9 changes: 0 additions & 9 deletions spec/jobs/user_email_spec.rb
Expand Up @@ -80,15 +80,6 @@

expect(ActionMailer::Base.deliveries).to eq([])
end

it "sends when critical" do
SiteSetting.disable_emails = 'yes'
Jobs::CriticalUserEmail.new.execute(type: :confirm_new_email, user_id: user.id)

expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
user.email
)
end
end

context "recently seen" do
Expand Down
28 changes: 18 additions & 10 deletions spec/requests/admin/email_controller_spec.rb
Expand Up @@ -137,32 +137,40 @@
let(:eviltrout) { Fabricate(:evil_trout) }
let(:admin) { Fabricate(:admin) }

it 'does not sends mail to anyone when setting is "yes"' do
it 'bypasses disable when setting is "yes"' do
SiteSetting.disable_emails = 'yes'

post "/admin/email/test.json", params: { email_address: admin.email }

expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
admin.email
)

incoming = JSON.parse(response.body)
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test_disabled"))
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end

it 'sends mail to staff only when setting is "non-staff"' do
it 'bypasses disable when setting is "non-staff"' do
SiteSetting.disable_emails = 'non-staff'

post "/admin/email/test.json", params: { email_address: admin.email }
incoming = JSON.parse(response.body)
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))

post "/admin/email/test.json", params: { email_address: eviltrout.email }

expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)

incoming = JSON.parse(response.body)
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test_disabled_for_non_staff"))
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end

it 'sends mail to everyone when setting is "no"' do
it 'works when setting is "no"' do
SiteSetting.disable_emails = 'no'

post "/admin/email/test.json", params: { email_address: eviltrout.email }

expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)

incoming = JSON.parse(response.body)
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
Expand Down

1 comment on commit a9d5ffb

@discoursebot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/discourse-is-sending-emails-even-though-emailing-is-disabled/112231/11

Please sign in to comment.