mirror of
https://github.com/discourse/discourse.git
synced 2024-11-27 18:33:37 +08:00
1de8361d2e
Currently processing emails that are blank or have a nil value for the mail will cause several errors. This update allows emails with blank body or missing sender to log the blank email error to the mail logs rather than throwing an error.
231 lines
7.3 KiB
Ruby
231 lines
7.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "email/processor"
|
|
|
|
RSpec.describe Email::Processor do
|
|
after { Discourse.redis.flushdb }
|
|
|
|
let(:from) { "foo@bar.com" }
|
|
|
|
context "when reply via email is too short" do
|
|
let(:mail) { file_from_fixtures("chinese_reply.eml", "emails").read }
|
|
fab!(:post) { Fabricate(:post) }
|
|
fab!(:user) { Fabricate(:user, email: "discourse@bar.com") }
|
|
|
|
fab!(:post_reply_key) do
|
|
Fabricate(
|
|
:post_reply_key,
|
|
user: user,
|
|
post: post,
|
|
reply_key: "4f97315cc828096c9cb34c6f1a0d6fe8",
|
|
)
|
|
end
|
|
|
|
before do
|
|
SiteSetting.email_in = true
|
|
SiteSetting.reply_by_email_address = "reply+%{reply_key}@bar.com"
|
|
SiteSetting.min_post_length = 1000
|
|
end
|
|
|
|
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 "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
|
|
|
|
it "sends a rejection email on an unrecognized error" do
|
|
begin
|
|
@orig_logger = Rails.logger
|
|
Rails.logger = @fake_logger = FakeLogger.new
|
|
|
|
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")
|
|
ensure
|
|
Rails.logger = @orig_logger
|
|
end
|
|
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 "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 do
|
|
SiteSetting.email_in = true
|
|
Fabricate(:mailinglist_mirror_category)
|
|
end
|
|
|
|
it "does not send rejection email" do
|
|
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) { Fabricate(:topic) }
|
|
fab!(:post) { Fabricate(:post, topic: topic, created_at: 3.days.ago) }
|
|
let(:mail) do
|
|
file_from_fixtures("old_destination.eml", "emails")
|
|
.read
|
|
.gsub("424242", topic.id.to_s)
|
|
.gsub("123456", 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
|
|
|
|
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
|