diff --git a/app/assets/javascripts/admin/templates/modal/admin_incoming_email.hbs b/app/assets/javascripts/admin/templates/modal/admin_incoming_email.hbs index d4907a7e322..6ba2b006f33 100644 --- a/app/assets/javascripts/admin/templates/modal/admin_incoming_email.hbs +++ b/app/assets/javascripts/admin/templates/modal/admin_incoming_email.hbs @@ -96,3 +96,15 @@ +{{#if model.rejection_message}} + +
+ +
+ +
+ {{textarea value=model.rejection_message}} +
+
+ +{{/if}} diff --git a/app/controllers/admin/email_controller.rb b/app/controllers/admin/email_controller.rb index 8ca208afb8d..33e8c376d1b 100644 --- a/app/controllers/admin/email_controller.rb +++ b/app/controllers/admin/email_controller.rb @@ -47,7 +47,7 @@ class Admin::EmailController < Admin::AdminController def handle_mail params.require(:email) - Email::Receiver.new(params[:email]).process + Email::Receiver.new(params[:email]).process! render text: "email was processed" end diff --git a/app/jobs/scheduled/poll_mailbox.rb b/app/jobs/scheduled/poll_mailbox.rb index 01ac885b443..26b8453eb57 100644 --- a/app/jobs/scheduled/poll_mailbox.rb +++ b/app/jobs/scheduled/poll_mailbox.rb @@ -23,9 +23,14 @@ module Jobs def process_popmail(popmail) begin mail_string = popmail.pop - Email::Receiver.new(mail_string).process + receiver = Email::Receiver.new(mail_string) + receiver.process! rescue => e - handle_failure(mail_string, e) + rejection_message = handle_failure(mail_string, e) + if rejection_message.present? && receiver && receiver.incoming_email + receiver.incoming_email.rejection_message = rejection_message.body.to_s + receiver.incoming_email.save + end end end @@ -49,6 +54,7 @@ module Jobs when ActiveRecord::Rollback then :email_reject_invalid_post when Email::Receiver::InvalidPostAction then :email_reject_invalid_post_action when Discourse::InvalidAccess then :email_reject_invalid_access + when RateLimiter::LimitExceeded then :email_reject_rate_limit_specified end template_args = {} @@ -59,6 +65,10 @@ module Jobs template_args[:post_error] = e.message end + if message_template == :email_reject_rate_limit_specified + template_args[:rate_limit_description] = e.description + end + if message_template # inform the user about the rejection message = Mail::Message.new(mail_string) @@ -68,6 +78,8 @@ module Jobs client_message = RejectionMailer.send_rejection(message_template, message.from, template_args) Email::Sender.new(client_message, message_template).send + + client_message else Discourse.handle_job_exception(e, error_context(@args, "Unrecognized error type when processing incoming email", mail: mail_string)) end diff --git a/app/serializers/incoming_email_details_serializer.rb b/app/serializers/incoming_email_details_serializer.rb index ac9e346caa5..0d8b8347798 100644 --- a/app/serializers/incoming_email_details_serializer.rb +++ b/app/serializers/incoming_email_details_serializer.rb @@ -2,6 +2,7 @@ class IncomingEmailDetailsSerializer < ApplicationSerializer attributes :error, :error_description, + :rejection_message, :return_path, :date, :from, diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index af4246d77da..065c7e9a0cd 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2296,6 +2296,7 @@ en: cc: "Cc" subject: "Subject" body: "Body" + rejection_message: "Rejection Mail" filters: from_placeholder: "from@example.com" to_placeholder: "to@example.com" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 35f537c9bb3..7811d97b0ec 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -406,11 +406,15 @@ en: first_day_topics_per_day: "You've reached the maximum number of topics a new user can create on their first day. Please wait %{time_left} before trying again." create_topic: "You're creating topics too quickly. Please wait %{time_left} before trying again." create_post: "You're replying too quickly. Please wait %{time_left} before trying again." + delete_post: "You're deleting posts too quickly. Please wait %{time_left} before trying again." topics_per_day: "You've reached the maximum number of new topics today. Please wait %{time_left} before trying again." pms_per_day: "You've reached the maximum number of messages today. Please wait %{time_left} before trying again." create_like: "You've reached the maximum number of likes today. Please wait %{time_left} before trying again." create_bookmark: "You've reached the maximum number of bookmarks today. Please wait %{time_left} before trying again." edit_post: "You've reached the maximun number of edits today. Please wait %{time_left} before trying again." + live_post_counts: "You've asking for live post counts too quickly. Please wait %{time_left} before trying again." + unsubscribe_via_email: "You've reached the maximum number of unsubscribe via email today. Please wait %{time_left} before trying again." + topic_invitations_per_day: "You've reached the maximum number of topic invitations today. Please wait %{time_left} before trying again." hours: one: "1 hour" @@ -1885,6 +1889,13 @@ en: 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: subject_template: "[%{site_name}] Email issue -- Invalid Post Action" text_body_template: | diff --git a/db/migrate/20160303234317_add_rejection_message_to_incoming_email.rb b/db/migrate/20160303234317_add_rejection_message_to_incoming_email.rb new file mode 100644 index 00000000000..da873df4035 --- /dev/null +++ b/db/migrate/20160303234317_add_rejection_message_to_incoming_email.rb @@ -0,0 +1,5 @@ +class AddRejectionMessageToIncomingEmail < ActiveRecord::Migration + def change + add_column :incoming_emails, :rejection_message, :text + end +end diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index fa7f81b912c..442fab9fad3 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -23,6 +23,8 @@ module Email class InvalidPost < ProcessingError; end class InvalidPostAction < ProcessingError; end + attr_reader :incoming_email + def initialize(mail_string) raise EmptyEmailError if mail_string.blank? @raw_email = mail_string @@ -30,7 +32,7 @@ module Email raise NoMessageIdError if @mail.message_id.blank? end - def process + def process! @from_email, @from_display_name = parse_from_field @incoming_email = find_or_create_incoming_email process_internal @@ -40,12 +42,12 @@ module Email end def find_or_create_incoming_email - IncomingEmail.find_or_create_by(message_id: @mail.message_id) do |incoming_email| - incoming_email.raw = @raw_email - incoming_email.subject = subject - incoming_email.from_address = @from_email - incoming_email.to_addresses = @mail.to.map(&:downcase).join(";") if @mail.to.present? - incoming_email.cc_addresses = @mail.cc.map(&:downcase).join(";") if @mail.cc.present? + IncomingEmail.find_or_create_by(message_id: @mail.message_id) do |ie| + ie.raw = @raw_email + ie.subject = subject + ie.from_address = @from_email + ie.to_addresses = @mail.to.map(&:downcase).join(";") if @mail.to.present? + ie.cc_addresses = @mail.cc.map(&:downcase).join(";") if @mail.cc.present? end end diff --git a/lib/rate_limiter/limit_exceeded.rb b/lib/rate_limiter/limit_exceeded.rb index ad7a000577b..b4a49e29182 100644 --- a/lib/rate_limiter/limit_exceeded.rb +++ b/lib/rate_limiter/limit_exceeded.rb @@ -9,7 +9,6 @@ class RateLimiter end def description - time_left = "" if @available_in < 1.minute.to_i time_left = I18n.t("rate_limiter.seconds", count: @available_in) @@ -20,7 +19,7 @@ class RateLimiter end if @type.present? - type_key = @type.gsub(/-/, '_') + type_key = @type.tr("-", "_") msg = I18n.t("rate_limiter.by_type.#{type_key}", time_left: time_left, default: "") return msg if msg.present? end diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index 734276c6a71..a559555f786 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -13,7 +13,7 @@ describe Email::Receiver do end def process(email_name) - Email::Receiver.new(email(email_name)).process + Email::Receiver.new(email(email_name)).process! end it "raises an EmptyEmailError when 'mail_string' is blank" do