2015-10-11 17:41:23 +08:00
|
|
|
require 'rails_helper'
|
2013-10-01 15:04:02 +08:00
|
|
|
require_dependency 'jobs/regular/process_post'
|
2013-06-14 06:11:10 +08:00
|
|
|
|
|
|
|
describe Jobs::PollMailbox do
|
|
|
|
|
2014-04-10 01:26:19 +08:00
|
|
|
let!(:poller) { Jobs::PollMailbox.new }
|
2013-06-14 06:11:10 +08:00
|
|
|
|
2014-04-10 01:26:19 +08:00
|
|
|
describe ".execute" do
|
|
|
|
|
2014-08-27 07:52:35 +08:00
|
|
|
it "does no polling if pop3_polling_enabled is false" do
|
|
|
|
SiteSetting.expects(:pop3_polling_enabled?).returns(false)
|
|
|
|
poller.expects(:poll_pop3).never
|
2014-04-10 01:26:19 +08:00
|
|
|
|
|
|
|
poller.execute({})
|
|
|
|
end
|
|
|
|
|
2014-08-27 07:52:35 +08:00
|
|
|
describe "with pop3_polling_enabled" do
|
2014-04-10 01:26:19 +08:00
|
|
|
|
2014-08-27 07:52:35 +08:00
|
|
|
it "calls poll_pop3" do
|
|
|
|
SiteSetting.expects(:pop3_polling_enabled?).returns(true)
|
|
|
|
poller.expects(:poll_pop3).once
|
2014-04-10 01:26:19 +08:00
|
|
|
|
|
|
|
poller.execute({})
|
|
|
|
end
|
|
|
|
end
|
2013-06-14 06:11:10 +08:00
|
|
|
|
|
|
|
end
|
|
|
|
|
2014-08-27 07:52:35 +08:00
|
|
|
describe ".poll_pop3" do
|
2014-04-10 01:26:19 +08:00
|
|
|
|
2014-07-01 06:16:16 +08:00
|
|
|
it "logs an error on pop authentication error" do
|
2014-04-10 01:26:19 +08:00
|
|
|
error = Net::POPAuthenticationError.new
|
|
|
|
data = { limit_once_per: 1.hour, message_params: { error: error }}
|
|
|
|
|
2014-08-27 08:00:27 +08:00
|
|
|
Net::POP3.any_instance.expects(:start).raises(error)
|
2014-07-01 06:16:16 +08:00
|
|
|
|
2015-02-10 04:47:46 +08:00
|
|
|
Discourse.expects(:handle_job_exception)
|
2014-04-10 01:26:19 +08:00
|
|
|
|
2014-08-27 07:52:35 +08:00
|
|
|
poller.poll_pop3
|
2014-04-10 01:26:19 +08:00
|
|
|
end
|
|
|
|
|
2014-08-27 08:00:27 +08:00
|
|
|
it "calls enable_ssl when the setting is enabled" do
|
|
|
|
SiteSetting.pop3_polling_ssl = true
|
|
|
|
Net::POP3.any_instance.stubs(:start)
|
|
|
|
Net::POP3.any_instance.expects(:enable_ssl)
|
|
|
|
|
|
|
|
poller.poll_pop3
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not call enable_ssl when the setting is off" do
|
|
|
|
SiteSetting.pop3_polling_ssl = false
|
|
|
|
Net::POP3.any_instance.stubs(:start)
|
|
|
|
Net::POP3.any_instance.expects(:enable_ssl).never
|
|
|
|
|
|
|
|
poller.poll_pop3
|
|
|
|
end
|
2014-04-10 01:26:19 +08:00
|
|
|
end
|
|
|
|
|
2014-08-02 02:03:03 +08:00
|
|
|
# Testing mock for the email objects that you get
|
|
|
|
# from Net::POP3.start { |pop| pop.mails }
|
|
|
|
class MockPop3EmailObject
|
|
|
|
def initialize(mail_string)
|
|
|
|
@message = mail_string
|
|
|
|
@delete_called = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
def pop
|
|
|
|
@message
|
|
|
|
end
|
|
|
|
|
|
|
|
def delete
|
|
|
|
@delete_called += 1
|
|
|
|
end
|
|
|
|
|
|
|
|
# call 'assert email.deleted?' at the end of the test
|
|
|
|
def deleted?
|
|
|
|
@delete_called == 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-02 02:03:55 +08:00
|
|
|
def expect_success
|
2014-08-02 03:40:28 +08:00
|
|
|
poller.expects(:handle_failure).never
|
|
|
|
end
|
|
|
|
|
|
|
|
def expect_exception(clazz)
|
|
|
|
poller.expects(:handle_failure).with(anything, instance_of(clazz))
|
2014-08-02 02:03:55 +08:00
|
|
|
end
|
|
|
|
|
2014-08-02 02:38:44 +08:00
|
|
|
describe "processing emails" do
|
2014-08-02 02:03:03 +08:00
|
|
|
let(:category) { Fabricate(:category) }
|
|
|
|
let(:user) { Fabricate(:user) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
SiteSetting.email_in = true
|
2014-08-02 03:40:28 +08:00
|
|
|
SiteSetting.reply_by_email_address = "reply+%{reply_key}@appmail.adventuretime.ooo"
|
|
|
|
category.email_in = 'incoming+amazing@appmail.adventuretime.ooo'
|
2014-08-02 02:03:03 +08:00
|
|
|
category.save
|
2014-09-05 13:20:39 +08:00
|
|
|
user.change_trust_level! 2
|
2014-08-02 02:03:03 +08:00
|
|
|
user.username = 'Jake'
|
2014-08-02 03:40:28 +08:00
|
|
|
user.email = 'jake@adventuretime.ooo'
|
2014-08-02 02:03:03 +08:00
|
|
|
user.save
|
|
|
|
end
|
|
|
|
|
2014-08-02 02:38:44 +08:00
|
|
|
describe "a valid incoming email" do
|
2014-08-02 03:40:28 +08:00
|
|
|
let(:email) {
|
|
|
|
# this string replacing is kinda dumb
|
|
|
|
str = fixture_file('emails/valid_incoming.eml')
|
|
|
|
str = str.gsub("FROM", 'jake@adventuretime.ooo').gsub("TO", 'incoming+amazing@appmail.adventuretime.ooo')
|
|
|
|
MockPop3EmailObject.new str
|
|
|
|
}
|
2014-08-02 02:03:03 +08:00
|
|
|
let(:expected_post) { fixture_file('emails/valid_incoming.cooked') }
|
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
it "posts a new topic with the correct content" do
|
2014-08-02 02:03:55 +08:00
|
|
|
expect_success
|
2014-08-02 02:03:03 +08:00
|
|
|
|
|
|
|
poller.handle_mail(email)
|
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
topic = Topic.where(category: category).where.not(id: category.topic_id).last
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic).to be_present
|
|
|
|
expect(topic.title).to eq("We should have a post-by-email-feature")
|
2014-08-02 03:40:28 +08:00
|
|
|
|
2014-08-02 02:03:03 +08:00
|
|
|
post = topic.posts.first
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(post.cooked.strip).to eq(expected_post.strip)
|
2014-08-02 02:03:03 +08:00
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-08-02 03:40:28 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "with insufficient trust" do
|
|
|
|
before do
|
2014-09-05 13:20:39 +08:00
|
|
|
user.change_trust_level! 0
|
2014-08-02 03:40:28 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it "raises a UserNotSufficientTrustLevelError" do
|
|
|
|
expect_exception Email::Receiver::UserNotSufficientTrustLevelError
|
|
|
|
|
|
|
|
poller.handle_mail(email)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "posts the topic if allow_strangers is true" do
|
|
|
|
begin
|
|
|
|
category.email_in_allow_strangers = true
|
|
|
|
category.save
|
|
|
|
|
|
|
|
expect_success
|
|
|
|
poller.handle_mail(email)
|
|
|
|
topic = Topic.where(category: category).where.not(id: category.topic_id).last
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(topic).to be_present
|
|
|
|
expect(topic.title).to eq("We should have a post-by-email-feature")
|
2014-08-02 03:40:28 +08:00
|
|
|
ensure
|
|
|
|
category.email_in_allow_strangers = false
|
|
|
|
category.save
|
|
|
|
end
|
|
|
|
end
|
2014-08-02 02:03:03 +08:00
|
|
|
end
|
2015-04-10 17:29:45 +08:00
|
|
|
|
|
|
|
describe "user in restricted group" do
|
|
|
|
|
|
|
|
it "raises InvalidAccess error" do
|
|
|
|
restricted_group = Fabricate(:group)
|
|
|
|
restricted_group.add(user)
|
|
|
|
restricted_group.save
|
|
|
|
|
|
|
|
category.set_permissions(restricted_group => :readonly)
|
|
|
|
category.save
|
|
|
|
|
|
|
|
expect_exception Discourse::InvalidAccess
|
|
|
|
|
|
|
|
poller.handle_mail(email)
|
|
|
|
expect(email).to be_deleted
|
|
|
|
end
|
|
|
|
end
|
2014-08-02 02:03:03 +08:00
|
|
|
end
|
|
|
|
|
2014-08-02 02:38:44 +08:00
|
|
|
describe "a valid reply" do
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:reply_key) { '59d8df8370b7e95c5a49fbf86aeb2c93' }
|
|
|
|
let(:to) { SiteSetting.reply_by_email_address.gsub("%{reply_key}", reply_key) }
|
|
|
|
let(:raw_email) { fill_email(fixture_file("emails/valid_reply.eml"), user.email, to) }
|
|
|
|
let(:email) { MockPop3EmailObject.new(raw_email) }
|
|
|
|
let(:expected_post) { fixture_file('emails/valid_reply.cooked') }
|
2014-08-02 02:03:03 +08:00
|
|
|
let(:topic) { Fabricate(:topic) }
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:first_post) { Fabricate(:post, user: user, topic: topic, post_number: 1) }
|
2014-08-02 02:03:03 +08:00
|
|
|
|
|
|
|
before do
|
|
|
|
first_post.save
|
2015-12-16 08:31:19 +08:00
|
|
|
EmailLog.create(to_address: user.email,
|
2014-08-02 02:03:03 +08:00
|
|
|
email_type: 'user_posted',
|
2015-12-16 08:31:19 +08:00
|
|
|
reply_key: reply_key,
|
2014-08-02 02:38:44 +08:00
|
|
|
user: user,
|
2014-08-02 02:03:03 +08:00
|
|
|
post: first_post,
|
|
|
|
topic: topic)
|
|
|
|
end
|
|
|
|
|
2014-08-02 02:38:44 +08:00
|
|
|
it "creates a new post" do
|
2014-08-02 02:03:55 +08:00
|
|
|
expect_success
|
2014-08-02 02:03:03 +08:00
|
|
|
|
|
|
|
poller.handle_mail(email)
|
|
|
|
|
2014-08-02 02:38:44 +08:00
|
|
|
new_post = Post.find_by(topic: topic, post_number: 2)
|
2014-08-02 02:03:03 +08:00
|
|
|
assert new_post.present?
|
|
|
|
assert_equal expected_post.strip, new_post.cooked.strip
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-08-02 02:03:03 +08:00
|
|
|
end
|
|
|
|
|
2014-08-14 02:06:17 +08:00
|
|
|
it "works with multiple To addresses" do
|
|
|
|
email = MockPop3EmailObject.new fixture_file('emails/multiple_destinations.eml')
|
|
|
|
expect_success
|
|
|
|
|
|
|
|
poller.handle_mail(email)
|
|
|
|
|
|
|
|
new_post = Post.find_by(topic: topic, post_number: 2)
|
|
|
|
assert new_post.present?
|
|
|
|
assert_equal expected_post.strip, new_post.cooked.strip
|
|
|
|
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-08-14 02:06:17 +08:00
|
|
|
end
|
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
describe "with the wrong reply key" do
|
2014-08-14 02:06:17 +08:00
|
|
|
let(:email) { MockPop3EmailObject.new fixture_file('emails/wrong_reply_key.eml') }
|
2014-08-02 02:38:44 +08:00
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
it "raises an EmailLogNotFound error" do
|
|
|
|
expect_exception Email::Receiver::EmailLogNotFound
|
2014-08-02 02:03:03 +08:00
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
poller.handle_mail(email)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-08-02 03:40:28 +08:00
|
|
|
end
|
2014-08-02 02:38:44 +08:00
|
|
|
end
|
|
|
|
end
|
2014-08-02 02:03:03 +08:00
|
|
|
|
2014-10-25 22:36:59 +08:00
|
|
|
describe "when topic is closed" do
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:reply_key) { '59d8df8370b7e95c5a49fbf86aeb2c93' }
|
|
|
|
let(:to) { SiteSetting.reply_by_email_address.gsub("%{reply_key}", reply_key) }
|
|
|
|
let(:raw_email) { fill_email(fixture_file("emails/valid_reply.eml"), user.email, to) }
|
|
|
|
let(:email) { MockPop3EmailObject.new(raw_email) }
|
2014-10-25 22:36:59 +08:00
|
|
|
let(:topic) { Fabricate(:topic, closed: true) }
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:first_post) { Fabricate(:post, user: user, topic: topic, post_number: 1) }
|
2014-10-25 22:36:59 +08:00
|
|
|
|
|
|
|
before do
|
|
|
|
first_post.save
|
2015-12-16 08:31:19 +08:00
|
|
|
EmailLog.create(to_address: user.email,
|
2014-10-25 22:36:59 +08:00
|
|
|
email_type: 'user_posted',
|
2015-12-16 08:31:19 +08:00
|
|
|
reply_key: reply_key,
|
2014-10-25 22:36:59 +08:00
|
|
|
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)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-10-25 22:36:59 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-27 14:58:31 +08:00
|
|
|
describe "when topic is deleted" do
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:reply_key) { '59d8df8370b7e95c5a49fbf86aeb2c93' }
|
|
|
|
let(:to) { SiteSetting.reply_by_email_address.gsub("%{reply_key}", reply_key) }
|
|
|
|
let(:raw_email) { fill_email(fixture_file("emails/valid_reply.eml"), user.email, to) }
|
|
|
|
let(:email) { MockPop3EmailObject.new(raw_email) }
|
2014-10-27 14:58:31 +08:00
|
|
|
let(:deleted_topic) { Fabricate(:deleted_topic) }
|
2015-12-16 08:31:19 +08:00
|
|
|
let(:first_post) { Fabricate(:post, user: user, topic: deleted_topic, post_number: 1)}
|
2014-10-27 14:58:31 +08:00
|
|
|
|
|
|
|
before do
|
|
|
|
first_post.save
|
2015-12-16 08:31:19 +08:00
|
|
|
EmailLog.create(to_address: user.email,
|
2014-10-27 14:58:31 +08:00
|
|
|
email_type: 'user_posted',
|
2015-12-16 08:31:19 +08:00
|
|
|
reply_key: reply_key,
|
2014-10-27 14:58:31 +08:00
|
|
|
user: user,
|
|
|
|
post: first_post,
|
|
|
|
topic: deleted_topic)
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "should not create post" do
|
|
|
|
it "raises a TopicNotFoundError" do
|
|
|
|
expect_exception Email::Receiver::TopicNotFoundError
|
|
|
|
|
|
|
|
poller.handle_mail(email)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-10-27 14:58:31 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
describe "in failure conditions" do
|
2014-04-10 01:26:19 +08:00
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
it "a valid reply without an email log raises an EmailLogNotFound error" do
|
2015-12-16 08:31:19 +08:00
|
|
|
to = SiteSetting.reply_by_email_address.gsub("%{reply_key}", '59d8df8370b7e95c5a49fbf86aeb2c93')
|
|
|
|
raw_email = fill_email(fixture_file("emails/valid_reply.eml"), user.email, to)
|
|
|
|
email = MockPop3EmailObject.new(raw_email)
|
2014-08-02 03:40:28 +08:00
|
|
|
expect_exception Email::Receiver::EmailLogNotFound
|
2014-04-10 01:26:19 +08:00
|
|
|
|
|
|
|
poller.handle_mail(email)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-04-10 01:26:19 +08:00
|
|
|
end
|
|
|
|
|
2014-08-27 08:08:53 +08:00
|
|
|
it "a no content reply raises an EmptyEmailError" do
|
2014-08-02 03:40:28 +08:00
|
|
|
email = MockPop3EmailObject.new fixture_file('emails/no_content_reply.eml')
|
2014-08-27 08:08:53 +08:00
|
|
|
expect_exception Email::Receiver::EmptyEmailError
|
2014-04-10 01:26:19 +08:00
|
|
|
|
|
|
|
poller.handle_mail(email)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-04-10 01:26:19 +08:00
|
|
|
end
|
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
it "a fully empty email raises an EmptyEmailError" do
|
|
|
|
email = MockPop3EmailObject.new fixture_file('emails/empty.eml')
|
|
|
|
expect_exception Email::Receiver::EmptyEmailError
|
2014-04-10 01:26:19 +08:00
|
|
|
|
2014-08-02 03:40:28 +08:00
|
|
|
poller.handle_mail(email)
|
2014-12-31 22:55:03 +08:00
|
|
|
expect(email).to be_deleted
|
2014-04-10 01:26:19 +08:00
|
|
|
end
|
|
|
|
|
2013-06-14 06:11:10 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|