mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 15:48:43 -05:00
FEATURE: retry processing incoming emails on rate limit
This commit is contained in:
parent
5c06076b5c
commit
51322a46b3
5 changed files with 61 additions and 15 deletions
16
app/jobs/regular/process_email.rb
Normal file
16
app/jobs/regular/process_email.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Jobs
|
||||||
|
|
||||||
|
class ProcessEmail < Jobs::Base
|
||||||
|
sidekiq_options retry: 3
|
||||||
|
|
||||||
|
def execute(args)
|
||||||
|
Email::Processor.process!(args[:mail], false)
|
||||||
|
end
|
||||||
|
|
||||||
|
sidekiq_retries_exhausted do |msg|
|
||||||
|
Rails.logger.warn("Incoming email could not be processed after 3 retries.\n\n#{msg["args"][:mail]}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -2054,13 +2054,6 @@ en:
|
||||||
|
|
||||||
If you can correct the problem, please try again.
|
If you can correct the problem, please try again.
|
||||||
|
|
||||||
email_reject_rate_limit_specified:
|
|
||||||
subject_template: "[%{site_name}] Email issue -- Rate limited"
|
|
||||||
text_body_template: |
|
|
||||||
We're sorry, but your email message to %{destination} (titled %{former_title}) didn't work.
|
|
||||||
|
|
||||||
Reason: %{rate_limit_description}
|
|
||||||
|
|
||||||
email_reject_invalid_post_action:
|
email_reject_invalid_post_action:
|
||||||
subject_template: "[%{site_name}] Email issue -- Invalid Post Action"
|
subject_template: "[%{site_name}] Email issue -- Invalid Post Action"
|
||||||
text_body_template: |
|
text_body_template: |
|
||||||
|
|
|
@ -2,18 +2,21 @@ module Email
|
||||||
|
|
||||||
class Processor
|
class Processor
|
||||||
|
|
||||||
def initialize(mail)
|
def initialize(mail, retry_on_rate_limit=true)
|
||||||
@mail = mail
|
@mail = mail
|
||||||
|
@retry_on_rate_limit = retry_on_rate_limit
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.process!(mail)
|
def self.process!(mail, retry_on_rate_limit=true)
|
||||||
Email::Processor.new(mail).process!
|
Email::Processor.new(mail, retry_on_rate_limit).process!
|
||||||
end
|
end
|
||||||
|
|
||||||
def process!
|
def process!
|
||||||
begin
|
begin
|
||||||
receiver = Email::Receiver.new(@mail)
|
receiver = Email::Receiver.new(@mail)
|
||||||
receiver.process!
|
receiver.process!
|
||||||
|
rescue RateLimiter::LimitExceeded
|
||||||
|
@retry_on_rate_limit ? Jobs.enqueue(:process_email, mail: @mail) : raise
|
||||||
rescue Email::Receiver::BouncedEmailError => e
|
rescue Email::Receiver::BouncedEmailError => e
|
||||||
# never reply to bounced emails
|
# never reply to bounced emails
|
||||||
log_email_process_failure(@mail, e)
|
log_email_process_failure(@mail, e)
|
||||||
|
@ -49,7 +52,6 @@ module Email
|
||||||
when ActiveRecord::Rollback then :email_reject_invalid_post
|
when ActiveRecord::Rollback then :email_reject_invalid_post
|
||||||
when Email::Receiver::InvalidPostAction then :email_reject_invalid_post_action
|
when Email::Receiver::InvalidPostAction then :email_reject_invalid_post_action
|
||||||
when Discourse::InvalidAccess then :email_reject_invalid_access
|
when Discourse::InvalidAccess then :email_reject_invalid_access
|
||||||
when RateLimiter::LimitExceeded then :email_reject_rate_limit_specified
|
|
||||||
end
|
end
|
||||||
|
|
||||||
template_args = {}
|
template_args = {}
|
||||||
|
@ -61,10 +63,6 @@ module Email
|
||||||
template_args[:post_error] = e.message
|
template_args[:post_error] = e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
if message_template == :email_reject_rate_limit_specified
|
|
||||||
template_args[:rate_limit_description] = e.description
|
|
||||||
end
|
|
||||||
|
|
||||||
if message_template
|
if message_template
|
||||||
# inform the user about the rejection
|
# inform the user about the rejection
|
||||||
message = Mail::Message.new(mail_string)
|
message = Mail::Message.new(mail_string)
|
||||||
|
|
27
spec/components/email/processor_spec.rb
Normal file
27
spec/components/email/processor_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
require "rails_helper"
|
||||||
|
require "email/processor"
|
||||||
|
|
||||||
|
describe Email::Processor do
|
||||||
|
|
||||||
|
describe "rate limits" do
|
||||||
|
|
||||||
|
let(:mail) { "From: foo@bar.com\nTo: bar@foo.com\nSubject: FOO BAR\n\nFoo foo bar bar?" }
|
||||||
|
let(:limit_exceeded) { RateLimiter::LimitExceeded.new(10) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Email::Receiver.any_instance.expects(:process!).raises(limit_exceeded)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "enqueues a background job by default" do
|
||||||
|
Jobs.expects(:enqueue).with(:process_email, mail: mail)
|
||||||
|
Email::Processor.process!(mail)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't enqueue a background job when retry is disabled" do
|
||||||
|
Jobs.expects(:enqueue).with(:process_email, mail: mail).never
|
||||||
|
expect { Email::Processor.process!(mail, false) }.to raise_error(limit_exceeded)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
12
spec/jobs/process_email_spec.rb
Normal file
12
spec/jobs/process_email_spec.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe Jobs::ProcessEmail do
|
||||||
|
|
||||||
|
let(:mail) { "From: foo@bar.com\nTo: bar@foo.com\nSubject: FOO BAR\n\nFoo foo bar bar?" }
|
||||||
|
|
||||||
|
it "process an email without retry" do
|
||||||
|
Email::Processor.expects(:process!).with(mail, false)
|
||||||
|
Jobs::ProcessEmail.new.execute(mail: mail)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue