diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb
index f8fb71f5bd8..142e83d4e19 100644
--- a/lib/email/receiver.rb
+++ b/lib/email/receiver.rb
@@ -162,28 +162,38 @@ module Email
REPLYING_HEADER_LABELS = ['From', 'Sent', 'To', 'Subject', 'Reply To', 'Cc', 'Bcc', 'Date']
REPLYING_HEADER_REGEX = Regexp.union(REPLYING_HEADER_LABELS.map { |lbl| "#{lbl}:" })
+ def line_is_quote?(l)
+ l =~ /\A\s*\-{3,80}\s*\z/ ||
+ l =~ Regexp.new("\\A\\s*" + I18n.t('user_notifications.previous_discussion') + "\\s*\\Z") ||
+ (l =~ /via #{SiteSetting.title}(.*)\:$/) ||
+ # 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.
+ (l =~ /\d{4}/ && l =~ /\d:\d\d/ && l =~ /\:$/) ||
+ (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 if l =~ /\A\s*\-{3,80}\s*\z/ ||
- l =~ Regexp.new("\\A\\s*" + I18n.t('user_notifications.previous_discussion') + "\\s*\\Z") ||
- (l =~ /via #{SiteSetting.title}(.*)\:$/) ||
- # 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.
- (l =~ /\d{4}/ && l =~ /\d:\d\d/ && l =~ /\:$/) ||
- (l =~ /On \w+ \d+,? \d+,?.*wrote:/)
+ 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
break if (0..2).all? { |off| lines[idx+off] =~ REPLYING_HEADER_REGEX }
# Headers on the same line
break if REPLYING_HEADER_LABELS.count { |lbl| l.include? lbl } >= 3
-
- range_end = idx
+ range_end = range_start + idx
end
- lines[0..range_end].join.strip
+ lines[range_start..range_end].join.strip
end
def wrap_body_in_quote(user_email)
diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb
index 4b460b3ada4..82533078990 100644
--- a/spec/components/email/receiver_spec.rb
+++ b/spec/components/email/receiver_spec.rb
@@ -42,15 +42,13 @@ describe Email::Receiver do
end
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
expect(test_parse_body(fixture_file("emails/hebrew.eml"))).to eq("שלום")
end
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
expect(test_parse_body(fixture_file("emails/big5.eml"))).to eq("媽!我上電視了!")
end
@@ -149,12 +147,30 @@ the lazy dog. The quick brown fox jumps over the lazy dog."
)
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
- 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
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
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.last.cooked.strip).to eq(fixture_file("emails/paragraphs.cooked").strip)
- expect(topic.posts.last.cooked).not_to match /
/
+ expect(topic.posts.last.cooked).to match(//)
expect(Upload.find_by(sha1: upload_sha)).not_to eq(nil)
end
diff --git a/spec/fixtures/emails/inline_mixed.eml b/spec/fixtures/emails/inline_mixed.eml
new file mode 100644
index 00000000000..f8be9c7a548
--- /dev/null
+++ b/spec/fixtures/emails/inline_mixed.eml
@@ -0,0 +1,37 @@
+In-Reply-To:
+References:
+ <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
+To: Discourse
+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 wrote:
+
+> 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