diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index fb8ba2c4e42..0f1294c2356 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -2438,6 +2438,14 @@ en: None of the destination email addresses are recognized, or the Message-ID header in the email has been modified. Please make sure that you are sending to the correct email address provided by staff. + email_reject_old_destination: + title: "Email Reject Old Destination" + subject_template: "[%{email_prefix}] Email issue -- You are trying to reply to an old notification" + text_body_template: | + We're sorry, but your email message to %{destination} (titled %{former_title}) didn't work. + + For security reasons we only accept replies to original notifications for 90 days. Please [visit the topic](%{short_url}) to continue the conversation. + email_reject_topic_not_found: title: "Email Reject Topic Not Found" subject_template: "[%{email_prefix}] Email issue -- Topic Not Found" diff --git a/lib/email/processor.rb b/lib/email/processor.rb index f212fef6678..b996dae6291 100644 --- a/lib/email/processor.rb +++ b/lib/email/processor.rb @@ -55,6 +55,7 @@ module Email 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 Email::Receiver::OldDestinationError then :email_reject_old_destination else :email_reject_unrecognized_error end @@ -75,6 +76,10 @@ module Email Rails.logger.error(msg) end + if message_template == :email_reject_old_destination + template_args[:short_url] = e.message + end + if message_template # inform the user about the rejection message = Mail::Message.new(mail_string) diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index 01d2be82836..06c9cb67618 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -33,6 +33,7 @@ module Email class InvalidPostAction < ProcessingError; end class UnsubscribeNotAllowed < ProcessingError; end class EmailNotAllowed < ProcessingError; end + class OldDestinationError < ProcessingError; end attr_reader :incoming_email attr_reader :raw_email @@ -42,8 +43,7 @@ module Email COMMON_ENCODINGS ||= [-"utf-8", -"windows-1252", -"iso-8859-1"] def self.formats - @formats ||= Enum.new(plaintext: 1, - markdown: 2) + @formats ||= Enum.new(plaintext: 1, markdown: 2) end def initialize(mail_string, opts = {}) @@ -163,7 +163,15 @@ module Email end end - raise first_exception || BadDestinationAddress + raise first_exception if first_exception + + if post = find_related_post(force: true) + if Guardian.new(user).can_see_post?(post) && post.created_at < 90.days.ago + raise OldDestinationError.new("#{Discourse.base_url}/p/#{post.id}") + end + end + + raise BadDestinationAddress end end @@ -728,8 +736,8 @@ module Email @category_email_in_regex ||= Regexp.union Category.pluck(:email_in).select(&:present?).map { |e| e.split("|") }.flatten.uniq end - def find_related_post - return if SiteSetting.find_related_post_with_key && !sent_to_mailinglist_mirror? + def find_related_post(force: false) + return if !force && SiteSetting.find_related_post_with_key && !sent_to_mailinglist_mirror? message_ids = Email::Receiver.extract_reply_message_ids(@mail, max_message_id_count: 5) return if message_ids.empty? diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index 5d9b217458e..9ded4025a72 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -78,6 +78,13 @@ describe Email::Receiver do expect { process(:bad_destinations) }.to raise_error(Email::Receiver::BadDestinationAddress) end + it "raises an OldDestinationError when notification is too old" do + topic = Fabricate(:topic, id: 424242) + post = Fabricate(:post, topic: topic, id: 123456, created_at: 1.year.ago) + + expect { process(:old_destination) }.to raise_error(Email::Receiver::OldDestinationError) + end + it "raises a BouncerEmailError when email is a bounced email" do expect { process(:bounced_email) }.to raise_error(Email::Receiver::BouncedEmailError) expect(IncomingEmail.last.is_bounce).to eq(true) diff --git a/spec/fixtures/emails/old_destination.eml b/spec/fixtures/emails/old_destination.eml new file mode 100644 index 00000000000..eb847ead444 --- /dev/null +++ b/spec/fixtures/emails/old_destination.eml @@ -0,0 +1,12 @@ +Return-Path: +From: Foo Bar +To: wat@bar.com +Cc: foofoo@bar.com +Date: Fri, 15 Jan 2018 00:12:43 +0100 +Message-ID: <999@foo.bar.mail> +In-Reply-To: +Mime-Version: 1.0 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +Lorem ipsum dolor sit amet, consectetur adipiscing elit.