From 08dc0e6ee62fbe63dfd6282b0d68d564ba174d26 Mon Sep 17 00:00:00 2001
From: Arpit Jalan <arpit@techapj.com>
Date: Sat, 25 Oct 2014 20:06:59 +0530
Subject: [PATCH] FIX: email replies to closed topic should not be accepted

---
 app/jobs/scheduled/poll_mailbox.rb     |  2 ++
 config/locales/server.en.yml           |  7 ++++++
 lib/email/receiver.rb                  |  2 ++
 spec/components/email/receiver_spec.rb | 31 ++++++++++++++++++++++++++
 spec/jobs/poll_mailbox_spec.rb         | 26 ++++++++++++++++++++-
 5 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/app/jobs/scheduled/poll_mailbox.rb b/app/jobs/scheduled/poll_mailbox.rb
index 6226461f1..d0f17b2bc 100644
--- a/app/jobs/scheduled/poll_mailbox.rb
+++ b/app/jobs/scheduled/poll_mailbox.rb
@@ -45,6 +45,8 @@ module Jobs
           message_template = :email_reject_reply_key
         when Email::Receiver::BadDestinationAddress
           message_template = :email_reject_destination
+        when Email::Receiver::TopicClosedError
+          message_template = :email_reject_topic_closed
         when ActiveRecord::Rollback
           message_template = :email_reject_post_error
         when Email::Receiver::InvalidPost
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index ac0b5543e..ca3dc4625 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1522,6 +1522,13 @@ en:
 
         None of the destination addresses are recognized. Please make sure that the site address is in the To: line (not Cc: or Bcc:), and that you are sending to the correct email address provided by staff.
 
+    email_reject_topic_closed:
+      subject_template: "Email issue -- Topic Closed"
+      text_body_template: |
+        We're sorry, but your email message to %{destination} (titled %{former_title}) didn't work.
+
+        The topic is closed. If you believe this is in error, contact a staff member.
+
     email_error_notification:
       subject_template: "Email issue -- POP authentication error"
       text_body_template: |
diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb
index 871fe8f9f..102683106 100644
--- a/lib/email/receiver.rb
+++ b/lib/email/receiver.rb
@@ -15,6 +15,7 @@ module Email
     class UserNotFoundError < ProcessingError; end
     class UserNotSufficientTrustLevelError < ProcessingError; end
     class BadDestinationAddress < ProcessingError; end
+    class TopicClosedError < ProcessingError; end
     class EmailLogNotFound < ProcessingError; end
     class InvalidPost < ProcessingError; end
 
@@ -68,6 +69,7 @@ module Email
         @email_log = dest_info[:obj]
 
         raise EmailLogNotFound if @email_log.blank?
+        raise TopicClosedError if Topic.find_by_id(@email_log.topic_id).closed?
 
         create_reply
       end
diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb
index f5484fa0b..93fb469e9 100644
--- a/spec/components/email/receiver_spec.rb
+++ b/spec/components/email/receiver_spec.rb
@@ -222,6 +222,37 @@ Pleasure to have you here!
 
   end
 
+  describe "posting reply to a closed topic" do
+    let(:reply_key) { raise "Override this in a lower describe block" }
+    let(:email_raw) { raise "Override this in a lower describe block" }
+    let(:receiver) { Email::Receiver.new(email_raw) }
+    let(:topic) { Fabricate(:topic, closed: true) }
+    let(:post) { Fabricate(:post, topic: topic, post_number: 1) }
+    let(:replying_user_email) { 'jake@adventuretime.ooo' }
+    let(:replying_user) { Fabricate(:user, email: replying_user_email, trust_level: 2) }
+    let(:email_log) { EmailLog.new(reply_key: reply_key,
+                                   post: post,
+                                   post_id: post.id,
+                                   topic_id: topic.id,
+                                   email_type: 'user_posted',
+                                   user: replying_user,
+                                   user_id: replying_user.id,
+                                   to_address: replying_user_email
+    ) }
+
+    before do
+      email_log.save
+    end
+
+    describe "should not create post" do
+      let!(:reply_key) { '59d8df8370b7e95c5a49fbf86aeb2c93' }
+      let!(:email_raw) { fixture_file("emails/valid_reply.eml") }
+      it "raises a TopicClosedError" do
+        expect { receiver.process }.to raise_error(Email::Receiver::TopicClosedError)
+      end
+    end
+  end
+
   describe "posting a new topic" do
     let(:category_destination) { raise "Override this in a lower describe block" }
     let(:email_raw) { raise "Override this in a lower describe block" }
diff --git a/spec/jobs/poll_mailbox_spec.rb b/spec/jobs/poll_mailbox_spec.rb
index aa4999b06..50a017f5e 100644
--- a/spec/jobs/poll_mailbox_spec.rb
+++ b/spec/jobs/poll_mailbox_spec.rb
@@ -207,6 +207,31 @@ describe Jobs::PollMailbox do
       end
     end
 
+    describe "when topic is closed" do
+      let(:email) { MockPop3EmailObject.new fixture_file('emails/valid_reply.eml')}
+      let(:topic) { Fabricate(:topic, closed: true) }
+      let(:first_post) { Fabricate(:post, topic: topic, post_number: 1)}
+
+      before do
+        first_post.save
+        EmailLog.create(to_address: 'jake@email.example.com',
+                        email_type: 'user_posted',
+                        reply_key: '59d8df8370b7e95c5a49fbf86aeb2c93',
+                        user: user,
+                        post: first_post,
+                        topic: topic)
+      end
+
+      describe "should not create post" do
+        it "raises a TopicClosedError" do
+          expect_exception Email::Receiver::TopicClosedError
+
+          poller.handle_mail(email)
+          email.should be_deleted
+        end
+      end
+    end
+
     describe "in failure conditions" do
 
       it "a valid reply without an email log raises an EmailLogNotFound error" do
@@ -233,7 +258,6 @@ describe Jobs::PollMailbox do
         email.should be_deleted
       end
 
-
     end
   end