FEATURE: ability to send emails to a group

This commit is contained in:
Régis Hanol
2015-12-07 17:01:08 +01:00
parent f3c4ed706f
commit 1cde276656
5 changed files with 111 additions and 54 deletions

View File

@ -1,8 +1,5 @@
require_dependency 'new_post_manager'
require 'email/html_cleaner'
#
# Handles an incoming message
#
require_dependency 'email/html_cleaner'
module Email
@ -34,37 +31,32 @@ module Email
message = Mail.new(@raw)
body = parse_body message
body = parse_body(message)
dest_info = {type: :invalid, obj: nil}
dest_info = { type: :invalid, obj: nil }
message.to.each do |to_address|
if dest_info[:type] == :invalid
dest_info = check_address to_address
end
dest_info = check_address(to_address)
break if dest_info[:type] != :invalid
end
raise BadDestinationAddress if dest_info[:type] == :invalid
raise BadDestinationAddress if dest_info[:type] == :invalid
raise AutoGeneratedEmailError if message.header.to_s =~ /auto-generated/ || message.header.to_s =~ /auto-replied/
# TODO get to a state where we can remove this
@message = message
@body = body
if dest_info[:type] == :category
user_email = @message.from.first
@user = User.find_by_email(user_email)
case dest_info[:type]
when :group
raise BadDestinationAddress unless SiteSetting.email_in
category = dest_info[:obj]
@category_id = category.id
@allow_strangers = category.email_in_allow_strangers
group = dest_info[:obj]
user_email = @message.from.first
@user = User.find_by_email(user_email)
# create staged account when user doesn't exist
if @user.blank? && @allow_strangers
if @user.blank?
if SiteSetting.allow_staged_accounts
username = UserNameSuggester.suggest(user_email)
name = User.suggest_name(user_email)
@user = User.create(email: user_email, username: username, name: name, staged: true)
@user = create_staged_account(user_email)
else
wrap_body_in_quote(user_email)
@user = Discourse.system_user
@ -72,38 +64,67 @@ module Email
end
raise UserNotFoundError if @user.blank?
raise UserNotSufficientTrustLevelError.new @user unless @allow_strangers || @user.has_trust_level?(TrustLevel[SiteSetting.email_in_min_trust.to_i])
raise UserNotSufficientTrustLevelError.new(@user) unless @user.has_trust_level?(TrustLevel[SiteSetting.email_in_min_trust.to_i])
create_new_topic
else
create_new_topic(archetype: Archetype.private_message, target_group_names: [group.name])
when :category
raise BadDestinationAddress unless SiteSetting.email_in
category = dest_info[:obj]
if @user.blank? && category.email_in_allow_strangers
if SiteSetting.allow_staged_accounts
@user = create_staged_account(user_email)
else
wrap_body_in_quote(user_email)
@user = Discourse.system_user
end
end
raise UserNotFoundError if @user.blank?
raise UserNotSufficientTrustLevelError.new(@user) unless category.email_in_allow_strangers || @user.has_trust_level?(TrustLevel[SiteSetting.email_in_min_trust.to_i])
create_new_topic(category: category.id)
when :reply
@email_log = dest_info[:obj]
raise EmailLogNotFound if @email_log.blank?
raise EmailLogNotFound if @email_log.blank?
raise TopicNotFoundError if Topic.find_by_id(@email_log.topic_id).nil?
raise TopicClosedError if Topic.find_by_id(@email_log.topic_id).closed?
raise TopicClosedError if Topic.find_by_id(@email_log.topic_id).closed?
create_reply
end
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError => e
raise EmailUnparsableError.new(e)
end
def check_address(address)
category = Category.find_by_email(address)
return {type: :category, obj: category} if category
def create_staged_account(email)
User.create(
email: email,
username: UserNameSuggester.suggest(email),
name: User.suggest_name(email),
staged: true
)
end
regex = Regexp.escape SiteSetting.reply_by_email_address
def check_address(address)
group = Group.find_by_email(address)
return { type: :group, obj: group } if group
category = Category.find_by_email(address)
return { type: :category, obj: category } if category
regex = Regexp.escape(SiteSetting.reply_by_email_address)
regex = regex.gsub(Regexp.escape('%{reply_key}'), "(.*)")
regex = Regexp.new regex
regex = Regexp.new(regex)
match = regex.match address
if match && match[1].present?
reply_key = match[1]
email_log = EmailLog.for(reply_key)
return {type: :reply, obj: email_log}
return { type: :reply, obj: email_log }
end
{type: :invalid, obj: nil}
{ type: :invalid, obj: nil }
end
def parse_body(message)
@ -211,13 +232,13 @@ module Email
reply_to_post_number: @email_log.post.post_number)
end
def create_new_topic
result = create_post_with_attachments(@user,
raw: @body,
title: @message.subject,
category: @category_id)
def create_new_topic(topic_options={})
topic_options[:raw] = @body
topic_options[:title] = @message.subject
result = create_post_with_attachments(@user, topic_options)
topic_id = result.post.present? ? result.post.topic_id : nil
EmailLog.create(
email_type: "topic_via_incoming_email",
to_address: @message.from.first, # pick from address because we want the user's email
@ -228,10 +249,10 @@ module Email
result
end
def create_post_with_attachments(user, post_opts={})
def create_post_with_attachments(user, post_options={})
options = {
cooking_options: { traditional_markdown_linebreaks: true },
}.merge(post_opts)
}.merge(post_options)
raw = options[:raw]