runger_email_reply_trimmer 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (230) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +72 -0
  5. data/LICENSE +9 -0
  6. data/README.md +21 -0
  7. data/Rakefile +17 -0
  8. data/bin/release +27 -0
  9. data/lib/runger_email_reply_trimmer/delimiter_matcher.rb +12 -0
  10. data/lib/runger_email_reply_trimmer/email_header_matcher.rb +72 -0
  11. data/lib/runger_email_reply_trimmer/embedded_email_matcher.rb +158 -0
  12. data/lib/runger_email_reply_trimmer/empty_line_matcher.rb +9 -0
  13. data/lib/runger_email_reply_trimmer/quote_matcher.rb +9 -0
  14. data/lib/runger_email_reply_trimmer/signature_matcher.rb +52 -0
  15. data/lib/runger_email_reply_trimmer/version.rb +5 -0
  16. data/lib/runger_email_reply_trimmer.rb +226 -0
  17. data/runger_email_reply_trimmer.gemspec +21 -0
  18. data/test/before/email_headers_1.txt +1 -0
  19. data/test/before/email_headers_2.txt +1 -0
  20. data/test/before/email_headers_3.txt +1 -0
  21. data/test/before/email_headers_4.txt +1 -0
  22. data/test/before/embedded_email_10.txt +25 -0
  23. data/test/before/embedded_email_german_3.txt +1 -0
  24. data/test/before/embedded_email_spanish_2.txt +1 -0
  25. data/test/before/forwarded_apple.txt +1 -0
  26. data/test/before/forwarded_gmail.txt +1 -0
  27. data/test/before/forwarded_message.txt +0 -0
  28. data/test/elided/delimiters.txt +10 -0
  29. data/test/elided/dual_embedded.txt +10 -0
  30. data/test/elided/email_headers_1.txt +14 -0
  31. data/test/elided/email_headers_2.txt +9 -0
  32. data/test/elided/email_headers_3.txt +16 -0
  33. data/test/elided/email_headers_4.txt +15 -0
  34. data/test/elided/email_headers_5.txt +23 -0
  35. data/test/elided/embedded_ception.txt +38 -0
  36. data/test/elided/embedded_email_1.txt +6 -0
  37. data/test/elided/embedded_email_10.txt +40 -0
  38. data/test/elided/embedded_email_11.txt +3 -0
  39. data/test/elided/embedded_email_12.txt +8 -0
  40. data/test/elided/embedded_email_13.txt +9 -0
  41. data/test/elided/embedded_email_14.txt +11 -0
  42. data/test/elided/embedded_email_15.txt +4 -0
  43. data/test/elided/embedded_email_16.txt +4 -0
  44. data/test/elided/embedded_email_17.txt +2 -0
  45. data/test/elided/embedded_email_18.txt +1 -0
  46. data/test/elided/embedded_email_19.txt +0 -0
  47. data/test/elided/embedded_email_2.txt +9 -0
  48. data/test/elided/embedded_email_3.txt +14 -0
  49. data/test/elided/embedded_email_4.txt +15 -0
  50. data/test/elided/embedded_email_5.txt +3 -0
  51. data/test/elided/embedded_email_6.txt +3 -0
  52. data/test/elided/embedded_email_7.txt +10 -0
  53. data/test/elided/embedded_email_8.txt +3 -0
  54. data/test/elided/embedded_email_9.txt +3 -0
  55. data/test/elided/embedded_email_chinese.txt +4 -0
  56. data/test/elided/embedded_email_dutch_1.txt +10 -0
  57. data/test/elided/embedded_email_dutch_2.txt +59 -0
  58. data/test/elided/embedded_email_french_1.txt +9 -0
  59. data/test/elided/embedded_email_french_2.txt +19 -0
  60. data/test/elided/embedded_email_german_1.txt +22 -0
  61. data/test/elided/embedded_email_german_2.txt +3 -0
  62. data/test/elided/embedded_email_german_3.txt +7 -0
  63. data/test/elided/embedded_email_german_4.txt +15 -0
  64. data/test/elided/embedded_email_german_5.txt +20 -0
  65. data/test/elided/embedded_email_german_6.txt +8 -0
  66. data/test/elided/embedded_email_italian.txt +28 -0
  67. data/test/elided/embedded_email_norwegian.txt +9 -0
  68. data/test/elided/embedded_email_polish_1.txt +32 -0
  69. data/test/elided/embedded_email_polish_2.txt +7 -0
  70. data/test/elided/embedded_email_portuguese.txt +14 -0
  71. data/test/elided/embedded_email_quote_text.txt +6 -0
  72. data/test/elided/embedded_email_russian_1.txt +25 -0
  73. data/test/elided/embedded_email_russian_2.txt +23 -0
  74. data/test/elided/embedded_email_spanish_1.txt +32 -0
  75. data/test/elided/embedded_email_spanish_2.txt +10 -0
  76. data/test/elided/embedded_email_swedish.txt +8 -0
  77. data/test/elided/embedded_email_ukrainian.txt +17 -0
  78. data/test/elided/forwarded_apple.txt +15 -0
  79. data/test/elided/forwarded_gmail.txt +15 -0
  80. data/test/elided/forwarded_message.txt +6 -0
  81. data/test/elided/normalize_line_endings.txt +0 -0
  82. data/test/elided/quote_and_text.txt +0 -0
  83. data/test/elided/quote_only.txt +0 -0
  84. data/test/elided/retains_spaces_and_formatting.txt +0 -0
  85. data/test/elided/signatures.txt +31 -0
  86. data/test/elided/spam_1.txt +75 -0
  87. data/test/elided/spam_2.txt +152 -0
  88. data/test/elided/strip.txt +0 -0
  89. data/test/elided/text_only.txt +0 -0
  90. data/test/elided/usenet.txt +7 -0
  91. data/test/emails/delimiters.txt +14 -0
  92. data/test/emails/dual_embedded.txt +13 -0
  93. data/test/emails/email_headers_1.txt +17 -0
  94. data/test/emails/email_headers_2.txt +10 -0
  95. data/test/emails/email_headers_3.txt +18 -0
  96. data/test/emails/email_headers_4.txt +17 -0
  97. data/test/emails/email_headers_5.txt +37 -0
  98. data/test/emails/embedded_ception.txt +47 -0
  99. data/test/emails/embedded_email_1.txt +8 -0
  100. data/test/emails/embedded_email_10.txt +42 -0
  101. data/test/emails/embedded_email_11.txt +5 -0
  102. data/test/emails/embedded_email_12.txt +18 -0
  103. data/test/emails/embedded_email_13.txt +14 -0
  104. data/test/emails/embedded_email_14.txt +16 -0
  105. data/test/emails/embedded_email_15.txt +9 -0
  106. data/test/emails/embedded_email_16.txt +16 -0
  107. data/test/emails/embedded_email_17.txt +38 -0
  108. data/test/emails/embedded_email_18.txt +7 -0
  109. data/test/emails/embedded_email_19.txt +13 -0
  110. data/test/emails/embedded_email_2.txt +16 -0
  111. data/test/emails/embedded_email_3.txt +24 -0
  112. data/test/emails/embedded_email_4.txt +19 -0
  113. data/test/emails/embedded_email_5.txt +5 -0
  114. data/test/emails/embedded_email_6.txt +11 -0
  115. data/test/emails/embedded_email_7.txt +20 -0
  116. data/test/emails/embedded_email_8.txt +5 -0
  117. data/test/emails/embedded_email_9.txt +5 -0
  118. data/test/emails/embedded_email_chinese.txt +7 -0
  119. data/test/emails/embedded_email_dutch_1.txt +13 -0
  120. data/test/emails/embedded_email_dutch_2.txt +62 -0
  121. data/test/emails/embedded_email_french_1.txt +12 -0
  122. data/test/emails/embedded_email_french_2.txt +21 -0
  123. data/test/emails/embedded_email_german_1.txt +26 -0
  124. data/test/emails/embedded_email_german_2.txt +6 -0
  125. data/test/emails/embedded_email_german_3.txt +10 -0
  126. data/test/emails/embedded_email_german_4.txt +18 -0
  127. data/test/emails/embedded_email_german_5.txt +23 -0
  128. data/test/emails/embedded_email_german_6.txt +14 -0
  129. data/test/emails/embedded_email_italian.txt +31 -0
  130. data/test/emails/embedded_email_norwegian.txt +11 -0
  131. data/test/emails/embedded_email_polish_1.txt +34 -0
  132. data/test/emails/embedded_email_polish_2.txt +11 -0
  133. data/test/emails/embedded_email_portuguese.txt +18 -0
  134. data/test/emails/embedded_email_quote_text.txt +10 -0
  135. data/test/emails/embedded_email_russian_1.txt +27 -0
  136. data/test/emails/embedded_email_russian_2.txt +26 -0
  137. data/test/emails/embedded_email_spanish_1.txt +41 -0
  138. data/test/emails/embedded_email_spanish_2.txt +12 -0
  139. data/test/emails/embedded_email_swedish.txt +20 -0
  140. data/test/emails/embedded_email_ukrainian.txt +19 -0
  141. data/test/emails/forwarded_apple.txt +17 -0
  142. data/test/emails/forwarded_gmail.txt +17 -0
  143. data/test/emails/forwarded_message.txt +9 -0
  144. data/test/emails/normalize_line_endings.txt +4 -0
  145. data/test/emails/quote_and_text.txt +3 -0
  146. data/test/emails/quote_only.txt +1 -0
  147. data/test/emails/retains_spaces_and_formatting.txt +14 -0
  148. data/test/emails/signatures.txt +33 -0
  149. data/test/emails/spam_1.txt +75 -0
  150. data/test/emails/spam_2.txt +174 -0
  151. data/test/emails/strip.txt +10 -0
  152. data/test/emails/text_only.txt +1 -0
  153. data/test/emails/usenet.txt +9 -0
  154. data/test/embedded/email_headers_1.txt +12 -0
  155. data/test/embedded/email_headers_2.txt +8 -0
  156. data/test/embedded/email_headers_3.txt +16 -0
  157. data/test/embedded/email_headers_4.txt +15 -0
  158. data/test/embedded/embedded_email_10.txt +15 -0
  159. data/test/embedded/embedded_email_german_3.txt +6 -0
  160. data/test/embedded/embedded_email_spanish_2.txt +9 -0
  161. data/test/embedded/forwarded_apple.txt +13 -0
  162. data/test/embedded/forwarded_gmail.txt +14 -0
  163. data/test/embedded/forwarded_message.txt +8 -0
  164. data/test/matchers/does_not_contain_embedded_email.txt +5 -0
  165. data/test/test_email_matcher.rb +17 -0
  166. data/test/test_email_reply_trimmer.rb +87 -0
  167. data/test/trimmed/delimiters.txt +3 -0
  168. data/test/trimmed/dual_embedded.txt +1 -0
  169. data/test/trimmed/email_headers_1.txt +1 -0
  170. data/test/trimmed/email_headers_2.txt +1 -0
  171. data/test/trimmed/email_headers_3.txt +1 -0
  172. data/test/trimmed/email_headers_4.txt +1 -0
  173. data/test/trimmed/email_headers_5.txt +11 -0
  174. data/test/trimmed/embedded_ception.txt +4 -0
  175. data/test/trimmed/embedded_email_1.txt +1 -0
  176. data/test/trimmed/embedded_email_10.txt +1 -0
  177. data/test/trimmed/embedded_email_11.txt +1 -0
  178. data/test/trimmed/embedded_email_12.txt +1 -0
  179. data/test/trimmed/embedded_email_13.txt +3 -0
  180. data/test/trimmed/embedded_email_14.txt +3 -0
  181. data/test/trimmed/embedded_email_15.txt +3 -0
  182. data/test/trimmed/embedded_email_16.txt +11 -0
  183. data/test/trimmed/embedded_email_17.txt +35 -0
  184. data/test/trimmed/embedded_email_18.txt +5 -0
  185. data/test/trimmed/embedded_email_19.txt +13 -0
  186. data/test/trimmed/embedded_email_2.txt +3 -0
  187. data/test/trimmed/embedded_email_3.txt +7 -0
  188. data/test/trimmed/embedded_email_4.txt +2 -0
  189. data/test/trimmed/embedded_email_5.txt +1 -0
  190. data/test/trimmed/embedded_email_6.txt +7 -0
  191. data/test/trimmed/embedded_email_7.txt +10 -0
  192. data/test/trimmed/embedded_email_8.txt +1 -0
  193. data/test/trimmed/embedded_email_9.txt +1 -0
  194. data/test/trimmed/embedded_email_chinese.txt +2 -0
  195. data/test/trimmed/embedded_email_dutch_1.txt +1 -0
  196. data/test/trimmed/embedded_email_dutch_2.txt +2 -0
  197. data/test/trimmed/embedded_email_french_1.txt +1 -0
  198. data/test/trimmed/embedded_email_french_2.txt +1 -0
  199. data/test/trimmed/embedded_email_german_1.txt +1 -0
  200. data/test/trimmed/embedded_email_german_2.txt +1 -0
  201. data/test/trimmed/embedded_email_german_3.txt +1 -0
  202. data/test/trimmed/embedded_email_german_4.txt +1 -0
  203. data/test/trimmed/embedded_email_german_5.txt +1 -0
  204. data/test/trimmed/embedded_email_german_6.txt +4 -0
  205. data/test/trimmed/embedded_email_italian.txt +1 -0
  206. data/test/trimmed/embedded_email_norwegian.txt +1 -0
  207. data/test/trimmed/embedded_email_polish_1.txt +1 -0
  208. data/test/trimmed/embedded_email_polish_2.txt +2 -0
  209. data/test/trimmed/embedded_email_portuguese.txt +2 -0
  210. data/test/trimmed/embedded_email_quote_text.txt +2 -0
  211. data/test/trimmed/embedded_email_russian_1.txt +1 -0
  212. data/test/trimmed/embedded_email_russian_2.txt +1 -0
  213. data/test/trimmed/embedded_email_spanish_1.txt +6 -0
  214. data/test/trimmed/embedded_email_spanish_2.txt +1 -0
  215. data/test/trimmed/embedded_email_swedish.txt +9 -0
  216. data/test/trimmed/embedded_email_ukrainian.txt +1 -0
  217. data/test/trimmed/forwarded_apple.txt +1 -0
  218. data/test/trimmed/forwarded_gmail.txt +1 -0
  219. data/test/trimmed/forwarded_message.txt +1 -0
  220. data/test/trimmed/normalize_line_endings.txt +4 -0
  221. data/test/trimmed/quote_and_text.txt +3 -0
  222. data/test/trimmed/quote_only.txt +1 -0
  223. data/test/trimmed/retains_spaces_and_formatting.txt +14 -0
  224. data/test/trimmed/signatures.txt +1 -0
  225. data/test/trimmed/spam_1.txt +0 -0
  226. data/test/trimmed/spam_2.txt +21 -0
  227. data/test/trimmed/strip.txt +1 -0
  228. data/test/trimmed/text_only.txt +1 -0
  229. data/test/trimmed/usenet.txt +1 -0
  230. metadata +275 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dd04b62e18b2b1f82ad85786471685f6dc53c9675d2f7d7431966fd0bb518a79
4
+ data.tar.gz: ff797d745d30f3cc614dd8a5a76b669e1e4baa02dffd93a949523f0e7750ed00
5
+ SHA512:
6
+ metadata.gz: cc7c3c0a0956f7d36aea958cdbcb42992958fc59e85d0e0bfc401857c8779a38e41038fa753ced8f8a268542fa45f96cf2bd96d69a150a273cb1714c429d3797
7
+ data.tar.gz: badb11c1de342bca0146764c79272a8cfe9220e0376d3665df1ccd9fc2cee1a0b9ad783c1f99613b694ad2ac6184602271a9b037c4150cf6120be4f91881701b
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## v0.2.0 (2023-05-21)
2
+ ### Changed
3
+ - Rename with "Runger" prefix.
4
+ - Make various other tweaks to make this a Runger-style gem.
5
+
6
+ ### Added
7
+ - Release via RubyGems.
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in runger_email_reply_trimmer.gemspec
6
+ gemspec
7
+
8
+ group :development do
9
+ gem 'release_assistant', require: false, git: 'https://github.com/davidrunger/release_assistant'
10
+ end
11
+
12
+ group :development, :test do
13
+ gem 'minitest', '~> 5', require: false
14
+ gem 'rake', '~> 12', require: false
15
+ gem 'rubocop', require: false
16
+ gem 'runger_style', require: false
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,72 @@
1
+ GIT
2
+ remote: https://github.com/davidrunger/release_assistant
3
+ revision: a278e05c53c700b8946e5fed16c7286eacb963e3
4
+ specs:
5
+ release_assistant (0.3.3.alpha)
6
+ activesupport (>= 6, < 8)
7
+ colorize (~> 0.8)
8
+ memoist (~> 0.16)
9
+ slop (~> 4.8)
10
+
11
+ PATH
12
+ remote: .
13
+ specs:
14
+ runger_email_reply_trimmer (0.2.1)
15
+
16
+ GEM
17
+ remote: https://rubygems.org/
18
+ specs:
19
+ activesupport (7.0.4.3)
20
+ concurrent-ruby (~> 1.0, >= 1.0.2)
21
+ i18n (>= 1.6, < 2)
22
+ minitest (>= 5.1)
23
+ tzinfo (~> 2.0)
24
+ ast (2.4.2)
25
+ colorize (0.8.1)
26
+ concurrent-ruby (1.2.2)
27
+ i18n (1.13.0)
28
+ concurrent-ruby (~> 1.0)
29
+ json (2.6.3)
30
+ memoist (0.16.2)
31
+ minitest (5.18.0)
32
+ parallel (1.23.0)
33
+ parser (3.2.2.1)
34
+ ast (~> 2.4.1)
35
+ rainbow (3.1.1)
36
+ rake (12.3.3)
37
+ regexp_parser (2.8.0)
38
+ rexml (3.2.5)
39
+ rubocop (1.51.0)
40
+ json (~> 2.3)
41
+ parallel (~> 1.10)
42
+ parser (>= 3.2.0.0)
43
+ rainbow (>= 2.2.2, < 4.0)
44
+ regexp_parser (>= 1.8, < 3.0)
45
+ rexml (>= 3.2.5, < 4.0)
46
+ rubocop-ast (>= 1.28.0, < 2.0)
47
+ ruby-progressbar (~> 1.7)
48
+ unicode-display_width (>= 2.4.0, < 3.0)
49
+ rubocop-ast (1.28.1)
50
+ parser (>= 3.2.1.0)
51
+ ruby-progressbar (1.13.0)
52
+ runger_style (0.2.22)
53
+ rubocop (>= 1.38.0, < 2)
54
+ slop (4.10.1)
55
+ tzinfo (2.0.6)
56
+ concurrent-ruby (~> 1.0)
57
+ unicode-display_width (2.4.2)
58
+
59
+ PLATFORMS
60
+ x86_64-darwin-20
61
+ x86_64-linux
62
+
63
+ DEPENDENCIES
64
+ minitest (~> 5)
65
+ rake (~> 12)
66
+ release_assistant!
67
+ rubocop
68
+ runger_email_reply_trimmer!
69
+ runger_style
70
+
71
+ BUNDLED WITH
72
+ 2.4.12
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Discourse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Runger Email Reply Trimmer
2
+
3
+ RungerEmailReplyTrimmer is a small library to trim replies from plain text email.
4
+
5
+ ## Usage
6
+
7
+ To trim replies:
8
+
9
+ `trimmed_body = RungerEmailReplyTrimmer.trim(email_body)`
10
+
11
+ ## Installation
12
+
13
+ List the gem in your `Gemfile`:
14
+
15
+ ```rb
16
+ gem 'runger_email_reply_trimmer'
17
+ ```
18
+
19
+ ## This is a fork
20
+
21
+ It was forked from https://github.com/discourse/email_reply_trimmer.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ def name
7
+ @name ||= Dir['*.gemspec'].first.split('.').first
8
+ end
9
+
10
+ def version
11
+ @version ||= File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*['"](?'version'\d+\.\d+\.\d+)['"]/,
12
+ 'version']
13
+ end
14
+
15
+ Rake::TestTask.new(:test)
16
+
17
+ task default: :test
data/bin/release ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'release' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
12
+
13
+ bundle_binstub = File.expand_path('bundle', __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require 'rubygems'
25
+ require 'bundler/setup'
26
+
27
+ load Gem.bin_path('release_assistant', 'release')
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DelimiterMatcher
4
+ module_function
5
+
6
+ DELIMITER_CHARACTERS = '-_,=+~#*ᐧ—'
7
+ DELIMITER_REGEX = /^[[:blank:]]*[#{Regexp.escape(DELIMITER_CHARACTERS)}]+[[:blank:]]*$/
8
+
9
+ def match?(line)
10
+ line =~ DELIMITER_REGEX
11
+ end
12
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailHeaderMatcher
4
+ module_function
5
+
6
+ EMAIL_HEADERS_WITH_DATE_MARKERS = [
7
+ # Norwegian
8
+ ['Sendt'],
9
+ # English
10
+ ['Sent', 'Date'],
11
+ # French
12
+ ['Date', 'Le'],
13
+ # German
14
+ ['Gesendet'],
15
+ # Portuguese
16
+ ['Enviada em'],
17
+ # Spanish
18
+ ['Enviado'],
19
+ # Spanish (Mexican)
20
+ ['Fecha'],
21
+ # Italian
22
+ ['Data'],
23
+ # Dutch
24
+ ['Datum'],
25
+ # Swedish
26
+ ['Skickat'],
27
+ # Chinese
28
+ ['发送时间'],
29
+ ].freeze
30
+
31
+ EMAIL_HEADERS_WITH_DATE_REGEXES =
32
+ EMAIL_HEADERS_WITH_DATE_MARKERS.map do |header|
33
+ /^[[:blank:]*]*(?:#{header.join("|")})[[:blank:]*]*:.*\d+/
34
+ end
35
+
36
+ EMAIL_HEADERS_WITH_TEXT_MARKERS = [
37
+ # Norwegian
38
+ ['Fra', 'Til', 'Emne'],
39
+ # English
40
+ ['From', 'To', 'Cc', 'Reply-To', 'Subject'],
41
+ # French
42
+ ['De', 'Expéditeur', 'À', 'Destinataire', 'Répondre à', 'Objet'],
43
+ # German
44
+ ['Von', 'An', 'Betreff'],
45
+ # Portuguese
46
+ ['De', 'Para', 'Assunto'],
47
+ # Spanish
48
+ ['De', 'Para', 'Asunto'],
49
+ # Italian
50
+ ['Da', 'Risposta', 'A', 'Oggetto'],
51
+ # Dutch
52
+ ['Van', 'Beantwoorden - Aan', 'Aan', 'Onderwerp'],
53
+ # Swedish
54
+ ['Från', 'Till', 'Ämne'],
55
+ # Chinese
56
+ ['发件人', '收件人', '主题'],
57
+ ].freeze
58
+
59
+ EMAIL_HEADERS_WITH_TEXT_REGEXES =
60
+ EMAIL_HEADERS_WITH_TEXT_MARKERS.map do |header|
61
+ /^[[:blank:]*]*(?:#{header.join("|")})[[:blank:]*]*:.*[[:word:]]+/i
62
+ end
63
+
64
+ EMAIL_HEADER_REGEXES = [
65
+ EMAIL_HEADERS_WITH_DATE_REGEXES,
66
+ EMAIL_HEADERS_WITH_TEXT_REGEXES,
67
+ ].flatten
68
+
69
+ def match?(line)
70
+ EMAIL_HEADER_REGEXES.any? { |r| line =~ r }
71
+ end
72
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmbeddedEmailMatcher
4
+ module_function
5
+
6
+ # On Wed, Sep 25, 2013, at 03:57 PM, jorge_castro wrote:
7
+ # On Thursday, June 27, 2013, knwang via Discourse Meta wrote:
8
+ # On Wed, 2015-12-02 at 13:58 +0000, Tom Newsom wrote:
9
+ # On 10/12/15 12:30, Jeff Atwood wrote:
10
+ # ---- On Tue, 22 Dec 2015 14:17:36 +0530 Sam Saffron&lt;info@discourse.org&gt; wrote ----
11
+ # Op 24 aug. 2013 om 16:48 heeft ven88 via Discourse Meta <info@discourse.org> het volgende geschreven:
12
+ # Le 4 janv. 2016 19:03, "Neil Lalonde" <info@discourse.org> a écrit :
13
+ # Dnia 14 lip 2015 o godz. 00:25 Michael Downey <info@discourse.org> napisał(a):
14
+ # Em seg, 27 de jul de 2015 17:13, Neil Lalonde <info@discourse.org> escreveu:
15
+ # El jueves, 21 de noviembre de 2013, codinghorror escribió:
16
+ # At 6/16/2016 08:32 PM, you wrote:
17
+ ON_DATE_SOMEONE_WROTE_REGEXES = [
18
+ # Chinese
19
+ /^[[:blank:]<>-]*在 (?:(?!\b(?>在|写道)\b).)+?写道[[:blank:].:>-]*$/im,
20
+ # Dutch
21
+ /^[[:blank:]<>-]*Op (?:(?!\b(?>Op|het\svolgende\sgeschreven|schreef)\b).)+?(het\svolgende\sgeschreven|schreef[^:]+)[[:blank:].:>-]*$/im,
22
+ # English
23
+ /^[[:blank:]<>-]*In message (?:(?!\b(?>In message|writes)\b).)+?writes[[:blank:].:>-]*$/im,
24
+ /^[[:blank:]<>-]*(On|At) (?:(?!\b(?>On|wrote|writes|says|said)\b).)+?(wrote|writes|says|said)[[:blank:].:>-]*$/im,
25
+ # French
26
+ /^[[:blank:]<>-]*Le (?:(?!\b(?>Le|nous\sa\sdit|a\s+écrit)\b).)+?(nous\sa\sdit|a\s+écrit)[[:blank:].:>-]*$/im,
27
+ # German
28
+ /^[[:blank:]<>-]*Am (?:(?!\b(?>Am|schrieben\sSie)\b).)+?schrieben\sSie[[:blank:].:>-]*$/im,
29
+ /^[[:blank:]<>-]*Am (?:(?!\b(?>Am|geschrieben)\b).)+?(geschrieben|schrieb[^:]+)[[:blank:].:>-]*$/im,
30
+ # Italian
31
+ /^[[:blank:]<>-]*Il (?:(?!\b(?>Il|ha\sscritto)\b).)+?ha\sscritto[[:blank:].:>-]*$/im,
32
+ # Polish
33
+ /^[[:blank:]<>-]*(Dnia|Dňa) (?:(?!\b(?>Dnia|Dňa|napisał)\b).)+?napisał(\(a\))?[[:blank:].:>-]*$/im,
34
+ # Portuguese
35
+ /^[[:blank:]<>-]*Em (?:(?!\b(?>Em|escreveu)\b).)+?escreveu[[:blank:].:>-]*$/im,
36
+ # Spanish
37
+ /^[[:blank:]<>-]*El (?:(?!\b(?>El|escribió)\b).)+?escribió[[:blank:].:>-]*$/im,
38
+ ].freeze
39
+
40
+ # Op 10 dec. 2015 18:35 schreef "Arpit Jalan" <info@discourse.org>:
41
+ # Am 18.09.2013 um 16:24 schrieb codinghorror <info@discourse.org>:
42
+ # Den 15. jun. 2016 kl. 20.42 skrev Jeff Atwood <info@discourse.org>:
43
+ # søn. 30. apr. 2017 kl. 00.26 skrev David Taylor <meta@discoursemail.com>:
44
+ ON_DATE_WROTE_SOMEONE_MARKERS = [
45
+ # Dutch
46
+ ['Op', 'schreef'],
47
+ # German
48
+ ['Am', 'schrieb'],
49
+ # Norwegian
50
+ ['Den', 'skrev'],
51
+ # Dutch
52
+ ['søn.', 'skrev'],
53
+ ].freeze
54
+
55
+ ON_DATE_WROTE_SOMEONE_REGEXES =
56
+ ON_DATE_WROTE_SOMEONE_MARKERS.map do |on, wrote|
57
+ /^[[:blank:]>]*#{on}\s.+\s#{wrote}\s[^:]+:/
58
+ end
59
+
60
+ # суббота, 14 марта 2015 г. пользователь etewiah написал:
61
+ # 23 mar 2017 21:25 "Neil Lalonde" <meta@discoursemail.com> napisał(a):
62
+ # 30 серп. 2016 р. 20:45 "Arpit" no-reply@example.com пише:
63
+ DATE_SOMEONE_WROTE_MARKERS = [
64
+ # Russian
65
+ ['пользователь', 'написал'],
66
+ # Polish
67
+ ['', 'napisał\\(a\\)'],
68
+ # Ukrainian
69
+ ['', 'пише'],
70
+ ].freeze
71
+
72
+ DATE_SOMEONE_WROTE_REGEXES =
73
+ DATE_SOMEONE_WROTE_MARKERS.map do |user, wrote|
74
+ if user.empty?
75
+ /\d{4}.{1,80}\n?.{0,80}?#{wrote}:/
76
+ else
77
+ /\d{4}.{1,80}#{user}.{0,80}\n?.{0,80}?#{wrote}:/
78
+ end
79
+ end
80
+
81
+ # Max Mustermann <try_discourse@discoursemail.com> schrieb am Fr., 28. Apr. 2017 um 11:53 Uhr:
82
+ SOMEONE_WROTE_ON_DATE_REGEXES = [
83
+ # English
84
+ /^.+\bwrote\b[[:space:]]+\bon\b.+[^:]+:/,
85
+ # German
86
+ /^.+\bschrieb\b[[:space:]]+\bam\b.+[^:]+:/,
87
+ ].freeze
88
+
89
+ # 2016-03-03 17:21 GMT+01:00 Some One
90
+ ISO_DATE_SOMEONE_REGEX = /^[[:blank:]>]*20\d\d-\d\d-\d\d \d\d:\d\d GMT\+\d\d:\d\d [\w[:blank:]]+$/
91
+
92
+ # 2015-10-18 0:17 GMT+03:00 Matt Palmer <info@discourse.org>:
93
+ # 2013/10/2 camilohollanda <info@discourse.org>
94
+ # вт, 5 янв. 2016 г. в 23:39, Erlend Sogge Heggen <info@discourse.org>:
95
+ # ср, 1 апр. 2015, 18:29, Denis Didkovsky <info@discourse.org>:
96
+ DATE_SOMEONE_EMAIL_REGEX = /\d{4}.{1,80}\s?<[^@<>]+@[^@<>.]+\.[^@<>]+>:?$/
97
+
98
+ # codinghorror via Discourse Meta wrote:
99
+ # codinghorror via Discourse Meta <info@discourse.org> schrieb:
100
+ SOMEONE_VIA_SOMETHING_WROTE_MARKERS = [
101
+ # English
102
+ 'wrote',
103
+ # German
104
+ 'schrieb',
105
+ ].freeze
106
+
107
+ SOMEONE_VIA_SOMETHING_WROTE_REGEXES =
108
+ SOMEONE_VIA_SOMETHING_WROTE_MARKERS.map do |wrote|
109
+ /^.+ via .+ #{wrote}:?[[:blank:]]*$/
110
+ end
111
+
112
+ # Some One <info@discourse.org> wrote:
113
+ # Gavin Sinclair (gsinclair@soyabean.com.au) wrote:
114
+ SOMEONE_EMAIL_WROTE_REGEX = /^.+\b[\w.+-]+@[\w.-]+\.\w{2,}\b.+wrote:?$/
115
+
116
+ # Posted by mpalmer on 01/21/2016
117
+ POSTED_BY_SOMEONE_ON_DATE_REGEX = /^[[:blank:]>]*Posted by .+ on \d{2}\/\d{2}\/\d{4}$/i
118
+
119
+ # Begin forwarded message:
120
+ # Reply Message
121
+ # ----- Forwarded Message -----
122
+ # ----- Original Message -----
123
+ # -----Original Message-----
124
+ # *----- Original Message -----*
125
+ # ----- Reply message -----
126
+ # ------------------ 原始邮件 ------------------
127
+ FORWARDED_EMAIL_REGEXES = [
128
+ # English
129
+ /^[[:blank:]>]*Begin forwarded message:/i,
130
+ /^[[:blank:]>*]*-{2,}[[:blank:]]*(Forwarded|Original|Reply) Message[[:blank:]]*-{2,}/i,
131
+ # French
132
+ /^[[:blank:]>]*Début du message transféré :/i,
133
+ /^[[:blank:]>*]*-{2,}[[:blank:]]*Message transféré[[:blank:]]*-{2,}/i,
134
+ # German
135
+ /^[[:blank:]>*]*-{2,}[[:blank:]]*Ursprüngliche Nachricht[[:blank:]]*-{2,}/i,
136
+ # Spanish
137
+ /^[[:blank:]>*]*-{2,}[[:blank:]]*Mensaje original[[:blank:]]*-{2,}/i,
138
+ # Chinese
139
+ /^[[:blank:]>*]*-{2,}[[:blank:]]*原始邮件[[:blank:]]*-{2,}/i,
140
+ ].freeze
141
+
142
+ EMBEDDED_REGEXES = [
143
+ ON_DATE_SOMEONE_WROTE_REGEXES,
144
+ ON_DATE_WROTE_SOMEONE_REGEXES,
145
+ DATE_SOMEONE_WROTE_REGEXES,
146
+ DATE_SOMEONE_EMAIL_REGEX,
147
+ SOMEONE_WROTE_ON_DATE_REGEXES,
148
+ ISO_DATE_SOMEONE_REGEX,
149
+ SOMEONE_VIA_SOMETHING_WROTE_REGEXES,
150
+ SOMEONE_EMAIL_WROTE_REGEX,
151
+ POSTED_BY_SOMEONE_ON_DATE_REGEX,
152
+ FORWARDED_EMAIL_REGEXES,
153
+ ].flatten
154
+
155
+ def match?(line)
156
+ EMBEDDED_REGEXES.any? { |r| line =~ r }
157
+ end
158
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmptyLineMatcher
4
+ module_function
5
+
6
+ def match?(line)
7
+ line =~ /^[[:blank:]]*$/
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QuoteMatcher
4
+ module_function
5
+
6
+ def match?(line)
7
+ line =~ /^[[:blank:]]*>/
8
+ end
9
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SignatureMatcher
4
+ module_function
5
+
6
+ # Envoyé depuis mon iPhone
7
+ # Von meinem Mobilgerät gesendet
8
+ # Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.
9
+ # Nik from mobile
10
+ # From My Iphone 6
11
+ # Sent via mobile
12
+ # Sent with Airmail
13
+ # Sent from Windows Mail
14
+ # Sent from my TI-85
15
+ # <<sent by galaxy>>
16
+ # (sent from a phone)
17
+ # (Sent from mobile device)
18
+ # 從我的 iPhone 傳送
19
+ SIGNATURE_REGEXES = [
20
+ # Chinese
21
+ /^[[:blank:]]*從我的 iPhone 傳送/i,
22
+ # English
23
+ /^[[:blank:]]*[[:word:]]+ from mobile/i,
24
+ /^[[:blank:]]*[(<]*Sent (from|via|with|by) .+[)>]*/i,
25
+ /^[[:blank:]]*From my .{1,20}/i,
26
+ /^[[:blank:]]*Get Outlook for /i,
27
+ # French
28
+ /^[[:blank:]]*Envoyé depuis (mon|Yahoo Mail)/i,
29
+ # German
30
+ /^[[:blank:]]*Von meinem .+ gesendet/i,
31
+ /^[[:blank:]]*Diese Nachricht wurde von .+ gesendet/i,
32
+ # Italian
33
+ /^[[:blank:]]*Inviato da /i,
34
+ # Norwegian
35
+ /^[[:blank:]]*Sendt fra min /i,
36
+ # Portuguese
37
+ /^[[:blank:]]*Enviado do meu /i,
38
+ # Spanish
39
+ /^[[:blank:]]*Enviado desde mi /i,
40
+ # Dutch
41
+ /^[[:blank:]]*Verzonden met /i,
42
+ /^[[:blank:]]*Verstuurd vanaf mijn /i,
43
+ # Swedish
44
+ /^[[:blank:]]*från min /i,
45
+ ].freeze
46
+
47
+ def match?(line)
48
+ # remove any markdown links
49
+ stripped = line.gsub(/\[([^\]]+)\]\([^)]+\)/) { ::Regexp.last_match(1) }
50
+ SIGNATURE_REGEXES.any? { |r| stripped =~ r }
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RungerEmailReplyTrimmer
4
+ VERSION = '0.2.1'
5
+ end