FIX: Allow emails to begin with a quote (but skip it!)
This commit is contained in:
parent
85580cd243
commit
2196160549
|
@ -162,28 +162,38 @@ module Email
|
||||||
REPLYING_HEADER_LABELS = ['From', 'Sent', 'To', 'Subject', 'Reply To', 'Cc', 'Bcc', 'Date']
|
REPLYING_HEADER_LABELS = ['From', 'Sent', 'To', 'Subject', 'Reply To', 'Cc', 'Bcc', 'Date']
|
||||||
REPLYING_HEADER_REGEX = Regexp.union(REPLYING_HEADER_LABELS.map { |lbl| "#{lbl}:" })
|
REPLYING_HEADER_REGEX = Regexp.union(REPLYING_HEADER_LABELS.map { |lbl| "#{lbl}:" })
|
||||||
|
|
||||||
def discourse_email_trimmer(body)
|
def line_is_quote?(l)
|
||||||
lines = body.scrub.lines.to_a
|
l =~ /\A\s*\-{3,80}\s*\z/ ||
|
||||||
range_end = 0
|
|
||||||
|
|
||||||
lines.each_with_index do |l, idx|
|
|
||||||
break if l =~ /\A\s*\-{3,80}\s*\z/ ||
|
|
||||||
l =~ Regexp.new("\\A\\s*" + I18n.t('user_notifications.previous_discussion') + "\\s*\\Z") ||
|
l =~ Regexp.new("\\A\\s*" + I18n.t('user_notifications.previous_discussion') + "\\s*\\Z") ||
|
||||||
(l =~ /via #{SiteSetting.title}(.*)\:$/) ||
|
(l =~ /via #{SiteSetting.title}(.*)\:$/) ||
|
||||||
# This one might be controversial but so many reply lines have years, times and end with a colon.
|
# This one might be controversial but so many reply lines have years, times and end with a colon.
|
||||||
# Let's try it and see how well it works.
|
# Let's try it and see how well it works.
|
||||||
(l =~ /\d{4}/ && l =~ /\d:\d\d/ && l =~ /\:$/) ||
|
(l =~ /\d{4}/ && l =~ /\d:\d\d/ && l =~ /\:$/) ||
|
||||||
(l =~ /On \w+ \d+,? \d+,?.*wrote:/)
|
(l =~ /On [\w, ]+\d+.*wrote:/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def discourse_email_trimmer(body)
|
||||||
|
lines = body.scrub.lines.to_a
|
||||||
|
range_start = 0
|
||||||
|
range_end = 0
|
||||||
|
|
||||||
|
# If we started with a quote, skip it
|
||||||
|
lines.each_with_index do |l, idx|
|
||||||
|
break unless line_is_quote?(l) or l =~ /^>/ or l.blank?
|
||||||
|
range_start = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
lines[range_start..-1].each_with_index do |l, idx|
|
||||||
|
break if line_is_quote?(l)
|
||||||
|
|
||||||
# Headers on subsequent lines
|
# Headers on subsequent lines
|
||||||
break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX }
|
break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX }
|
||||||
# Headers on the same line
|
# Headers on the same line
|
||||||
break if REPLYING_HEADER_LABELS.count { |lbl| l.include? lbl } >= 3
|
break if REPLYING_HEADER_LABELS.count { |lbl| l.include? lbl } >= 3
|
||||||
|
range_end = range_start + idx
|
||||||
range_end = idx
|
|
||||||
end
|
end
|
||||||
|
|
||||||
lines[0..range_end].join.strip
|
lines[range_start..range_end].join.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
def wrap_body_in_quote(user_email)
|
def wrap_body_in_quote(user_email)
|
||||||
|
|
|
@ -42,15 +42,13 @@ describe Email::Receiver do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports a Hebrew reply" do
|
it "supports a Hebrew reply" do
|
||||||
I18n.expects(:t).with('user_notifications.previous_discussion').returns('כלטוב')
|
I18n.stubs(:t).with('user_notifications.previous_discussion').returns('כלטוב')
|
||||||
|
|
||||||
# The force_encoding call is only needed for the test - it is passed on fine to the cooked post
|
# The force_encoding call is only needed for the test - it is passed on fine to the cooked post
|
||||||
expect(test_parse_body(fixture_file("emails/hebrew.eml"))).to eq("שלום")
|
expect(test_parse_body(fixture_file("emails/hebrew.eml"))).to eq("שלום")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports a BIG5-encoded reply" do
|
it "supports a BIG5-encoded reply" do
|
||||||
I18n.expects(:t).with('user_notifications.previous_discussion').returns('媽!我上電視了!')
|
|
||||||
|
|
||||||
# The force_encoding call is only needed for the test - it is passed on fine to the cooked post
|
# The force_encoding call is only needed for the test - it is passed on fine to the cooked post
|
||||||
expect(test_parse_body(fixture_file("emails/big5.eml"))).to eq("媽!我上電視了!")
|
expect(test_parse_body(fixture_file("emails/big5.eml"))).to eq("媽!我上電視了!")
|
||||||
end
|
end
|
||||||
|
@ -149,12 +147,30 @@ the lazy dog. The quick brown fox jumps over the lazy dog."
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "can retrieve the first part of multiple replies" do
|
||||||
|
expect(test_parse_body(fixture_file("emails/inline_mixed.eml"))).to eq(
|
||||||
|
"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||||
|
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||||
|
|
||||||
|
> First paragraph.
|
||||||
|
>
|
||||||
|
> Second paragraph.
|
||||||
|
|
||||||
|
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown"
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
it "should not include previous replies" do
|
it "should not include previous replies" do
|
||||||
expect(test_parse_body(fixture_file("emails/previous_replies.eml"))).not_to match /Previous Replies/
|
expect(test_parse_body(fixture_file("emails/previous_replies.eml"))).not_to match(/Previous Replies/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "strips iPhone signature" do
|
it "strips iPhone signature" do
|
||||||
expect(test_parse_body(fixture_file("emails/iphone_signature.eml"))).not_to match /Sent from my iPhone/
|
expect(test_parse_body(fixture_file("emails/iphone_signature.eml"))).not_to match(/Sent from my iPhone/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "properly renders email reply from gmail web client" do
|
it "properly renders email reply from gmail web client" do
|
||||||
|
@ -288,7 +304,7 @@ This is a link http://example.com"
|
||||||
|
|
||||||
expect(topic.posts.count).to eq(start_count + 1)
|
expect(topic.posts.count).to eq(start_count + 1)
|
||||||
expect(topic.posts.last.cooked.strip).to eq(fixture_file("emails/paragraphs.cooked").strip)
|
expect(topic.posts.last.cooked.strip).to eq(fixture_file("emails/paragraphs.cooked").strip)
|
||||||
expect(topic.posts.last.cooked).not_to match /<br/
|
expect(topic.posts.last.cooked).not_to match(/<br/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -312,7 +328,7 @@ This is a link http://example.com"
|
||||||
receiver.process
|
receiver.process
|
||||||
|
|
||||||
expect(topic.posts.count).to eq(start_count + 1)
|
expect(topic.posts.count).to eq(start_count + 1)
|
||||||
expect(topic.posts.last.cooked).to match /<img src=['"](\/uploads\/default\/original\/.+\.png)['"] width=['"]289['"] height=['"]126['"]>/
|
expect(topic.posts.last.cooked).to match(/<img src=['"](\/uploads\/default\/original\/.+\.png)['"] width=['"]289['"] height=['"]126['"]>/)
|
||||||
expect(Upload.find_by(sha1: upload_sha)).not_to eq(nil)
|
expect(Upload.find_by(sha1: upload_sha)).not_to eq(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
In-Reply-To: <reply@discourse-app.mail>
|
||||||
|
References: <topic/36@discourse.techapj.com>
|
||||||
|
<5434ced4ee0f9_663fb0b5f76070593b@discourse-app.mail>
|
||||||
|
Date: Mon, 1 Dec 2014 20:48:40 +0530
|
||||||
|
Delivered-To: someone@googlemail.com
|
||||||
|
Subject: Re: [Discourse] [Meta] Testing reply via email
|
||||||
|
From: Walter White <walter.white@googlemail.com>
|
||||||
|
To: Discourse <reply@mail.com>
|
||||||
|
Content-Type: multipart/alternative; boundary=20cf30363f8522466905092920a6
|
||||||
|
|
||||||
|
--20cf30363f8522466905092920a6
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
|
||||||
|
On Wed, Oct 8, 2014 at 11:12 AM, techAPJ <info@unconfigured> wrote:
|
||||||
|
|
||||||
|
> techAPJ <https://meta.discourse.org/users/techapj>
|
||||||
|
> November 28
|
||||||
|
>
|
||||||
|
> Test reply.
|
||||||
|
>
|
||||||
|
> First paragraph.
|
||||||
|
>
|
||||||
|
> Second paragraph.
|
||||||
|
|
||||||
|
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||||
|
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog.
|
||||||
|
|
||||||
|
> First paragraph.
|
||||||
|
>
|
||||||
|
> Second paragraph.
|
||||||
|
|
||||||
|
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
|
||||||
|
the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
Loading…
Reference in New Issue