mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 16:11:08 +08:00
FEATURE: support email attachments
This commit is contained in:
@ -3,8 +3,11 @@
|
||||
#
|
||||
|
||||
module Email
|
||||
|
||||
class Receiver
|
||||
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
class ProcessingError < StandardError; end
|
||||
class EmailUnparsableError < ProcessingError; end
|
||||
class EmptyEmailError < ProcessingError; end
|
||||
@ -18,28 +21,11 @@ module Email
|
||||
@raw = raw
|
||||
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
|
||||
end
|
||||
|
||||
category = Category.find_by_email(@message.to.first)
|
||||
return false if not category
|
||||
|
||||
@category_id = category.id
|
||||
@allow_strangers = category.email_in_allow_strangers
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
def process
|
||||
raise EmptyEmailError if @raw.blank?
|
||||
|
||||
@message = Mail.new(@raw)
|
||||
|
||||
|
||||
# First remove the known discourse stuff.
|
||||
parse_body
|
||||
raise EmptyEmailError if @body.blank?
|
||||
@ -48,18 +34,17 @@ module Email
|
||||
@body = EmailReplyParser.read(@body).visible_text.force_encoding('UTF-8')
|
||||
|
||||
discourse_email_parser
|
||||
|
||||
raise EmailUnparsableError if @body.blank?
|
||||
|
||||
if is_in_email?
|
||||
@user = User.find_by_email(@message.from.first)
|
||||
if @user.blank? and @allow_strangers
|
||||
if @user.blank? && @allow_strangers
|
||||
wrap_body_in_quote
|
||||
@user = Discourse.system_user
|
||||
end
|
||||
|
||||
raise UserNotFoundError if @user.blank?
|
||||
raise UserNotSufficientTrustLevelError.new @user if not @user.has_trust_level?(TrustLevel.levels[SiteSetting.email_in_min_trust.to_i])
|
||||
raise UserNotSufficientTrustLevelError.new @user unless @user.has_trust_level?(TrustLevel.levels[SiteSetting.email_in_min_trust.to_i])
|
||||
|
||||
create_new_topic
|
||||
else
|
||||
@ -81,12 +66,6 @@ module Email
|
||||
|
||||
private
|
||||
|
||||
def wrap_body_in_quote
|
||||
@body = "[quote=\"#{@message.from.first}\"]
|
||||
#{@body}
|
||||
[/quote]"
|
||||
end
|
||||
|
||||
def parse_body
|
||||
html = nil
|
||||
|
||||
@ -102,7 +81,7 @@ module Email
|
||||
|
||||
if @message.content_type =~ /text\/html/
|
||||
if defined? @message.charset
|
||||
html = @message.body.decoded.force_encoding(@message.charset).encode("UTF-8").to_s
|
||||
html = @message.body.decoded.force_encoding(@message.charset).encode("UTF-8").to_s
|
||||
else
|
||||
html = @message.body.to_s
|
||||
end
|
||||
@ -127,12 +106,11 @@ module Email
|
||||
# If we have an HTML message, strip the markup
|
||||
doc = Nokogiri::HTML(html)
|
||||
|
||||
# Blackberry is annoying in that it only provides HTML. We can easily
|
||||
# extract it though
|
||||
# Blackberry is annoying in that it only provides HTML. We can easily extract it though
|
||||
content = doc.at("#BB10_response_div")
|
||||
return content.text if content.present?
|
||||
|
||||
return doc.xpath("//text()").text
|
||||
doc.xpath("//text()").text
|
||||
end
|
||||
|
||||
def discourse_email_parser
|
||||
@ -154,35 +132,91 @@ module Email
|
||||
@body.strip!
|
||||
end
|
||||
|
||||
def create_reply
|
||||
# Try to post the body as a reply
|
||||
creator = PostCreator.new(email_log.user,
|
||||
raw: @body,
|
||||
topic_id: @email_log.topic_id,
|
||||
reply_to_post_number: @email_log.post.post_number,
|
||||
cooking_options: {traditional_markdown_linebreaks: true})
|
||||
def is_in_email?
|
||||
@allow_strangers = false
|
||||
|
||||
creator.create
|
||||
if SiteSetting.email_in && SiteSetting.email_in_address == @message.to.first
|
||||
@category_id = SiteSetting.email_in_category.to_i
|
||||
return true
|
||||
end
|
||||
|
||||
category = Category.find_by_email(@message.to.first)
|
||||
return false unless category
|
||||
|
||||
@category_id = category.id
|
||||
@allow_strangers = category.email_in_allow_strangers
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def wrap_body_in_quote
|
||||
@body = "[quote=\"#{@message.from.first}\"]
|
||||
#{@body}
|
||||
[/quote]"
|
||||
end
|
||||
|
||||
def create_reply
|
||||
create_post_with_attachments(email_log.user, @body, @email_log.topic_id, @email_log.post.post_number)
|
||||
end
|
||||
|
||||
def create_new_topic
|
||||
# Try to post the body as a reply
|
||||
topic_creator = TopicCreator.new(@user,
|
||||
Guardian.new(@user),
|
||||
category: @category_id,
|
||||
title: @message.subject)
|
||||
topic = TopicCreator.new(
|
||||
@user,
|
||||
Guardian.new(@user),
|
||||
category: @category_id,
|
||||
title: @message.subject,
|
||||
).create
|
||||
|
||||
topic = topic_creator.create
|
||||
post_creator = PostCreator.new(@user,
|
||||
raw: @body,
|
||||
topic_id: topic.id,
|
||||
cooking_options: {traditional_markdown_linebreaks: true})
|
||||
post = create_post_with_attachments(@user, @body, topic.id)
|
||||
|
||||
post_creator.create
|
||||
EmailLog.create(email_type: "topic_via_incoming_email",
|
||||
to_address: @message.to.first,
|
||||
topic_id: topic.id, user_id: @user.id)
|
||||
topic
|
||||
EmailLog.create(
|
||||
email_type: "topic_via_incoming_email",
|
||||
to_address: @message.to.first,
|
||||
topic_id: topic.id,
|
||||
user_id: @user.id,
|
||||
)
|
||||
|
||||
post
|
||||
end
|
||||
|
||||
def create_post_with_attachments(user, raw, topic_id, reply_to_post_number=nil)
|
||||
options = {
|
||||
raw: raw,
|
||||
topic_id: topic_id,
|
||||
cooking_options: { traditional_markdown_linebreaks: true },
|
||||
}
|
||||
options[:reply_to_post_number] = reply_to_post_number if reply_to_post_number
|
||||
|
||||
# deal with attachments
|
||||
@message.attachments.each do |attachment|
|
||||
tmp = Tempfile.new("discourse-email-attachment")
|
||||
begin
|
||||
# read attachment
|
||||
File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded }
|
||||
# create the upload for the user
|
||||
upload = Upload.create_for(user.id, tmp, attachment.filename, File.size(tmp))
|
||||
if upload && upload.errors.empty?
|
||||
# TODO: should use the same code as the client to insert attachments
|
||||
raw << "\n#{attachment_markdown(upload)}\n"
|
||||
end
|
||||
ensure
|
||||
tmp.close!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
create_post(user, options)
|
||||
end
|
||||
|
||||
def attachment_markdown(upload)if FileHelper.is_image?(upload.original_filename)
|
||||
"<img src='#{upload.url}' width='#{upload.width}' height='#{upload.height}'>"
|
||||
else
|
||||
"<a class='attachment' href='#{upload.url}'>#{upload.original_filename}</a> (#{number_to_human_size(upload.filesize)})"
|
||||
end
|
||||
end
|
||||
|
||||
def create_post(user, options)
|
||||
PostCreator.new(user, options).create
|
||||
end
|
||||
|
||||
end
|
||||
|
Reference in New Issue
Block a user