mirror of
https://github.com/discourse/discourse.git
synced 2025-03-25 17:36:53 +08:00
FEATURE: Parse images in email signatures (#10137)
* FEATURE: Parse images in email signatures * DEV: Fix tests * Code review
This commit is contained in:
parent
07ad243603
commit
bd842cd2b0
app/services
lib/email
spec
@ -197,19 +197,23 @@ class InlineUploads
|
||||
end
|
||||
end
|
||||
|
||||
def self.match_img(markdown, external_src: false)
|
||||
def self.match_img(markdown, external_src: false, uploads: nil)
|
||||
markdown.scan(/(<(?!img)[^<>]+\/?>)?(\s*)(<img [^>\n]+>)/i) do |match|
|
||||
node = Nokogiri::HTML5::fragment(match[2].strip).children[0]
|
||||
src = node.attributes["src"]&.value
|
||||
|
||||
if src && (matched_uploads(src).present? || external_src)
|
||||
text = node.attributes["alt"]&.value
|
||||
width = node.attributes["width"]&.value.to_i
|
||||
height = node.attributes["height"]&.value.to_i
|
||||
upload = uploads&.[](src)
|
||||
|
||||
text = upload&.original_filename || node.attributes["alt"]&.value
|
||||
width = (node.attributes["width"]&.value || upload&.width).to_i
|
||||
height = (node.attributes["height"]&.value || upload&.height).to_i
|
||||
title = node.attributes["title"]&.value
|
||||
text = "#{text}|#{width}x#{height}" if width > 0 && height > 0
|
||||
url = upload&.short_url || PLACEHOLDER
|
||||
|
||||
spaces_before = match[1].present? ? match[1][/ +$/].size : 0
|
||||
replacement = +"#{" " * spaces_before}"
|
||||
replacement = +"#{" " * spaces_before}"
|
||||
|
||||
yield(match[2], src, replacement, $~.offset(0)[0]) if block_given?
|
||||
end
|
||||
|
@ -384,7 +384,8 @@ module Email
|
||||
|
||||
def to_markdown(html, elided_html)
|
||||
markdown = HtmlToMarkdown.new(html, keep_img_tags: true, keep_cid_imgs: true).to_markdown
|
||||
[EmailReplyTrimmer.trim(markdown), HtmlToMarkdown.new(elided_html).to_markdown]
|
||||
elided_markdown = HtmlToMarkdown.new(elided_html, keep_img_tags: true, keep_cid_imgs: true).to_markdown
|
||||
[EmailReplyTrimmer.trim(markdown), elided_markdown]
|
||||
end
|
||||
|
||||
HTML_EXTRACTERS ||= [
|
||||
@ -1032,6 +1033,7 @@ module Email
|
||||
end
|
||||
|
||||
def create_post_with_attachments(options = {})
|
||||
add_elided_to_raw!(options)
|
||||
options[:raw] = add_attachments(options[:raw], options[:user], options)
|
||||
create_post(options)
|
||||
end
|
||||
@ -1054,9 +1056,9 @@ module Email
|
||||
if raw[attachment.url]
|
||||
raw.sub!(attachment.url, upload.url)
|
||||
|
||||
InlineUploads.match_img(raw) do |match, src, replacement, _|
|
||||
InlineUploads.match_img(raw, uploads: { upload.url => upload }) do |match, src, replacement, _|
|
||||
if src == upload.url
|
||||
raw = raw.sub(match, UploadMarkdown.new(upload).image_markdown)
|
||||
raw = raw.sub(match, replacement)
|
||||
end
|
||||
end
|
||||
elsif raw[/\[image:.*?\d+[^\]]*\]/i]
|
||||
@ -1100,6 +1102,17 @@ module Email
|
||||
Email::Sender.new(client_message, :email_reject_attachment).send
|
||||
end
|
||||
|
||||
def add_elided_to_raw!(options)
|
||||
is_private_message = options[:archetype] == Archetype.private_message ||
|
||||
options[:topic].try(:private_message?)
|
||||
|
||||
# only add elided part in messages
|
||||
if options[:elided].present? && (SiteSetting.always_show_trimmed_content || is_private_message)
|
||||
options[:raw] << Email::Receiver.elided_html(options[:elided])
|
||||
options[:elided] = ""
|
||||
end
|
||||
end
|
||||
|
||||
def create_post(options = {})
|
||||
options[:via_email] = true
|
||||
options[:raw_email] = @raw_email
|
||||
@ -1107,13 +1120,7 @@ module Email
|
||||
options[:created_at] ||= @mail.date
|
||||
options[:created_at] = DateTime.now if options[:created_at] > DateTime.now
|
||||
|
||||
is_private_message = options[:archetype] == Archetype.private_message ||
|
||||
options[:topic].try(:private_message?)
|
||||
|
||||
# only add elided part in messages
|
||||
if options[:elided].present? && (SiteSetting.always_show_trimmed_content || is_private_message)
|
||||
options[:raw] << Email::Receiver.elided_html(options[:elided])
|
||||
end
|
||||
add_elided_to_raw!(options)
|
||||
|
||||
if sent_to_mailinglist_mirror?
|
||||
options[:skip_validations] = true
|
||||
|
@ -572,6 +572,27 @@ describe Email::Receiver do
|
||||
MD
|
||||
end
|
||||
|
||||
it "supports attached images in signature" do
|
||||
SiteSetting.incoming_email_prefer_html = true
|
||||
SiteSetting.always_show_trimmed_content = true
|
||||
|
||||
expect { process(:body_with_image) }.to change { topic.posts.count }
|
||||
|
||||
post = topic.posts.last
|
||||
upload = post.uploads.last
|
||||
|
||||
expect(post.raw).to eq(<<~MD.chomp)
|
||||
This is a **GMAIL** reply ;)
|
||||
|
||||
<details class='elided'>
|
||||
<summary title='Show trimmed content'>···</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
MD
|
||||
end
|
||||
|
||||
it "supports attachments" do
|
||||
SiteSetting.authorized_extensions = "txt|jpg"
|
||||
expect { process(:attached_txt_file) }.to change { topic.posts.count }
|
||||
|
87
spec/fixtures/emails/body_with_image.eml
vendored
Normal file
87
spec/fixtures/emails/body_with_image.eml
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
Return-Path: <discourse@bar.com>
|
||||
From: Foo Bar <discourse@bar.com>
|
||||
To: reply+4f97315cc828096c9cb34c6f1a0d6fe8@bar.com
|
||||
Date: Fri, 15 Jan 2016 00:12:43 +0100
|
||||
Message-ID: <6@foo.bar.mail>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="--==_mimepart_56990c8d3f66c_7cb53ffbb98602004746e";
|
||||
charset=UTF-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
----==_mimepart_56990c8d3f66c_7cb53ffbb98602004746e
|
||||
Content-Type: text/html; charset=UTF-8
|
||||
|
||||
<div>
|
||||
<div dir="auto">
|
||||
<p>This is a <b>GMAIL</b> reply ;)</p>
|
||||
</div>
|
||||
<div class="gmail_signature">
|
||||
<img src="cid:56990c92d6c64_7cb53ffbb986020047616@foo.bar.mail" width="300" height="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
----==_mimepart_56990c8d3f66c_7cb53ffbb98602004746e
|
||||
Content-Type: image/png;
|
||||
charset=UTF-8;
|
||||
filename=logo.png
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment;
|
||||
filename=logo.png
|
||||
Content-ID: <56990c92d6c64_7cb53ffbb986020047616@foo.bar.mail>
|
||||
|
||||
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
|
||||
YII=
|
||||
|
||||
----==_mimepart_56990c8d3f66c_7cb53ffbb98602004746e--
|
Loading…
x
Reference in New Issue
Block a user