mirror of
https://github.com/discourse/discourse.git
synced 2026-03-05 15:27:34 +08:00
DEV: email/receiver tests should explicitly test alternative_reply_by_email_addresses
Some of the email/receiver tests were using an alternative reply address in
their data, implicitly testing that functionality.
This commit modifies the test email fixtures to always use the main reply
address, and added a separate test explicitly testing the functionality of
`alternative_reply_by_email_addresses`.
This serves the mission of configuring as little as possible to not rely on
side effects.
DEV: email/processor tests should explicitly configure reply-by-email
Tests that rely on reply-by-email being configured should explicitly do so.
They're now moved to a common context in the same style as email/receiver
specs.
FIX: email to a category should not require enable reply-by-email
This commit removes the side effect of disabling category email address lookups
when `reply_by_email_enabled` is not configured, restoring functionality to the
situation where a category's `email_in` is configured without
`reply_by_email_enabled`.
Added tests for each of these situations.
DEV: separate tests for email receiver by whether reply_by_email should be configured
The impetus for this change is commit e05ef50c introducing an unintended side
effect that *should* have caused tests to fail; specifically the situation
where `email_in` is enabled and a category has an incoming email address
configured, but `reply_by_email_enabled` is *not* enabled.
The change in the referenced commit broke this configuration, but this was not
noticed as the spec always configured `reply_by_email_enabled`.
The only change made in this commit is reorganising the tests such that
reply-by-email is only configured when necessary. Thus, this commit *alone*
will break tests.
229 lines
7.5 KiB
Ruby
229 lines
7.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "email/processor"
|
|
|
|
RSpec.describe Email::Processor do
|
|
def configure_reply_by_email
|
|
SiteSetting.reply_by_email_address = "reply+%{reply_key}@bar.com"
|
|
SiteSetting.manual_polling_enabled = true
|
|
SiteSetting.reply_by_email_enabled = true
|
|
end
|
|
|
|
after { Discourse.redis.flushdb }
|
|
|
|
let(:from) { "foo@bar.com" }
|
|
|
|
context "with reply_by_email configured" do
|
|
before { configure_reply_by_email }
|
|
|
|
context "when reply via email is too short" do
|
|
let(:mail) { file_from_fixtures("chinese_reply.eml", "emails").read }
|
|
fab!(:post)
|
|
fab!(:user) { Fabricate(:user, email: "discourse@bar.com", refresh_auto_groups: true) }
|
|
|
|
fab!(:post_reply_key) do
|
|
Fabricate(
|
|
:post_reply_key,
|
|
user: user,
|
|
post: post,
|
|
reply_key: "4f97315cc828096c9cb34c6f1a0d6fe8",
|
|
)
|
|
end
|
|
|
|
before { SiteSetting.min_post_length = 1000 }
|
|
|
|
it "rejects reply and sends an email with custom error message" do
|
|
processor = Email::Processor.new(mail)
|
|
processor.process!
|
|
|
|
rejection_raw = ActionMailer::Base.deliveries.first.body.raw_source
|
|
|
|
count = SiteSetting.min_post_length
|
|
destination = processor.receiver.mail.to
|
|
former_title = processor.receiver.mail.subject
|
|
|
|
expect(rejection_raw.gsub(/\r/, "")).to eq(
|
|
I18n.t(
|
|
"system_messages.email_reject_post_too_short.text_body_template",
|
|
count: count,
|
|
destination: destination,
|
|
former_title: former_title,
|
|
).gsub(/\r/, ""),
|
|
)
|
|
end
|
|
end
|
|
describe "from reply to email address" do
|
|
let(:mail) do
|
|
"Date: Fri, 15 Jan 2016 00:12:43 +0100\nFrom: reply@bar.com\nTo: reply@bar.com\nSubject: FOO BAR\n\nFoo foo bar bar?"
|
|
end
|
|
|
|
it "ignores the email" do
|
|
Email::Receiver
|
|
.any_instance
|
|
.stubs(:process_internal)
|
|
.raises(Email::Receiver::FromReplyByAddressError.new)
|
|
|
|
expect { Email::Processor.process!(mail) }.not_to change { EmailLog.count }
|
|
end
|
|
end
|
|
|
|
describe "mailinglist mirror" do
|
|
before { Fabricate(:mailinglist_mirror_category) }
|
|
|
|
it "does not send rejection email" do
|
|
SiteSetting.email_in = true
|
|
|
|
Email::Receiver.any_instance.stubs(:process_internal).raises("boom")
|
|
|
|
email = <<~EMAIL
|
|
From: foo@example.com
|
|
To: list@example.com
|
|
Subject: Hello world
|
|
EMAIL
|
|
|
|
expect { Email::Processor.process!(email) }.to_not change { EmailLog.count }
|
|
end
|
|
end
|
|
|
|
describe "when replying to a post that is too old" do
|
|
fab!(:user) { Fabricate(:user, email: "discourse@bar.com") }
|
|
fab!(:topic)
|
|
fab!(:post) { Fabricate(:post, topic: topic, created_at: 3.days.ago) }
|
|
let(:mail) do
|
|
file_from_fixtures("old_destination.eml", "emails").read.gsub(":post_id", post.id.to_s)
|
|
end
|
|
|
|
it "rejects the email with the right response" do
|
|
SiteSetting.disallow_reply_by_email_after_days = 2
|
|
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_old_destination.text_body_template",
|
|
destination: '["reply+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com"]',
|
|
former_title: "Some Old Post",
|
|
short_url: "#{Discourse.base_url}/p/#{post.id}",
|
|
number_of_days: 2,
|
|
),
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "when mail is not set" do
|
|
it "does not raise an error" do
|
|
expect { Email::Processor.process!(nil) }.not_to raise_error
|
|
expect { Email::Processor.process!("") }.not_to raise_error
|
|
end
|
|
end
|
|
|
|
describe "rate limits" do
|
|
let(:mail) { "From: #{from}\nTo: bar@foo.com\nSubject: FOO BAR\n\nFoo foo bar bar?" }
|
|
let(:limit_exceeded) { RateLimiter::LimitExceeded.new(10) }
|
|
|
|
before { Email::Receiver.any_instance.expects(:process!).raises(limit_exceeded) }
|
|
|
|
it "enqueues a background job by default" do
|
|
expect_enqueued_with(job: :process_email, args: { mail: mail }) do
|
|
Email::Processor.process!(mail, retry_on_rate_limit: true)
|
|
end
|
|
end
|
|
|
|
it "doesn't enqueue a background job when retry is disabled" do
|
|
expect_not_enqueued_with(job: :process_email, args: { mail: mail }) do
|
|
expect { Email::Processor.process!(mail, retry_on_rate_limit: false) }.to raise_error(
|
|
limit_exceeded,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "known error" do
|
|
let(:mail) { "From: #{from}\nTo: bar@foo.com" }
|
|
let(:mail2) { "From: #{from}\nTo: foo@foo.com" }
|
|
let(:mail3) { "From: #{from}\nTo: foobar@foo.com" }
|
|
|
|
it "only sends one rejection email per day" do
|
|
key = "rejection_email:#{[from]}:email_reject_empty:#{Date.today}"
|
|
Discourse.redis.expire(key, 0)
|
|
|
|
expect { Email::Processor.process!(mail) }.to change { EmailLog.count }.by(1)
|
|
|
|
expect { Email::Processor.process!(mail2) }.not_to change { EmailLog.count }
|
|
|
|
freeze_time(Date.today + 1)
|
|
|
|
key = "rejection_email:#{[from]}:email_reject_empty:#{Date.today}"
|
|
Discourse.redis.expire(key, 0)
|
|
|
|
expect { Email::Processor.process!(mail3) }.to change { EmailLog.count }.by(1)
|
|
end
|
|
end
|
|
|
|
describe "unrecognized error" do
|
|
let(:mail) do
|
|
"Date: Fri, 15 Jan 2016 00:12:43 +0100\nFrom: #{from}\nTo: bar@foo.com\nSubject: FOO BAR\n\nFoo foo bar bar?"
|
|
end
|
|
let(:mail2) do
|
|
"Date: Fri, 15 Jan 2016 00:12:43 +0100\nFrom: #{from}\nTo: foo@foo.com\nSubject: BAR BAR\n\nBar bar bar bar?"
|
|
end
|
|
let(:fake_logger) { FakeLogger.new }
|
|
|
|
before { Rails.logger.broadcast_to(fake_logger) }
|
|
|
|
after { Rails.logger.stop_broadcasting_to(fake_logger) }
|
|
|
|
it "sends a rejection email on an unrecognized error" do
|
|
Email::Processor.any_instance.stubs(:can_send_rejection_email?).returns(true)
|
|
Email::Receiver.any_instance.stubs(:process_internal).raises("boom")
|
|
|
|
Email::Processor.process!(mail)
|
|
|
|
errors = fake_logger.errors
|
|
expect(errors.size).to eq(1)
|
|
expect(errors.first).to include("boom")
|
|
|
|
incoming_email = IncomingEmail.last
|
|
expect(incoming_email.error).to eq("RuntimeError")
|
|
expect(incoming_email.rejection_message).to be_present
|
|
|
|
expect(EmailLog.last.email_type).to eq("email_reject_unrecognized_error")
|
|
end
|
|
|
|
it "sends more than one rejection email per day" do
|
|
Email::Receiver.any_instance.stubs(:process_internal).raises("boom")
|
|
key = "rejection_email:#{[from]}:email_reject_unrecognized_error:#{Date.today}"
|
|
Discourse.redis.expire(key, 0)
|
|
|
|
expect { Email::Processor.process!(mail) }.to change { EmailLog.count }.by(1)
|
|
|
|
expect { Email::Processor.process!(mail2) }.to change { EmailLog.count }.by(1)
|
|
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
|