email_reply_trimmer 0.1.12 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +78 -17
  4. data/README.md +4 -4
  5. data/Rakefile +3 -6
  6. data/devenv.lock +184 -0
  7. data/devenv.nix +4 -0
  8. data/devenv.yaml +8 -0
  9. data/email_reply_trimmer.gemspec +4 -2
  10. data/lib/email_reply_trimmer/delimiter_matcher.rb +3 -2
  11. data/lib/email_reply_trimmer/email_header_matcher.rb +6 -5
  12. data/lib/email_reply_trimmer/embedded_email_matcher.rb +3 -2
  13. data/lib/email_reply_trimmer/empty_line_matcher.rb +1 -0
  14. data/lib/email_reply_trimmer/quote_matcher.rb +1 -0
  15. data/lib/email_reply_trimmer/signature_matcher.rb +2 -1
  16. data/lib/email_reply_trimmer.rb +83 -53
  17. data/test/before/forwarded_apple.txt +1 -0
  18. data/test/before/forwarded_gmail.txt +1 -0
  19. data/test/elided/block_code_spacers.txt +0 -0
  20. data/test/elided/forwarded_apple.txt +15 -0
  21. data/test/elided/forwarded_gmail.txt +15 -0
  22. data/test/elided/spam_1.txt +75 -0
  23. data/test/elided/spam_2.txt +152 -0
  24. data/test/emails/block_code_spacers.txt +13 -0
  25. data/test/emails/forwarded_apple.txt +17 -0
  26. data/test/emails/forwarded_gmail.txt +17 -0
  27. data/test/emails/spam_1.txt +75 -0
  28. data/test/emails/spam_2.txt +174 -0
  29. data/test/embedded/forwarded_apple.txt +13 -0
  30. data/test/embedded/forwarded_gmail.txt +14 -0
  31. data/test/test_email_matcher.rb +1 -0
  32. data/test/test_email_reply_trimmer.rb +6 -1
  33. data/test/trimmed/block_code_spacers.txt +13 -0
  34. data/test/trimmed/forwarded_apple.txt +1 -0
  35. data/test/trimmed/forwarded_gmail.txt +1 -0
  36. data/test/trimmed/spam_1.txt +0 -0
  37. data/test/trimmed/spam_2.txt +21 -0
  38. metadata +47 -12
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  require_relative "email_reply_trimmer/empty_line_matcher"
2
3
  require_relative "email_reply_trimmer/delimiter_matcher"
3
4
  require_relative "email_reply_trimmer/signature_matcher"
4
5
  require_relative "email_reply_trimmer/embedded_email_matcher"
5
6
  require_relative "email_reply_trimmer/email_header_matcher"
6
7
  require_relative "email_reply_trimmer/quote_matcher"
8
+ require 'securerandom'
7
9
 
8
10
  class EmailReplyTrimmer
9
- VERSION = "0.1.12"
11
+ VERSION = "0.2.0"
10
12
 
11
13
  DELIMITER = "d"
12
14
  EMBEDDED = "b"
@@ -23,7 +25,7 @@ class EmailReplyTrimmer
23
25
  return EMBEDDED if EmbeddedEmailMatcher.match? line
24
26
  return EMAIL_HEADER if EmailHeaderMatcher.match? line
25
27
  return QUOTE if QuoteMatcher.match? line
26
- return TEXT
28
+ TEXT
27
29
  end
28
30
 
29
31
  def self.trim(text, split = false)
@@ -32,11 +34,14 @@ class EmailReplyTrimmer
32
34
  # do some cleanup
33
35
  preprocess!(text)
34
36
 
37
+ # stash the code blocks - replace them with hashes
38
+ text, blocks = hoist_code_blocks(text)
39
+
35
40
  # from now on, we'll work on a line-by-line basis
36
41
  lines = text.split("\n")
37
42
  lines_dup = lines.dup
38
43
 
39
- # identify content of each lines
44
+ # create a string of characters, one per line, according to the line content
40
45
  pattern = lines.map { |l| identify_line_content(l) }.join
41
46
 
42
47
  # remove everything after the first delimiter
@@ -54,7 +59,7 @@ class EmailReplyTrimmer
54
59
  end
55
60
 
56
61
  # when the reply is at the end of the email
57
- if pattern =~ /^(b[^t]+)*b[bqeh]+t[et]*$/
62
+ if is_reply_at_end?(pattern)
58
63
  index = pattern =~ /t[et]*$/
59
64
  pattern = ""
60
65
  lines = lines[index..-1]
@@ -78,8 +83,8 @@ class EmailReplyTrimmer
78
83
 
79
84
  # if there is some text before a huge quote ending the email,
80
85
  # then remove the quote
81
- if pattern =~ /te*[qbe]+$/
82
- index = pattern =~ /te*[qbe]+$/
86
+ if pattern =~ /t?e*[qbe]+$/
87
+ index = pattern =~ /t?e*[qbe]+$/
83
88
  pattern = pattern[0..index]
84
89
  lines = lines[0..index]
85
90
  end
@@ -123,6 +128,9 @@ class EmailReplyTrimmer
123
128
  # results
124
129
  trimmed = lines.join("\n").strip
125
130
 
131
+ # re-inject code blocks
132
+ blocks.each { |token, block| trimmed.gsub!(token, block) }
133
+
126
134
  if split
127
135
  [trimmed, compute_elided(lines_dup, lines)]
128
136
  else
@@ -144,66 +152,88 @@ class EmailReplyTrimmer
144
152
 
145
153
  if index = pattern =~ /(?:h[eqd]*?){3,}[tq]/
146
154
  embedded = lines[index..-1].join("\n").strip
155
+ elsif index = pattern =~ /b(?:[eqd]*){3,}[tq]/
156
+ # Exception for email clients (macOS / iOS) which embed fwd emails in quotes.
157
+ embedded = lines[index + 1..-1].map { |l| l.gsub(/^>\s*/, '') }.join("\n").strip
158
+ end
159
+
160
+ if index
147
161
  before = lines[0...(pattern[0...index] =~ /e*(b[eqd]*|b*[ed]*)$/)].join("\n").strip
148
- return [embedded, before]
162
+ [embedded, before]
149
163
  end
150
164
  end
151
165
 
152
166
  private
153
167
 
154
- def self.preprocess!(text)
155
- # normalize line endings
156
- text.gsub!("\r\n", "\n")
157
-
158
- # remove PGP markers
159
- text.gsub!(/\A-----BEGIN PGP SIGNED MESSAGE-----\n(?:Hash: \w+)?\s+/i, "")
160
- text.gsub!(/^-----BEGIN PGP SIGNATURE-----$[\s\S]+^-----END PGP SIGNATURE-----/, "")
161
-
162
- # remove unsubscribe links
163
- text.gsub!(/^Unsubscribe: .+@.+(\n.+http:.+)?\s*\z/i, "")
164
-
165
- # remove alias-style quotes marker
166
- text.gsub!(/^.*>{5} "[^"\n]+" == .+ writes:/, "")
167
-
168
- # change enclosed-style quotes format
169
- text.gsub!(/^>>> ?(.+) ?>>>$\n([\s\S]+?)\n^<<< ?\1 ?<<<$/) { $2.gsub(/^/, "> ") }
170
- text.gsub!(/^>{4,}[[:blank:]]*$\n([\s\S]+?)\n^<{4,}[[:blank:]]*$/) { $1.gsub(/^/, "> ") }
171
-
172
- # fix all quotes formats
173
- text.gsub!(/^((?:[[:blank:]]*[[:alpha:]]*[>|])+)/) { $1.gsub(/([[:alpha:]]+>|\|)/, ">") }
174
-
175
- # fix embedded email markers that might span over multiple lines
176
- (
177
- EmbeddedEmailMatcher::ON_DATE_SOMEONE_WROTE_REGEXES +
178
- EmbeddedEmailMatcher::SOMEONE_WROTE_ON_DATE_REGEXES +
179
- EmbeddedEmailMatcher::DATE_SOMEONE_WROTE_REGEXES +
180
- [EmbeddedEmailMatcher::DATE_SOMEONE_EMAIL_REGEX]
181
- ).each do |r|
182
- text.gsub!(r) do |m|
183
- m.count("\n") > 4 ? m : m.gsub(/\n+[[:space:]]*/, " ")
184
- end
185
- end
168
+ def self.hoist_code_blocks(text)
169
+ blocks = {}
170
+ pattern = /^```\w*$\n.*?^```$/m
186
171
 
187
- # remove leading/trailing whitespaces
188
- text.strip!
172
+ text.gsub!(pattern) do |block|
173
+ token = SecureRandom.hex
174
+ blocks[token] = block
175
+ token
189
176
  end
190
177
 
191
- def self.compute_elided(text, lines)
192
- elided = []
178
+ [text, blocks]
179
+ end
193
180
 
194
- t = 0
195
- l = 0
181
+ def self.preprocess!(text)
182
+ # normalize line endings
183
+ text.gsub!("\r\n", "\n")
196
184
 
197
- while t < text.size
198
- while l < lines.size && text[t] == lines[l]
199
- t += 1
200
- l += 1
201
- end
202
- elided << text[t]
203
- t += 1
185
+ # remove PGP markers
186
+ text.gsub!(/\A-----BEGIN PGP SIGNED MESSAGE-----\n(?:Hash: \w+)?\s+/i, "")
187
+ text.gsub!(/^-----BEGIN PGP SIGNATURE-----$[\s\S]+^-----END PGP SIGNATURE-----/, "")
188
+
189
+ # remove unsubscribe links
190
+ text.gsub!(/^Unsubscribe: .+@.+(\n.+http:.+)?\s*\z/i, "")
191
+
192
+ # remove alias-style quotes marker
193
+ text.gsub!(/^.*>{5} "[^"\n]+" == .+ writes:/, "")
194
+
195
+ # change enclosed-style quotes format
196
+ text.gsub!(/^>>> ?(.+) ?>>>$\n([\s\S]+?)\n^<<< ?\1 ?<<<$/) { $2.gsub(/^/, "> ") }
197
+ text.gsub!(/^>{4,}[[:blank:]]*$\n([\s\S]+?)\n^<{4,}[[:blank:]]*$/) { $1.gsub(/^/, "> ") }
198
+
199
+ # fix all quotes formats
200
+ text.gsub!(/^((?:[[:blank:]]*[[:alpha:]]*[>|])+)/) { $1.gsub(/([[:alpha:]]+>|\|)/, ">") }
201
+
202
+ # fix embedded email markers that might span over multiple lines
203
+ (
204
+ EmbeddedEmailMatcher::ON_DATE_SOMEONE_WROTE_REGEXES +
205
+ EmbeddedEmailMatcher::SOMEONE_WROTE_ON_DATE_REGEXES +
206
+ EmbeddedEmailMatcher::DATE_SOMEONE_WROTE_REGEXES +
207
+ [EmbeddedEmailMatcher::DATE_SOMEONE_EMAIL_REGEX]
208
+ ).each do |r|
209
+ text.gsub!(r) do |m|
210
+ m.count("\n") > 4 ? m : m.gsub(/\n+[[:space:]]*/, " ")
204
211
  end
212
+ end
213
+
214
+ # remove leading/trailing whitespaces
215
+ text.strip!
216
+ end
217
+
218
+ def self.compute_elided(text, lines)
219
+ elided = []
220
+
221
+ t = 0
222
+ l = 0
205
223
 
206
- elided.join("\n").strip
224
+ while t < text.size
225
+ while l < lines.size && text[t] == lines[l]
226
+ t += 1
227
+ l += 1
228
+ end
229
+ elided << text[t]
230
+ t += 1
207
231
  end
208
232
 
233
+ elided.join("\n").strip
234
+ end
235
+
236
+ def self.is_reply_at_end?(pattern)
237
+ pattern =~ /^b[^t]+t[et]*$/
238
+ end
209
239
  end
@@ -0,0 +1 @@
1
+ This email has been forwarded from Apple Mail.
@@ -0,0 +1 @@
1
+ This email has been forwarded from Gmail.
File without changes
@@ -0,0 +1,15 @@
1
+ > Begin forwarded message:
2
+ >
3
+ > From: Foo Discourse <foo@discourse.org>
4
+ > Subject: This email is going to be forwarded
5
+ > Date: 01 January 2019 at 12:00:00 EET
6
+ > To: bar@discourse.org
7
+ >
8
+ > Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor
9
+ > lacus in metus vehicula, non dictum mi consequat. Nunc eget quam sit
10
+ > amet dolor scelerisque cursus. Etiam laoreet lectus a rutrum
11
+ > sollicitudin. Nullam sit amet lorem id ante lobortis fringilla. Duis
12
+ > dictum tempus sem et ultrices. Sed ac lectus ante. Vivamus interdum,
13
+ > risus non tincidunt accumsan, purus mi accumsan dolor, vitae euismod
14
+ > turpis orci ut est. Integer ut ante eu velit dignissim ullamcorper non
15
+ > id nibh. Nulla auctor magna erat, et posuere sapien gravida convallis.
@@ -0,0 +1,15 @@
1
+ ---------- Forwarded message ---------
2
+ From: Foo Discourse <foo@discourse.org>
3
+ Date: Tue, Jan 01, 2019 at 12:00 PM
4
+ Subject: This email is going to be forwarded
5
+ To: <bar@discourse.org>
6
+
7
+
8
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor
9
+ lacus in metus vehicula, non dictum mi consequat. Nunc eget quam sit
10
+ amet dolor scelerisque cursus. Etiam laoreet lectus a rutrum
11
+ sollicitudin. Nullam sit amet lorem id ante lobortis fringilla. Duis
12
+ dictum tempus sem et ultrices. Sed ac lectus ante. Vivamus interdum,
13
+ risus non tincidunt accumsan, purus mi accumsan dolor, vitae euismod
14
+ turpis orci ut est. Integer ut ante eu velit dignissim ullamcorper non
15
+ id nibh. Nulla auctor magna erat, et posuere sapien gravida convallis.
@@ -0,0 +1,75 @@
1
+ > On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
2
+ >
3
+ >> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
4
+ >>
5
+ >>> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
6
+ >>>
7
+ >>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
8
+ >>>>
9
+ >>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
10
+ >>>>>
11
+ >>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
12
+ >>>>>>
13
+ >>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
14
+ >>>>>>>
15
+ >>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
16
+ >>>>>>>>
17
+ >>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
18
+ >>>>>>>>>
19
+ >>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
20
+ >>>>>>>>>>
21
+ >>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
22
+ >>>>>>>>>>>
23
+ >>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
24
+ >>>>>>>>>>>>
25
+ >>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
26
+ >>>>>>>>>>>>>
27
+ >>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
28
+ >>>>>>>>>>>>>>
29
+ >>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
30
+ >>>>>>>>>>>>>>>
31
+ >>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
32
+ >>>>>>>>>>>>>>>>
33
+ >>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
34
+ >>>>>>>>>>>>>>>>>
35
+ >>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
36
+ >>>>>>>>>>>>>>>>>>
37
+ >>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
38
+ >>>>>>>>>>>>>>>>>>>
39
+ >>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
40
+ >>>>>>>>>>>>>>>>>>>>
41
+ >>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
42
+ >>>>>>>>>>>>>>>>>>>>>
43
+ >>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
44
+ >>>>>>>>>>>>>>>>>>>>>>
45
+ >>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
46
+ >>>>>>>>>>>>>>>>>>>>>>>
47
+ >>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
48
+ >>>>>>>>>>>>>>>>>>>>>>>>
49
+ >>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
50
+ >>>>>>>>>>>>>>>>>>>>>>>>>
51
+ >>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
52
+ >>>>>>>>>>>>>>>>>>>>>>>>>>
53
+ >>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
54
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>
55
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
56
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>
57
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
58
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
59
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
60
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
61
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
62
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
63
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
64
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
65
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
66
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
67
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
68
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
69
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
70
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
71
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
72
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
73
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
74
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
75
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
@@ -0,0 +1,152 @@
1
+ > On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
2
+ >
3
+ >> Hello world!
4
+ >>
5
+ >> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
6
+ >>
7
+ >>> Hello world!
8
+ >>>
9
+ >>> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
10
+ >>>
11
+ >>>> Hello world!
12
+ >>>>
13
+ >>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
14
+ >>>>
15
+ >>>>> Hello world!
16
+ >>>>>
17
+ >>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
18
+ >>>>>
19
+ >>>>>> Hello world!
20
+ >>>>>>
21
+ >>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
22
+ >>>>>>
23
+ >>>>>>> Hello world!
24
+ >>>>>>>
25
+ >>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
26
+ >>>>>>>
27
+ >>>>>>>> Hello world!
28
+ >>>>>>>>
29
+ >>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
30
+ >>>>>>>>
31
+ >>>>>>>>> Hello world!
32
+ >>>>>>>>>
33
+ >>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
34
+ >>>>>>>>>
35
+ >>>>>>>>>> Hello world!
36
+ >>>>>>>>>>
37
+ >>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
38
+ >>>>>>>>>>
39
+ >>>>>>>>>>> Hello world!
40
+ >>>>>>>>>>>
41
+ >>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
42
+ >>>>>>>>>>>
43
+ >>>>>>>>>>>> Hello world!
44
+ >>>>>>>>>>>>
45
+ >>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
46
+ >>>>>>>>>>>>
47
+ >>>>>>>>>>>>> Hello world!
48
+ >>>>>>>>>>>>>
49
+ >>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
50
+ >>>>>>>>>>>>>
51
+ >>>>>>>>>>>>>> Hello world!
52
+ >>>>>>>>>>>>>>
53
+ >>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
54
+ >>>>>>>>>>>>>>
55
+ >>>>>>>>>>>>>>> Hello world!
56
+ >>>>>>>>>>>>>>>
57
+ >>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
58
+ >>>>>>>>>>>>>>>
59
+ >>>>>>>>>>>>>>>> Hello world!
60
+ >>>>>>>>>>>>>>>>
61
+ >>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
62
+ >>>>>>>>>>>>>>>>
63
+ >>>>>>>>>>>>>>>>> Hello world!
64
+ >>>>>>>>>>>>>>>>>
65
+ >>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
66
+ >>>>>>>>>>>>>>>>>
67
+ >>>>>>>>>>>>>>>>>> Hello world!
68
+ >>>>>>>>>>>>>>>>>>
69
+ >>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
70
+ >>>>>>>>>>>>>>>>>>
71
+ >>>>>>>>>>>>>>>>>>> Hello world!
72
+ >>>>>>>>>>>>>>>>>>>
73
+ >>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
74
+ >>>>>>>>>>>>>>>>>>>
75
+ >>>>>>>>>>>>>>>>>>>> Hello world!
76
+ >>>>>>>>>>>>>>>>>>>>
77
+ >>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
78
+ >>>>>>>>>>>>>>>>>>>>
79
+ >>>>>>>>>>>>>>>>>>>>> Hello world!
80
+ >>>>>>>>>>>>>>>>>>>>>
81
+ >>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
82
+ >>>>>>>>>>>>>>>>>>>>>
83
+ >>>>>>>>>>>>>>>>>>>>>> Hello world!
84
+ >>>>>>>>>>>>>>>>>>>>>>
85
+ >>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
86
+ >>>>>>>>>>>>>>>>>>>>>>
87
+ >>>>>>>>>>>>>>>>>>>>>>> Hello world!
88
+ >>>>>>>>>>>>>>>>>>>>>>>
89
+ >>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
90
+ >>>>>>>>>>>>>>>>>>>>>>>
91
+ >>>>>>>>>>>>>>>>>>>>>>>> Hello world!
92
+ >>>>>>>>>>>>>>>>>>>>>>>>
93
+ >>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
94
+ >>>>>>>>>>>>>>>>>>>>>>>>
95
+ >>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
96
+ >>>>>>>>>>>>>>>>>>>>>>>>>
97
+ >>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
98
+ >>>>>>>>>>>>>>>>>>>>>>>>>
99
+ >>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
100
+ >>>>>>>>>>>>>>>>>>>>>>>>>>
101
+ >>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
102
+ >>>>>>>>>>>>>>>>>>>>>>>>>>
103
+ >>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
104
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>
105
+ >>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
106
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>
107
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
108
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>
109
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
110
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>
111
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
112
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
113
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
114
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
115
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
116
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
117
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
118
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
119
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
120
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
121
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
122
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
123
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
124
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
125
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
126
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
127
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
128
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
129
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
130
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
131
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
132
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
133
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
134
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
135
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
136
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
137
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
138
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
139
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
140
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
141
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
142
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
143
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
144
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
145
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
146
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
147
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
148
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
149
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
150
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
151
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello world!
152
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@@ -0,0 +1,13 @@
1
+ This is a long email with embedded code.
2
+
3
+ ```
4
+ # This should not be deleted
5
+ #
6
+
7
+ # Or trimmed
8
+ # It is code
9
+ ####
10
+ Code code code
11
+ ```
12
+
13
+ End of the email.
@@ -0,0 +1,17 @@
1
+ This email has been forwarded from Apple Mail.
2
+
3
+ > Begin forwarded message:
4
+ >
5
+ > From: Foo Discourse <foo@discourse.org>
6
+ > Subject: This email is going to be forwarded
7
+ > Date: 01 January 2019 at 12:00:00 EET
8
+ > To: bar@discourse.org
9
+ >
10
+ > Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor
11
+ > lacus in metus vehicula, non dictum mi consequat. Nunc eget quam sit
12
+ > amet dolor scelerisque cursus. Etiam laoreet lectus a rutrum
13
+ > sollicitudin. Nullam sit amet lorem id ante lobortis fringilla. Duis
14
+ > dictum tempus sem et ultrices. Sed ac lectus ante. Vivamus interdum,
15
+ > risus non tincidunt accumsan, purus mi accumsan dolor, vitae euismod
16
+ > turpis orci ut est. Integer ut ante eu velit dignissim ullamcorper non
17
+ > id nibh. Nulla auctor magna erat, et posuere sapien gravida convallis.
@@ -0,0 +1,17 @@
1
+ This email has been forwarded from Gmail.
2
+
3
+ ---------- Forwarded message ---------
4
+ From: Foo Discourse <foo@discourse.org>
5
+ Date: Tue, Jan 01, 2019 at 12:00 PM
6
+ Subject: This email is going to be forwarded
7
+ To: <bar@discourse.org>
8
+
9
+
10
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi auctor
11
+ lacus in metus vehicula, non dictum mi consequat. Nunc eget quam sit
12
+ amet dolor scelerisque cursus. Etiam laoreet lectus a rutrum
13
+ sollicitudin. Nullam sit amet lorem id ante lobortis fringilla. Duis
14
+ dictum tempus sem et ultrices. Sed ac lectus ante. Vivamus interdum,
15
+ risus non tincidunt accumsan, purus mi accumsan dolor, vitae euismod
16
+ turpis orci ut est. Integer ut ante eu velit dignissim ullamcorper non
17
+ id nibh. Nulla auctor magna erat, et posuere sapien gravida convallis.
@@ -0,0 +1,75 @@
1
+ > On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
2
+ >
3
+ >> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
4
+ >>
5
+ >>> On Thu, Apr 30, 2020 at 10:07 AM, "someone" <someone@example.com> wrote:
6
+ >>>
7
+ >>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
8
+ >>>>
9
+ >>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
10
+ >>>>>
11
+ >>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
12
+ >>>>>>
13
+ >>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
14
+ >>>>>>>
15
+ >>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
16
+ >>>>>>>>
17
+ >>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
18
+ >>>>>>>>>
19
+ >>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
20
+ >>>>>>>>>>
21
+ >>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
22
+ >>>>>>>>>>>
23
+ >>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
24
+ >>>>>>>>>>>>
25
+ >>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
26
+ >>>>>>>>>>>>>
27
+ >>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
28
+ >>>>>>>>>>>>>>
29
+ >>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
30
+ >>>>>>>>>>>>>>>
31
+ >>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
32
+ >>>>>>>>>>>>>>>>
33
+ >>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
34
+ >>>>>>>>>>>>>>>>>
35
+ >>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
36
+ >>>>>>>>>>>>>>>>>>
37
+ >>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
38
+ >>>>>>>>>>>>>>>>>>>
39
+ >>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
40
+ >>>>>>>>>>>>>>>>>>>>
41
+ >>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
42
+ >>>>>>>>>>>>>>>>>>>>>
43
+ >>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
44
+ >>>>>>>>>>>>>>>>>>>>>>
45
+ >>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
46
+ >>>>>>>>>>>>>>>>>>>>>>>
47
+ >>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
48
+ >>>>>>>>>>>>>>>>>>>>>>>>
49
+ >>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
50
+ >>>>>>>>>>>>>>>>>>>>>>>>>
51
+ >>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
52
+ >>>>>>>>>>>>>>>>>>>>>>>>>>
53
+ >>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
54
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>
55
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
56
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>
57
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
58
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
59
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
60
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
61
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
62
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
63
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
64
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
65
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
66
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
67
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
68
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
69
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
70
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
71
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
72
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
73
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote:
74
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
75
+ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Thu, Apr 30, 2020 at 10:06 AM, "someone" <someone@example.com> wrote: