Add public-inbox to Email-In-Feature

- Adds the advanced option to accept email from non-users per category email-address
 - Adds tests covering the new feature
 - Adds UI to configure this feature in the frontend
This commit is contained in:
Benjamin Kampmann 2014-02-27 16:36:33 +01:00
parent 37cea49459
commit d32cb55837
10 changed files with 118 additions and 2 deletions

View File

@ -67,6 +67,7 @@ Discourse.Category = Discourse.Model.extend({
auto_close_hours: this.get('auto_close_hours'),
position: this.get('position'),
email_in: this.get('email_in'),
email_in_allow_strangers: this.get('email_in_allow_strangers'),
parent_category_id: this.get('parent_category_id')
},
type: this.get('id') ? 'PUT' : 'POST'

View File

@ -113,6 +113,12 @@
{{i18n category.email_in}}
{{textField value=email_in}}
</div>
<div>
<label class="checkbox-label">
{{view Ember.Checkbox checkedBinding="email_in_allow_strangers"}}
{{i18n category.email_in_allow_strangers}}
</label>
</div>
</div>
</section>
{{/if}}

View File

@ -90,7 +90,7 @@ class CategoriesController < ApplicationController
end
end
params.permit(*required_param_keys, :position, :email_in, :parent_category_id, :auto_close_hours, :permissions => [*p.try(:keys)])
params.permit(*required_param_keys, :position, :email_in, :email_in_allow_strangers, :parent_category_id, :auto_close_hours, :permissions => [*p.try(:keys)])
end
end

View File

@ -6,6 +6,7 @@ class CategorySerializer < BasicCategorySerializer
:group_permissions,
:position,
:email_in,
:email_in_allow_strangers,
:can_delete
def group_permissions
@ -40,4 +41,8 @@ class CategorySerializer < BasicCategorySerializer
scope && scope.can_edit?(object)
end
def include_email_in_allow_strangers?
scope && scope.can_edit?(object)
end
end

View File

@ -1079,6 +1079,7 @@ en:
auto_close_label: "Auto-close topics after:"
auto_close_units: "hours"
email_in: "Custom incoming email address:"
email_in_allow_strangers: "Accept emails from non-users (aka strangers)"
edit_permissions: "Edit Permissions"
add_permission: "Add Permission"
this_year: "this year"

View File

@ -1,10 +1,12 @@
class AddCustomEmailInToCategories < ActiveRecord::Migration
def up
add_column :categories, :email_in, :string, null: true
add_column :categories, :email_in_allow_strangers, :boolean, default: false
add_index :categories, :email_in, unique: true
end
def down
remove_column :categories, :email_in
remove_column :categories, :email_in_allow_strangers
remove_index :categories, :email_in
end
end

View File

@ -13,6 +13,8 @@ Once that is in place, you can enable the "email_in"-feature globally in the sam
Once "email_in" is enabled globally a new configuration option appears in your category settings dialog allowing you to specify an email-address for that category. Emails going to the previously configured inbox to that email-address will be posted in this category instead of the default configuration. **Attention** User-Permissions and the minimum trust levels still apply.
Additionally, by checking the "accept non-user emails"-checkbox in the category settings, emails to the given email but from unknown email-addresses will be posted in the category by the System-User in a quoted fashion, showing the original email-address and content in the quotes.
### Troubleshooting
You might want to allow users to opt-in to receive all posts via email with the option on the bottom:

View File

@ -16,6 +16,7 @@ module Email
end
def is_in_email?
@allow_strangers = false
if SiteSetting.email_in and SiteSetting.email_in_address == @message.to.first
@category_id = SiteSetting.email_in_category.to_i
return true
@ -25,6 +26,7 @@ module Email
return false if not category
@category_id = category.id
@allow_strangers = category.email_in_allow_strangers
return true
end
@ -48,6 +50,11 @@ module Email
if is_in_email?
@user = User.find_by_email(@message.from.first)
if @user.blank? and @allow_strangers
wrap_body_in_quote
@user = Discourse.system_user
end
return Email::Receiver.results[:unprocessable] if @user.blank? or not @user.has_trust_level?(TrustLevel.levels[SiteSetting.email_in_min_trust.to_i])
create_new_topic
@ -75,6 +82,12 @@ module Email
private
def wrap_body_in_quote
@body = "[quote=\"#{@message.from.first}\"]
#{@body}
[/quote]"
end
def parse_body
html = nil

View File

@ -420,4 +420,91 @@ Jakie" }
end
describe "processes an unknown email sender to category" do
before do
SiteSetting.stubs(:email_in_address).returns("")
SiteSetting.stubs(:email_in_category).returns("42")
SiteSetting.stubs(:email_in).returns(true)
end
let(:incoming_email) { File.read("#{Rails.root}/spec/fixtures/emails/valid_incoming.eml") }
let(:receiver) { Email::Receiver.new(incoming_email) }
let(:non_inbox_email_category) { Fabricate.build(:category, id: 20, email_in_allow_strangers: false) }
let(:public_inbox_email_category) { Fabricate.build(:category, id: 25, email_in_allow_strangers: true) }
let(:subject) { "We should have a post-by-email-feature." }
let(:email_body) { "[quote=\"jake@adventuretime.ooo\"]
Hey folks,
I was thinking. Wouldn't it be great if we could post topics via email? Yes it would!
Jakie
[/quote]" }
describe "to disabled category" do
before do
User.expects(:find_by_email).with(
"jake@adventuretime.ooo").returns(nil)
Category.expects(:find_by_email).with(
"discourse-in@appmail.adventuretime.ooo").returns(non_inbox_email_category)
end
let!(:result) { receiver.process }
it "returns unprocessable" do
expect(result).to eq(Email::Receiver.results[:unprocessable])
end
end
describe "to enabled category" do
before do
User.expects(:find_by_email).with(
"jake@adventuretime.ooo").returns(nil)
Category.expects(:find_by_email).with(
"discourse-in@appmail.adventuretime.ooo").returns(public_inbox_email_category)
topic_creator = mock()
TopicCreator.expects(:new).with(Discourse.system_user,
instance_of(Guardian),
has_entries(title: subject,
category: 25)) # Make sure it is posted to the right category
.returns(topic_creator)
topic_creator.expects(:create).returns(topic_creator)
topic_creator.expects(:id).twice.returns(135)
post_creator = mock
PostCreator.expects(:new).with(Discourse.system_user,
has_entries(raw: email_body,
topic_id: 135,
cooking_options: {traditional_markdown_linebreaks: true}))
.returns(post_creator)
post_creator.expects(:create)
EmailLog.expects(:create).with(has_entries(
email_type: 'topic_via_incoming_email',
to_address: "discourse-in@appmail.adventuretime.ooo",
user_id: Discourse.system_user.id,
topic_id: 135
))
end
let!(:result) { receiver.process }
it "returns a processed result" do
expect(result).to eq(Email::Receiver.results[:processed])
end
it "extracts the body" do
expect(receiver.body).to eq(email_body)
end
end
end
end

View File

@ -2,4 +2,3 @@ Fabricator(:category) do
name { sequence(:name) { |n| "Amazing Category #{n}" } }
user
end