email_reply_trimmer 0.1.6 → 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 (105) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +98 -0
  4. data/README.md +4 -4
  5. data/Rakefile +4 -7
  6. data/devenv.lock +184 -0
  7. data/devenv.nix +4 -0
  8. data/devenv.yaml +8 -0
  9. data/email_reply_trimmer.gemspec +8 -2
  10. data/lib/email_reply_trimmer/delimiter_matcher.rb +3 -2
  11. data/lib/email_reply_trimmer/email_header_matcher.rb +21 -8
  12. data/lib/email_reply_trimmer/embedded_email_matcher.rb +53 -25
  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 +24 -9
  16. data/lib/email_reply_trimmer.rb +102 -37
  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/email_headers_5.txt +23 -0
  21. data/test/elided/embedded_ception.txt +3 -3
  22. data/test/elided/embedded_email_12.txt +2 -2
  23. data/test/elided/embedded_email_13.txt +9 -0
  24. data/test/elided/embedded_email_14.txt +11 -0
  25. data/test/elided/embedded_email_15.txt +4 -0
  26. data/test/elided/embedded_email_16.txt +4 -0
  27. data/test/elided/embedded_email_17.txt +2 -0
  28. data/test/elided/embedded_email_18.txt +1 -0
  29. data/test/elided/embedded_email_19.txt +0 -0
  30. data/test/elided/embedded_email_chinese.txt +4 -0
  31. data/test/elided/embedded_email_german_4.txt +15 -0
  32. data/test/elided/embedded_email_german_5.txt +20 -0
  33. data/test/elided/embedded_email_german_6.txt +8 -0
  34. data/test/elided/embedded_email_norwegian.txt +9 -0
  35. data/test/elided/embedded_email_polish_2.txt +7 -0
  36. data/test/elided/embedded_email_quote_text.txt +5 -0
  37. data/test/elided/embedded_email_russian_2.txt +23 -0
  38. data/test/elided/embedded_email_swedish.txt +8 -0
  39. data/test/elided/embedded_email_ukrainian.txt +17 -0
  40. data/test/elided/forwarded_apple.txt +15 -0
  41. data/test/elided/forwarded_gmail.txt +15 -0
  42. data/test/elided/signatures.txt +5 -0
  43. data/test/elided/spam_1.txt +75 -0
  44. data/test/elided/spam_2.txt +152 -0
  45. data/test/emails/block_code_spacers.txt +13 -0
  46. data/test/emails/email_headers_5.txt +37 -0
  47. data/test/emails/embedded_email_1.txt +1 -1
  48. data/test/emails/embedded_email_13.txt +14 -0
  49. data/test/emails/embedded_email_14.txt +16 -0
  50. data/test/emails/embedded_email_15.txt +9 -0
  51. data/test/emails/embedded_email_16.txt +16 -0
  52. data/test/emails/embedded_email_17.txt +38 -0
  53. data/test/emails/embedded_email_18.txt +7 -0
  54. data/test/emails/embedded_email_19.txt +13 -0
  55. data/test/emails/embedded_email_4.txt +13 -13
  56. data/test/emails/embedded_email_7.txt +4 -4
  57. data/test/emails/embedded_email_chinese.txt +7 -0
  58. data/test/emails/embedded_email_german_4.txt +18 -0
  59. data/test/emails/embedded_email_german_5.txt +23 -0
  60. data/test/emails/embedded_email_german_6.txt +14 -0
  61. data/test/emails/embedded_email_norwegian.txt +11 -0
  62. data/test/emails/embedded_email_polish_2.txt +11 -0
  63. data/test/emails/embedded_email_russian_2.txt +26 -0
  64. data/test/emails/embedded_email_swedish.txt +20 -0
  65. data/test/emails/embedded_email_ukrainian.txt +19 -0
  66. data/test/emails/forwarded_apple.txt +17 -0
  67. data/test/emails/forwarded_gmail.txt +17 -0
  68. data/test/emails/signatures.txt +5 -0
  69. data/test/emails/spam_1.txt +75 -0
  70. data/test/emails/spam_2.txt +174 -0
  71. data/test/embedded/forwarded_apple.txt +13 -0
  72. data/test/embedded/forwarded_gmail.txt +14 -0
  73. data/test/matchers/does_not_contain_embedded_email.txt +5 -0
  74. data/test/test_email_matcher.rb +16 -0
  75. data/test/test_email_reply_trimmer.rb +8 -3
  76. data/test/trimmed/block_code_spacers.txt +13 -0
  77. data/test/trimmed/email_headers_5.txt +11 -0
  78. data/test/trimmed/embedded_email_13.txt +3 -0
  79. data/test/trimmed/embedded_email_14.txt +3 -0
  80. data/test/trimmed/embedded_email_15.txt +3 -0
  81. data/test/trimmed/embedded_email_16.txt +11 -0
  82. data/test/trimmed/embedded_email_17.txt +35 -0
  83. data/test/trimmed/embedded_email_18.txt +5 -0
  84. data/test/trimmed/embedded_email_19.txt +13 -0
  85. data/test/trimmed/embedded_email_chinese.txt +2 -0
  86. data/test/trimmed/embedded_email_german_4.txt +1 -0
  87. data/test/trimmed/embedded_email_german_5.txt +1 -0
  88. data/test/trimmed/embedded_email_german_6.txt +4 -0
  89. data/test/trimmed/embedded_email_norwegian.txt +1 -0
  90. data/test/trimmed/embedded_email_polish_2.txt +2 -0
  91. data/test/trimmed/embedded_email_quote_text.txt +0 -5
  92. data/test/trimmed/embedded_email_russian_2.txt +1 -0
  93. data/test/trimmed/embedded_email_swedish.txt +9 -0
  94. data/test/trimmed/embedded_email_ukrainian.txt +1 -0
  95. data/test/trimmed/forwarded_apple.txt +1 -0
  96. data/test/trimmed/forwarded_gmail.txt +1 -0
  97. data/test/trimmed/spam_1.txt +0 -0
  98. data/test/trimmed/spam_2.txt +21 -0
  99. metadata +147 -15
  100. /data/test/elided/{embedded_email_polish.txt → embedded_email_polish_1.txt} +0 -0
  101. /data/test/elided/{embedded_email_russian.txt → embedded_email_russian_1.txt} +0 -0
  102. /data/test/emails/{embedded_email_polish.txt → embedded_email_polish_1.txt} +0 -0
  103. /data/test/emails/{embedded_email_russian.txt → embedded_email_russian_1.txt} +0 -0
  104. /data/test/trimmed/{embedded_email_polish.txt → embedded_email_polish_1.txt} +0 -0
  105. /data/test/trimmed/{embedded_email_russian.txt → embedded_email_russian_1.txt} +0 -0
@@ -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.6"
11
+ VERSION = "0.2.0"
10
12
 
11
13
  DELIMITER = "d"
12
14
  EMBEDDED = "b"
@@ -23,25 +25,23 @@ 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
- def self.trim(text, split=false)
30
- return if text.nil? || text =~ /\A[[:space:]]*\Z/m
31
+ def self.trim(text, split = false)
32
+ return if text.nil? || text =~ /\A[[:space:]]*\z/m
31
33
 
32
- # normalize line endings
33
- text.gsub!("\r\n", "\n")
34
+ # do some cleanup
35
+ preprocess!(text)
34
36
 
35
- # fix embedded email markers that might span over multiple lines
36
- EmbeddedEmailMatcher::ON_DATE_SOMEONE_WROTE_REGEXES.each do |r|
37
- text.gsub!(r) { |m| m.gsub(/\n[[:space:]>\-]*/, " ") }
38
- end
37
+ # stash the code blocks - replace them with hashes
38
+ text, blocks = hoist_code_blocks(text)
39
39
 
40
40
  # from now on, we'll work on a line-by-line basis
41
41
  lines = text.split("\n")
42
42
  lines_dup = lines.dup
43
43
 
44
- # identify content of each lines
44
+ # create a string of characters, one per line, according to the line content
45
45
  pattern = lines.map { |l| identify_line_content(l) }.join
46
46
 
47
47
  # remove everything after the first delimiter
@@ -59,8 +59,8 @@ class EmailReplyTrimmer
59
59
  end
60
60
 
61
61
  # when the reply is at the end of the email
62
- if pattern =~ /^b+q+[eq]*t[te]*$/
63
- index = pattern =~ /t/
62
+ if is_reply_at_end?(pattern)
63
+ index = pattern =~ /t[et]*$/
64
64
  pattern = ""
65
65
  lines = lines[index..-1]
66
66
  end
@@ -75,12 +75,20 @@ class EmailReplyTrimmer
75
75
 
76
76
  # if there is an embedded email marker, followed by a huge quote
77
77
  # then take everything up to that marker
78
- if pattern =~ /te*b[eqbh]*[te]*$/
78
+ if pattern =~ /te*b[eqbh]*([te]*)$/ && $1.count("t") < 7
79
79
  index = pattern =~ /te*b[eqbh]*[te]*$/
80
80
  pattern = pattern[0..index]
81
81
  lines = lines[0..index]
82
82
  end
83
83
 
84
+ # if there is some text before a huge quote ending the email,
85
+ # then remove the quote
86
+ if pattern =~ /t?e*[qbe]+$/
87
+ index = pattern =~ /t?e*[qbe]+$/
88
+ pattern = pattern[0..index]
89
+ lines = lines[0..index]
90
+ end
91
+
84
92
  # if there still are some embedded email markers, just remove them
85
93
  while pattern =~ /b/
86
94
  index = pattern =~ /b/
@@ -95,8 +103,8 @@ class EmailReplyTrimmer
95
103
  size.times.each { |s| pattern[index + s] = EMAIL_HEADER }
96
104
  end
97
105
 
98
- # if there are at least 3 consecutive email headers, take everything up to
99
- # these headers
106
+ # if there are at least 3 consecutive email headers,
107
+ # take everything up to these headers
100
108
  if pattern =~ /t[eq]*h{3,}/
101
109
  index = pattern =~ /t[eq]*h{3,}/
102
110
  pattern = pattern[0..index]
@@ -120,6 +128,9 @@ class EmailReplyTrimmer
120
128
  # results
121
129
  trimmed = lines.join("\n").strip
122
130
 
131
+ # re-inject code blocks
132
+ blocks.each { |token, block| trimmed.gsub!(token, block) }
133
+
123
134
  if split
124
135
  [trimmed, compute_elided(lines_dup, lines)]
125
136
  else
@@ -128,15 +139,10 @@ class EmailReplyTrimmer
128
139
  end
129
140
 
130
141
  def self.extract_embedded_email(text)
131
- return if text.nil? || text =~ /\A[[:space:]]*\Z/m
142
+ return if text.nil? || text =~ /\A[[:space:]]*\z/m
132
143
 
133
- # normalize line endings
134
- text.gsub!("\r\n", "\n")
135
-
136
- # fix embedded email markers that might span over multiple lines
137
- EmbeddedEmailMatcher::ON_DATE_SOMEONE_WROTE_REGEXES.each do |r|
138
- text.gsub!(r) { |m| m.gsub(/\n[[:space:]>\-]*/, " ") }
139
- end
144
+ # do some cleanup
145
+ preprocess!(text)
140
146
 
141
147
  # from now on, we'll work on a line-by-line basis
142
148
  lines = text.split("\n")
@@ -146,29 +152,88 @@ class EmailReplyTrimmer
146
152
 
147
153
  if index = pattern =~ /(?:h[eqd]*?){3,}[tq]/
148
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
149
161
  before = lines[0...(pattern[0...index] =~ /e*(b[eqd]*|b*[ed]*)$/)].join("\n").strip
150
- return [embedded, before]
162
+ [embedded, before]
151
163
  end
152
164
  end
153
165
 
154
166
  private
155
167
 
156
- def self.compute_elided(text, lines)
157
- elided = []
168
+ def self.hoist_code_blocks(text)
169
+ blocks = {}
170
+ pattern = /^```\w*$\n.*?^```$/m
158
171
 
159
- t = 0
160
- l = 0
172
+ text.gsub!(pattern) do |block|
173
+ token = SecureRandom.hex
174
+ blocks[token] = block
175
+ token
176
+ end
161
177
 
162
- while t < text.size
163
- while l < lines.size && text[t] == lines[l]
164
- t += 1
165
- l += 1
166
- end
167
- elided << text[t]
168
- t += 1
178
+ [text, blocks]
179
+ end
180
+
181
+ def self.preprocess!(text)
182
+ # normalize line endings
183
+ text.gsub!("\r\n", "\n")
184
+
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:]]*/, " ")
169
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
170
223
 
171
- 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
172
231
  end
173
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
174
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,23 @@
1
+ From: Erlend Sogge Heggen <meta@discoursemail.com>
2
+ Reply-To: Erlend Sogge Heggen <meta+abcd@discoursemail.com>
3
+ Date: Wednesday, 5 April 2017 at 17:01
4
+ To: Jef <jef@bar.com>
5
+ Subject: [Discourse Meta] [PM] Discourse for Communities of Practice, educational organisation
6
+
7
+
8
+ erlend_sh<https://meta.discourse.org/u/erlend_sh> Erlend Sogge Heggen<https://meta.discourse.org/u/erlend_sh> Team
9
+ April 5
10
+
11
+
12
+
13
+ Hi Jef,
14
+
15
+ Is your University a legally recognised educational institution? Otherwise I'm afraid you're not eligible for this discount.
16
+
17
+ Sincerely,
18
+
19
+ Erlend
20
+
21
+
22
+
23
+ This email message and any attachments may contain confidential information and may be privileged. If you are not the intended recipient or otherwise not authorized to receive this message, you are prohibited to use, copy, disclose or take any action based on this email or any information contained herein. If you are not the intended recipient, please advise the sender immediately by replying to this email and permanently delete this message and any attachments from your system.
@@ -2,7 +2,7 @@ On Mon, Feb 1, 2016 at 6:32 PM, Jeff Atwood <info@discourse.org> wrote:
2
2
 
3
3
  > This is Jeff's reply.
4
4
  >
5
- > On Mon, Feb 1, 2016 at 7:50 AM, Some One <foo@bar.com wrote:
5
+ > On Mon, Feb 1, 2016 at 7:50 AM, Some One <foo@bar.com > > wrote:
6
6
  >
7
7
  >> Great!
8
8
  >>
@@ -14,7 +14,7 @@ On Mon, Feb 1, 2016 at 6:32 PM, Jeff Atwood <info@discourse.org> wrote:
14
14
  >>
15
15
  >>> WAT?
16
16
  >>>
17
- >>> On Wed, Jan 27, 2016 at 10:48 PM, Some One < foo@bar.com> wrote:
17
+ >>> On Wed, Jan 27, 2016 at 10:48 PM, Some One < >>> foo@bar.com> wrote:
18
18
  >>>
19
19
  >>>> Hi Team,
20
20
  >>>>
@@ -22,7 +22,7 @@ On Mon, Feb 1, 2016 at 6:32 PM, Jeff Atwood <info@discourse.org> wrote:
22
22
  >>>>
23
23
  >>>> Some One
24
24
  >>>>
25
- >>>> On Wed, Jan 27, 2016 at 10:10 AM Discourse Team <team@discourse.org> wrote:
25
+ >>>> On Wed, Jan 27, 2016 at 10:10 AM Discourse Team <team@discourse.org> >>>> wrote:
26
26
  >>>>
27
27
  >>>>> Hello :waves_hand:
28
28
  >>>>>
@@ -1,8 +1,8 @@
1
- On Thu, 31 Mar 2016 at 11:16 Some One < mailto:Some One <some.one@foo.bar> wrote:
1
+ On Thu, 31 Mar 2016 at 11:16 Some One < mailto:Some One <some.one@foo.bar> > wrote:
2
2
 
3
3
 
4
4
  Two 2
5
5
 
6
- On Thu, 31 Mar 2016 at 10:05 Jeff Atwood < mailto:Jeff Atwood <team@discourse.org> wrote:
6
+ On Thu, 31 Mar 2016 at 10:05 Jeff Atwood < mailto:Jeff Atwood <team@discourse.org> > wrote:
7
7
 
8
8
  Three 3
@@ -0,0 +1,9 @@
1
+ At 6/16/2016 08:32 PM, you wrote:
2
+ ><https://meta.discourse.org/users/codinghorror>codinghorror
3
+ ><https://meta.discourse.org/users/codinghorror>Jeff Atwood co-founder
4
+ >June 17
5
+ >
6
+ >Sorry I got a little mixed up with all the incoming replies. Are you
7
+ >able to log in?
8
+ >
9
+ >Use your email address and "forgot password" if you need it reset.
@@ -0,0 +1,11 @@
1
+ 2016-10-24 15:36 GMT+02:00 Foo bar < info@foo.bar>:
2
+
3
+ > Thank you so much Erlend, very thanks!
4
+ >
5
+ > 2016-10-24 15:03 GMT+02:00 Erlend Sogge Heggen <meta@discoursemail.com>:
6
+ >
7
+ >> erlend_sh <https://meta.discourse.org/users/erlend_sh> Erlend Sogge
8
+ >> Heggen <https://meta.discourse.org/users/erlend_sh> team
9
+ >> October 24
10
+ >>
11
+ >> I received your application and I've replied with setup instructions.
@@ -0,0 +1,4 @@
1
+ 2017-02-05 13:29 GMT+02:00 Very long author name < notifications@forum.some-discourse-host.local>:
2
+
3
+ > [Original Messages is quoted here]
4
+ > [...]
@@ -0,0 +1,4 @@
1
+ --
2
+ Eric Hodel - drbrain@segment7.net - http://segment7.net
3
+ All messages signed with fingerprint:
4
+ FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04
@@ -0,0 +1,2 @@
1
+ On 15 May 2017 19:32, "Nomadic Sprite" <nomadic.sprite01@gmail.com> wrote:
2
+ On 8 May 2017 6:51 pm, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:
@@ -0,0 +1 @@
1
+ On 8 May 2017 17:34, "Andy Jones" <Andy.Jones@jameshall.co.uk> wrote:
File without changes
@@ -0,0 +1,4 @@
1
+ > 在 2016年12月12日,下午8:45,Erlend Sogge Heggen <meta@discoursemail.com> 写道:
2
+ > fu.zhang:
3
+ > Some random question
4
+ >
@@ -0,0 +1,15 @@
1
+ Max Mustermann <try_discourse@discoursemail.com> schrieb am Fr., 28. Apr. 2017 um 11:53 Uhr:
2
+
3
+ > max_2 <http://try.discourse.org/u/cfstras_2>
4
+ > April 28
5
+
6
+ > Hi there! you should be getting a mail.
7
+ > ------------------------------
8
+
9
+ > Visit Topic <http://try.discourse.org/t/this-is-my-internal-test/716/2>
10
+ > or reply to this email to respond.
11
+
12
+ > To unsubscribe from these emails, click here
13
+ > <http://try.discourse.org/email/unsubscribe/badf00d>
14
+ > .
15
+
@@ -0,0 +1,20 @@
1
+ Erlend Sogge Heggen <meta@discoursemail.com> schrieb am Di., 16. Aug. 2016 um 12:52 Uhr:
2
+
3
+ > erlend_sh <https://meta.discourse.org/users/erlend_sh> Erlend Sogge Heggen
4
+ > <https://meta.discourse.org/users/erlend_sh> team
5
+ > August 16
6
+ >
7
+ > Hi Bob,
8
+ >
9
+ > Sure, it sounds like your requirements would fit our Standard plan. I
10
+ > suggest you sign up for a free trial, as that will be the best way to see
11
+ > for yourself if we support the kind of custom styling
12
+ >
13
+ > Sincerely,
14
+ >
15
+ > Erlend
16
+ >
17
+ --
18
+ Viele Grüße / Best regards
19
+
20
+ Bob
@@ -0,0 +1,8 @@
1
+ Am 21.04.2016 17:48 schrieb "Einz Zwei" <noreply@discourse.pseuco.com >:
2
+
3
+ > einz.zwei <https://discourse.pseuco.com/users/einz.zwei> einz
4
+ > zwei <https://discourse.pseuco.com/users/einz.zwei>
5
+ > 21. April
6
+ >
7
+ > Vielleicht noch eine wichtige Frage:
8
+ > Wann sollten wir diese Trainingsvideos veröffentlichen, es gibt 2
@@ -0,0 +1,9 @@
1
+ Sendt fra min iPad
2
+
3
+ Den 15. jun. 2016 kl. 20.42 skrev Jeff Atwood <info@discourse.org<mailto:info@discourse.org>>:
4
+
5
+ codinghorror<https://meta.discourse.org/users/codinghorror> Jeff Atwood<https://meta.discourse.org/users/codinghorror> co-founder
6
+ June 15
7
+
8
+
9
+ Enable tags in your admin, site settings.
@@ -0,0 +1,7 @@
1
+ 23 mar 2017 21:25 "Neil Lalonde" <meta@discoursemail.com> napisał(a):
2
+
3
+ > neil <https://meta.discourse.org/users/neil> Neil Lalonde
4
+ > <https://meta.discourse.org/users/neil> Team
5
+ > March 23
6
+ >
7
+ > I have made required changes. Enjoy!
@@ -1 +1,6 @@
1
1
  On Mon, Aug 19, 2013 at 2:36 AM, SomeOne via Discourse Meta < info@discourse.org> wrote:
2
+
3
+ > This seems like a problem that would be better solved at the web server
4
+ > level, rather than by the application. If nothing else, adding an instance
5
+ > of Nginx as an SSL/TLS reverse-proxy would very quickly take care of this.
6
+ >
@@ -0,0 +1,23 @@
1
+ 20 окт. 2016 г. 19:37 пользователь "Rafael dos Santos Silva" < meta@discoursemail.com> написал:
2
+
3
+ > Falco <https://meta.discourse.org/users/falco> Rafael dos Santos Silva
4
+ > <https://meta.discourse.org/users/falco> team
5
+ > October 20
6
+ >
7
+ > Are you using our official docker install?
8
+ >
9
+ > If you are, try a rebuild:
10
+ >
11
+ > ssh root@server
12
+ > cd /var/discourse
13
+ > ./launcher rebuild app
14
+ >
15
+ > ------------------------------
16
+ >
17
+ > Visit Topic <https://meta.discourse.org/t/error-upgrading/51797/2> or
18
+ > reply to this email to respond.
19
+ >
20
+ > To unsubscribe from these emails, click here
21
+ > <https://meta.discourse.org/email/unsubscribe/184ce11578cd0abaddcb6e7460708971afed7278523347d3184a421229d87d08>
22
+ > .
23
+ >
@@ -0,0 +1,8 @@
1
+ Från: Foo Bar [mailto:noreply@foo.bar]
2
+ Skickat: den 5 juni 2017 12:22
3
+ Till: someone@domain.com
4
+ Ämne: [WAT] Photos from the symposium
5
+
6
+ If you have any pictures from any parts of the symposium that you are willing to share, please reply to this post to share them (you can simply copy and paste or drag'n'drop them into the text).
7
+
8
+ Here are the group pictures we took on Wednesday after lunch.
@@ -0,0 +1,17 @@
1
+ 30 серп. 2016 р. 20:45 "Arpit" <no-reply@example.com> пише:
2
+
3
+ > meg <http://forum.example.com/users/foo> Foo
4
+ > <http://forum.example.com/users/foo>
5
+ > Август 30
6
+ >
7
+ > Когда будет точное название, напишите в личку и мы поменяем название.
8
+ > ------------------------------
9
+ >
10
+ > Visit Message
11
+ > <http://forum.example.com/t/slug/24>
12
+ > or reply to this email to respond.
13
+ >
14
+ > To unsubscribe from these emails, click here
15
+ > <http://forum.example.com/email/unsubscribe/0123456789>
16
+ > .
17
+ >
@@ -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.
@@ -24,3 +24,8 @@ Sent from my Windows 8 PC <http://windows.microsoft.com/consumer-preview>
24
24
  (sent from a phone)
25
25
  (Sent from mobile device)
26
26
  從我的 iPhone 傳送
27
+ Sent from [mail](https://go.microsoft.com/fwlink/?LinkId=550986) for windows 10
28
+ Verzonden met BlackBerry Work
29
+
30
+ Get Outlook for iOShttps://aka.ms/o0ukef
31
+ Get [Outlook for Android](https://aka.ms/ghei36)
@@ -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: