sup 0.19.0 → 0.20.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d330a3455ed22952d8c45fce0f6a0d69346c40f2
4
- data.tar.gz: 337b95be43bc301f6180b542b2395df025f4f1db
3
+ metadata.gz: e7b5ce3c73c1c6d194d8103bb25de84981db2529
4
+ data.tar.gz: a5d0868505c66e8c7974025d5131738d2a436ab6
5
5
  SHA512:
6
- metadata.gz: f538e3054ba742a5fadd296bcb6d29b0295e3ca807a0dfe600d908b3cfa9602697bd4e422ac5bde8facb603fe12784add4709ccc4f5ca9b7b76bf348cec3a6f3
7
- data.tar.gz: 1923d32e3cfc13998e52bc7c53b19482f6a4ed9b13d4e79880a1a6a16d926b26af2e6aaa73d1ea6556a6d2cdaf51aae1979afc51eff01697df9801dd787a45a3
6
+ metadata.gz: 8b44f362bd82be161b1d9451d805af1a9d73d962df4c54196703dec1bbca383fb7bd5f2c0bf6479c1fc57bc27b37ec17a65fc2b24abab838e7f2797bfb64687a
7
+ data.tar.gz: e3a2eaaebf74bec788b18c28be9d9a2bee2b8fa06487780f3199aa7446ec386ac5ffc731595245e40be6423dfc1708bed14fe74ada70eab06097655ccc4fd47a
data/.gitignore CHANGED
@@ -4,6 +4,7 @@
4
4
  *~
5
5
  # artifact
6
6
  pkg/
7
+ man/
7
8
  *.gem
8
9
  # i have accidently added this one one too many times
9
10
  sup-exception-log.txt
@@ -14,4 +15,5 @@ Gemfile.lock
14
15
 
15
16
  # generated file for gnupg test
16
17
  test/gnupg_test_home/random_seed
18
+ test/gnupg_test_home/trustdb.gpg
17
19
 
@@ -0,0 +1,3 @@
1
+ [submodule "doc/wiki"]
2
+ path = doc/wiki
3
+ url = https://github.com/sup-heliotrope/sup.wiki.git
@@ -7,6 +7,7 @@ rvm:
7
7
 
8
8
  before_install:
9
9
  - sudo apt-get update -qq
10
- - sudo apt-get install -qq uuid-dev uuid libncursesw5-dev libncursesw5 gnupg2
10
+ - sudo apt-get install -qq uuid-dev uuid libncursesw5-dev libncursesw5 gnupg2 pandoc
11
+ - git submodule update --init --recursive
11
12
 
12
13
  script: bundle exec rake travis
@@ -13,12 +13,13 @@ Michael Stapelberg <michael at the stapelberg dot des>
13
13
  Eric Sherman <hyperbolist at the gmail dot coms>
14
14
  Tero Tilus <tero at the tilus dot nets>
15
15
  Ben Walton <bwalton at the artsci.utoronto dot cas>
16
+ Scott Bonds <scott at the ggr dot coms>
16
17
  Mike Stipicevic <stipim at the rpi dot edus>
17
18
  Martin Bähr <mbaehr at the societyserver dot orgs>
19
+ Matthieu Rakotojaona <matthieu.rakotojaona at the gmail dot coms>
18
20
  Clint Byrum <clint at the ubuntu dot coms>
19
21
  Wael M. Nasreddine <wael.nasreddine at the gmail dot coms>
20
22
  Marcus Williams <marcus-sup at the bar-coded dot nets>
21
- Matthieu Rakotojaona <matthieu.rakotojaona at the gmail dot coms>
22
23
  Lionel Ott <white.magic at the gmx dot des>
23
24
  Gaudenz Steinlin <gaudenz at the soziologie dot chs>
24
25
  Ingmar Vanhassel <ingmar at the exherbo dot orgs>
@@ -37,25 +38,27 @@ Markus Klinik <mkl at the lambdanaut dot nets>
37
38
  Bo Borgerson <gigabo at the gmail dot coms>
38
39
  Atte Kojo <atte.kojo at the reaktor dot fis>
39
40
  Michael Hamann <michael at the content-space dot des>
40
- William Erik Baxter <web at the superscript dot coms>
41
41
  Jonathan Lassoff <jof at the thejof dot coms>
42
+ William Erik Baxter <web at the superscript dot coms>
42
43
  Grant Hollingworth <grant at the antiflux dot orgs>
43
44
  Ico Doornekamp <ico at the pruts dot nls>
44
45
  Adeodato Simó <dato at the net.com.org dot ess>
45
46
  Daniel Schoepe <daniel.schoepe at the googlemail dot coms>
46
47
  James Taylor <james at the jamestaylor dot orgs>
47
48
  Jason Petsod <jason at the petsod dot orgs>
48
- Robin Burchell <viroteck at the viroteck dot nets>
49
49
  Steve Goldman <sgoldman at the tower-research dot coms>
50
+ Robin Burchell <viroteck at the viroteck dot nets>
50
51
  Peter Harkins <ph at the malaprop dot orgs>
51
52
  Decklin Foster <decklin at the red-bean dot coms>
52
53
  Cameron Matheson <cam+sup at the cammunism dot orgs>
53
54
  Carl Worth <cworth at the cworth dot orgs>
54
55
  Alex Vandiver <alex at the chmrr dot nets>
55
- Andrew Pimlott <andrew at the pimlott dot nets>
56
56
  Jeff Balogh <its.jeff.balogh at the gmail dot coms>
57
+ Andrew Pimlott <andrew at the pimlott dot nets>
57
58
  Matías Aguirre <matiasaguirre at the gmail dot coms>
58
59
  PaulSmecker <paul.smecker at the gmail dot coms>
60
+ Per Andersson <avtobiff at the gmail dot coms>
61
+ Ruthard Baudach <rthrd at the web dot des>
59
62
  Kornilios Kourtis <kkourt at the cslab.ece.ntua dot grs>
60
63
  Lars Fischer <fischer at the wiwi.uni-siegen dot des>
61
64
  madhat2r <MaDhAt2r at the dukefoo dot coms>
@@ -67,18 +70,17 @@ Steven Lawrance <stl at the koffein dot nets>
67
70
  Jonah <Jonah at the GoodCoffee dot cas>
68
71
  ian <itaylor at the uark dot edus>
69
72
  Adam Lloyd <adam at the alloy-d dot nets>
70
- MichaelRevell <mikearevell at the gmail dot coms>
71
- Gregor Hoffleit <gregor at the sam.mediasupervision dot des>
72
73
  Todd Eisenberger <teisenbe at the andrew.cmu dot edus>
73
- Per Andersson <avtobiff at the gmail dot coms>
74
74
  0xACE <0xACE at the users.noreply.github dot coms>
75
+ MichaelRevell <mikearevell at the gmail dot coms>
76
+ Gregor Hoffleit <gregor at the sam.mediasupervision dot des>
75
77
  Steven Schmeiser <steven at the schmeiser dot orgs>
76
78
  Steven Walter <swalter at the monarch.(none)>
77
79
  Jon M. Dugan <jdugan at the es dot nets>
78
- akojo <atte.kojo at the gmail dot coms>
79
- Matthias Vallentin <vallentin at the icir dot orgs>
80
- William A. Kennington III <william at the wkennington dot coms>
81
80
  Horacio Sanson <horacio at the skillupjapan.co dot jps>
82
81
  Stefan Lundström <lundst at the snabb.(none)>
82
+ William A. Kennington III <william at the wkennington dot coms>
83
+ akojo <atte.kojo at the gmail dot coms>
84
+ Matthias Vallentin <vallentin at the icir dot orgs>
83
85
  Johannes Larsen <johs.a.larsen at the gmail dot coms>
84
86
  Kirill Smelkov <kirr at the landau.phys.spbu dot rus>
data/Gemfile CHANGED
@@ -1,3 +1,7 @@
1
1
  source 'https://rubygems.org/'
2
2
 
3
+ if !RbConfig::CONFIG['arch'].include?('openbsd')
4
+ gem 'xapian-ruby', '~> 1.2.15'
5
+ end
6
+
3
7
  gemspec
@@ -1,3 +1,16 @@
1
+ == 0.20.0 / 2014-10-06
2
+
3
+ * add man-pages (generated from wiki) (Per Andersson)!
4
+ * HTML messages or messages that are decoded with the mime-decode hook
5
+ are now indexed if the mime-decode hook is set up (Scott Bonds).
6
+ * OpenBSD support (Scott Bonds)!
7
+ * goto-hook for keybinding to open URLs.
8
+ * support special charaters in source URIs (Scott Bonds).
9
+ * output message id and locations on all load_from_source failures
10
+ * fix long-standing getlocal bug
11
+ * make new test GPG keys (old ones expired), valid for one year, script
12
+ now available in devel/ for making new ones.
13
+
1
14
  == 0.19.0 / 2014-07-05
2
15
 
3
16
  * new check-attachment hook
data/Rakefile CHANGED
@@ -9,4 +9,45 @@ Rake::TestTask.new(:test) do |test|
9
9
  end
10
10
  task :default => :test
11
11
 
12
+ task :build => [:man]
12
13
  task :travis => [:test, :build]
14
+
15
+ def test_pandoc
16
+ return system("pandoc -v > /dev/null 2>&1")
17
+ end
18
+
19
+ task :man do
20
+ puts "building manpages from wiki.."
21
+ unless test_pandoc
22
+ puts "no pandoc installed, needed for manpage generation."
23
+ return
24
+ end
25
+
26
+ # test if wiki is cloned
27
+ unless Dir.exist? 'doc/wiki/man'
28
+ puts "wiki git repository is not cloned in doc/wiki, try: git submodule update --init."
29
+ return
30
+ end
31
+
32
+ unless Dir.exist? 'man'
33
+ Dir.mkdir 'man'
34
+ end
35
+
36
+ Dir.glob("doc/wiki/man/*.md").each do |md|
37
+ m = /^.*\/(?<manpage>[^\/]*)\.md$/.match(md)[:manpage]
38
+ puts "generating manpage for: #{m}.."
39
+ r = system "pandoc -s -f markdown -t man #{md} -o man/#{m}"
40
+
41
+ unless r
42
+ puts "failed to generate manpage: #{m}."
43
+ return
44
+ end
45
+ end
46
+ end
47
+
48
+ task :clean do
49
+ ['man', 'pkg'].each do |d|
50
+ puts "cleaning #{d}.."
51
+ FileUtils.rm_r d if Dir.exist? d
52
+ end
53
+ end
@@ -1,3 +1,13 @@
1
+ Release 0.20.0:
2
+
3
+ We've got man pages (Mr. Andersson)! We've got OpenBSD support (Scott Bonds)!
4
+ It is now possible to get your HTML emails indexed by setting up a mime-decode
5
+ hook before you index (Scott Bonds)! Scott Bonds also fixed up special character handing in source URIs. It is now possible to set up a goto hook
6
+ for opening the URL below the cursor.
7
+
8
+ Also a few long standing bugs have been fixed, and new GPG keys have been made
9
+ for the tests.
10
+
1
11
  Release 0.19.0:
2
12
 
3
13
  New hook: check-attachment and a new option to shows dates in 24h format.
data/bin/sup CHANGED
@@ -106,26 +106,28 @@ end
106
106
  ## ncurses.so that's been compiled against libncursesw. (note the w.) why
107
107
  ## this works, i have no idea. much like pretty much every aspect of
108
108
  ## dealing with curses. cargo cult programming at its best.
109
- require 'dl/import'
110
109
  require 'rbconfig'
111
- module LibC
112
- extend DL.const_defined?(:Importer) ? DL::Importer : DL::Importable
113
- setlocale_lib = case RbConfig::CONFIG['arch']
114
- when /darwin/; "libc.dylib"
115
- when /cygwin/; "cygwin1.dll"
116
- when /freebsd/; "libc.so.7"
117
- else; "libc.so.6"
118
- end
110
+ unless RbConfig::CONFIG['arch'] =~ /openbsd/
111
+ require 'dl/import'
112
+ module LibC
113
+ extend DL.const_defined?(:Importer) ? DL::Importer : DL::Importable
114
+ setlocale_lib = case RbConfig::CONFIG['arch']
115
+ when /darwin/; "libc.dylib"
116
+ when /cygwin/; "cygwin1.dll"
117
+ when /freebsd/; "libc.so.7"
118
+ else; "libc.so.6"
119
+ end
119
120
 
120
- debug "dynamically loading setlocale() from #{setlocale_lib}"
121
- begin
122
- dlload setlocale_lib
123
- extern "void setlocale(int, const char *)"
124
- debug "setting locale..."
125
- LibC.setlocale(6, "") # LC_ALL == 6
126
- rescue RuntimeError => e
127
- warn "cannot dlload setlocale(); ncurses wide character support probably broken."
128
- warn "dlload error was #{e.class}: #{e.message}"
121
+ debug "dynamically loading setlocale() from #{setlocale_lib}"
122
+ begin
123
+ dlload setlocale_lib
124
+ extern "void setlocale(int, const char *)"
125
+ debug "setting locale..."
126
+ LibC.setlocale(6, "") # LC_ALL == 6
127
+ rescue RuntimeError => e
128
+ warn "cannot dlload setlocale(); ncurses wide character support probably broken."
129
+ warn "dlload error was #{e.class}: #{e.message}"
130
+ end
129
131
  end
130
132
  end
131
133
 
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rubygems/command.rb'
3
+ require 'rubygems/dependency_installer.rb'
4
+ require 'rbconfig'
5
+
6
+ begin
7
+ Gem::Command.build_args = ARGV
8
+ rescue NoMethodError
9
+ end
10
+
11
+ puts "xapian: platform specific dependencies.."
12
+
13
+ inst = Gem::DependencyInstaller.new
14
+ begin
15
+
16
+ if !RbConfig::CONFIG['arch'].include?('openbsd')
17
+ # update version in Gemfile as well
18
+ name = "xapian-ruby"
19
+ version = "~> 1.2.15"
20
+
21
+ begin
22
+ # try to load gem
23
+
24
+ gem name, version
25
+ STDERR.puts "xapian: already installed."
26
+
27
+ rescue Gem::LoadError
28
+
29
+ STDERR.puts "xapian: installing xapian-ruby.."
30
+ inst.install name, version
31
+
32
+ end
33
+ else
34
+ STDERR.puts "xapian: openbsd: you have to install xapian-core and xapian-bindings manually, have a look at: https://github.com/sup-heliotrope/sup/wiki/Installation%3A-OpenBSD"
35
+ end
36
+
37
+ rescue
38
+
39
+ exit(1)
40
+
41
+ end
42
+
43
+ # create dummy rakefile to indicate success
44
+ f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
45
+ f.write("task :default\n")
46
+ f.close
47
+
data/lib/sup.rb CHANGED
@@ -8,6 +8,7 @@ require 'fileutils'
8
8
  require 'locale'
9
9
  require 'ncursesw'
10
10
  require 'rmail'
11
+ require 'uri'
11
12
  begin
12
13
  require 'fastthread'
13
14
  rescue LoadError
@@ -64,6 +65,7 @@ module Redwood
64
65
  LEGACY_YAML_DOMAIN = "masanjin.net"
65
66
  YAML_DATE = "2006-10-01"
66
67
  MAILDIR_SYNC_CHECK_SKIPPED = 'SKIPPED'
68
+ URI_ENCODE_CHARS = "!*'();:@&=+$,?#[] " # see https://en.wikipedia.org/wiki/Percent-encoding
67
69
 
68
70
  ## record exceptions thrown in threads nicely
69
71
  @exceptions = []
@@ -396,6 +396,18 @@ EOS
396
396
  end
397
397
  end
398
398
 
399
+ ## ask* functions. these functions display a one-line text field with
400
+ ## a prompt at the bottom of the screen. answers typed or choosen by
401
+ ## tab-completion
402
+ ##
403
+ ## common arguments are:
404
+ ##
405
+ ## domain: token used as key for @textfields, which seems to be a
406
+ ## dictionary of input field objects
407
+ ## question: string used as prompt
408
+ ## completions: array of possible answers, that can be completed by using
409
+ ## the tab key
410
+ ## default: default value to return
399
411
  def ask_with_completions domain, question, completions, default=nil
400
412
  ask domain, question, default do |s|
401
413
  s.fix_encoding!
@@ -12,7 +12,15 @@ class Maildir < Source
12
12
  def initialize uri, usual=true, archived=false, sync_back=true, id=nil, labels=[]
13
13
  super uri, usual, archived, id
14
14
  @expanded_uri = Source.expand_filesystem_uri(uri)
15
- uri = URI(@expanded_uri)
15
+ parts = @expanded_uri.match /^([a-zA-Z0-9]*:(\/\/)?)(.*)/
16
+ if parts
17
+ prefix = parts[1]
18
+ @path = parts[3]
19
+ uri = URI(prefix + URI.encode(@path, URI_ENCODE_CHARS))
20
+ else
21
+ uri = URI(URI.encode @expanded_uri, URI_ENCODE_CHARS)
22
+ @path = uri.path
23
+ end
16
24
 
17
25
  raise ArgumentError, "not a maildir URI" unless uri.scheme == "maildir"
18
26
  raise ArgumentError, "maildir URI cannot have a host: #{uri.host}" if uri.host
@@ -22,7 +30,7 @@ class Maildir < Source
22
30
  # sync by default if not specified
23
31
  @sync_back = true if @sync_back.nil?
24
32
 
25
- @dir = uri.path
33
+ @dir = URI.decode uri.path
26
34
  @labels = Set.new(labels || [])
27
35
  @mutex = Mutex.new
28
36
  @ctimes = { 'cur' => Time.at(0), 'new' => Time.at(0) }
@@ -120,7 +128,10 @@ class Maildir < Source
120
128
  @ctimes[d] = ctime
121
129
 
122
130
  old_ids = benchmark(:maildir_read_index) { Index.instance.enum_for(:each_source_info, self.id, "#{d}/").to_a }
123
- new_ids = benchmark(:maildir_read_dir) { Dir.glob("#{subdir}/*").map { |x| File.join(d,File.basename(x)) }.sort }
131
+ new_ids = benchmark(:maildir_read_dir) {
132
+ Dir.open(subdir).select {
133
+ |f| !File.directory? f}.map {
134
+ |x| File.join(d,File.basename(x)) }.sort }
124
135
  added += new_ids - old_ids
125
136
  deleted += old_ids - new_ids
126
137
  debug "#{old_ids.size} in index, #{new_ids.size} in filesystem"
@@ -19,16 +19,24 @@ class MBox < Source
19
19
  case uri_or_fp
20
20
  when String
21
21
  @expanded_uri = Source.expand_filesystem_uri(uri_or_fp)
22
- uri = URI(@expanded_uri)
22
+ parts = @expanded_uri.match /^([a-zA-Z0-9]*:(\/\/)?)(.*)/
23
+ if parts
24
+ prefix = parts[1]
25
+ @path = parts[3]
26
+ uri = URI(prefix + URI.encode(@path, URI_ENCODE_CHARS))
27
+ else
28
+ uri = URI(URI.encode @expanded_uri, URI_ENCODE_CHARS)
29
+ @path = uri.path
30
+ end
31
+
23
32
  raise ArgumentError, "not an mbox uri" unless uri.scheme == "mbox"
24
33
  raise ArgumentError, "mbox URI ('#{uri}') cannot have a host: #{uri.host}" if uri.host
25
34
  raise ArgumentError, "mbox URI must have a path component" unless uri.path
26
35
  @f = nil
27
- @path = uri.path
28
36
  else
29
37
  @f = uri_or_fp
30
38
  @path = uri_or_fp.path
31
- @expanded_uri = "mbox://#{@path}"
39
+ @expanded_uri = "mbox://#{URI.encode @path, URI_ENCODE_CHARS}"
32
40
  end
33
41
 
34
42
  super uri_or_fp, usual, archived, id
@@ -268,6 +268,14 @@ class Message
268
268
  debug "could not load message: #{location.inspect}, exception: #{e.inspect}"
269
269
 
270
270
  [Chunk::Text.new(error_message.split("\n"))]
271
+
272
+ rescue Exception => e
273
+
274
+ warn "problem reading message #{id}"
275
+ debug "could not load message: #{location.inspect}, exception: #{e.inspect}"
276
+
277
+ raise e
278
+
271
279
  end
272
280
  end
273
281
 
@@ -327,17 +335,17 @@ EOS
327
335
  to.map { |p| p.indexable_content },
328
336
  cc.map { |p| p.indexable_content },
329
337
  bcc.map { |p| p.indexable_content },
330
- indexable_chunks.map { |c| c.lines },
338
+ indexable_chunks.map { |c| c.lines.map { |l| l.fix_encoding! } },
331
339
  indexable_subject,
332
340
  ].flatten.compact.join " "
333
341
  end
334
342
 
335
343
  def indexable_body
336
- indexable_chunks.map { |c| c.lines }.flatten.compact.join " "
344
+ indexable_chunks.map { |c| c.lines }.flatten.compact.map { |l| l.fix_encoding! }.join " "
337
345
  end
338
346
 
339
347
  def indexable_chunks
340
- chunks.select { |c| c.is_a? Chunk::Text } || []
348
+ chunks.select { |c| c.indexable? } || []
341
349
  end
342
350
 
343
351
  def indexable_subject
@@ -164,6 +164,7 @@ EOS
164
164
  ## something we can display inline. otherwise, it's viewable.
165
165
  def inlineable?; false end
166
166
  def expandable?; !viewable? end
167
+ def indexable?; expandable? end
167
168
  def initial_state; :open end
168
169
  def viewable?; @lines.nil? end
169
170
  def view_default! path
@@ -229,6 +230,7 @@ EOS
229
230
  def inlineable?; true end
230
231
  def quotable?; true end
231
232
  def expandable?; false end
233
+ def indexable?; true end
232
234
  def viewable?; false end
233
235
  def color; :text_color end
234
236
  end
@@ -242,6 +244,7 @@ EOS
242
244
  def inlineable?; @lines.length == 1 end
243
245
  def quotable?; true end
244
246
  def expandable?; !inlineable? end
247
+ def indexable?; expandable? end
245
248
  def viewable?; false end
246
249
 
247
250
  def patina_color; :quote_patina_color end
@@ -258,6 +261,7 @@ EOS
258
261
  def inlineable?; @lines.length == 1 end
259
262
  def quotable?; false end
260
263
  def expandable?; !inlineable? end
264
+ def indexable?; expandable? end
261
265
  def viewable?; false end
262
266
 
263
267
  def patina_color; :sig_patina_color end
@@ -291,6 +295,7 @@ EOS
291
295
  def inlineable?; false end
292
296
  def quotable?; false end
293
297
  def expandable?; true end
298
+ def indexable?; true end
294
299
  def initial_state; :closed end
295
300
  def viewable?; false end
296
301
 
@@ -322,6 +327,7 @@ EOS
322
327
  def inlineable?; false end
323
328
  def quotable?; false end
324
329
  def expandable?; !@lines.empty? end
330
+ def indexable?; false end
325
331
  def viewable?; false end
326
332
  end
327
333
  end
@@ -20,6 +20,7 @@ Variables:
20
20
  to the raw headers for the message. E.g., header["From"],
21
21
  header["To"], etc.
22
22
  from_email: the email part of the From: line, or nil if empty
23
+ message_id: the unique message id of the message
23
24
  Return value:
24
25
  A string (multi-line ok) containing the text of the signature, or nil to
25
26
  use the default signature, or :none for no signature.
@@ -688,7 +689,7 @@ private
688
689
  from_email = p && p.email
689
690
 
690
691
  ## first run the hook
691
- hook_sig = HookManager.run "signature", :header => @header, :from_email => from_email
692
+ hook_sig = HookManager.run "signature", :header => @header, :from_email => from_email, :message_id => @message_id
692
693
 
693
694
  return [] if hook_sig == :none
694
695
  return ["", "-- "] + hook_sig.split("\n") if hook_sig
@@ -856,6 +856,12 @@ protected
856
856
  need_update = false
857
857
 
858
858
  @mutex.synchronize do
859
+ # and certainly not sure why this happens..
860
+ #
861
+ # probably a race condition between thread modification and updating
862
+ # going on.
863
+ return if @threads[l].empty?
864
+
859
865
  @size_widgets[l] = size_widget_for_thread @threads[l]
860
866
  @date_widgets[l] = date_widget_for_thread @threads[l]
861
867
 
@@ -42,6 +42,14 @@ Return value:
42
42
  None.
43
43
  EOS
44
44
 
45
+ HookManager.register "goto", <<EOS
46
+ Open the uri given as a parameter.
47
+ Variables:
48
+ uri: The uri
49
+ Return value:
50
+ None.
51
+ EOS
52
+
45
53
  register_keymap do |k|
46
54
  k.add :toggle_detailed_header, "Toggle detailed header", 'h'
47
55
  k.add :show_header, "Show full message header", 'H'
@@ -80,6 +88,8 @@ EOS
80
88
  k.add :kill_and_next, "Kill this thread, kill buffer, and view next", '&'
81
89
  k.add :toggle_wrap, "Toggle wrapping of text", 'w'
82
90
 
91
+ k.add :goto_uri, "Goto uri under cursor", 'g'
92
+
83
93
  k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
84
94
  kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
85
95
  kk.add :delete_and_kill, "Delete this thread and kill buffer", 'd'
@@ -722,6 +732,48 @@ EOS
722
732
  [user_labels, super].join(" -- ")
723
733
  end
724
734
 
735
+ def goto_uri
736
+ unless (chunk = @chunk_lines[curpos])
737
+ BufferManager.flash "No URI found."
738
+ return
739
+ end
740
+ unless HookManager.enabled? "goto"
741
+ BufferManager.flash "You must add a goto.rb hook before you can goto a URI."
742
+ return
743
+ end
744
+
745
+ # @text is a list of lines with this format:
746
+ # [
747
+ # [[:text_color, "Some text"]]
748
+ # [[:text_color, " continued here"]]
749
+ # ]
750
+
751
+ linetext = @text.slice(curpos, @text.length).flatten(1)
752
+ .take_while{|d| d[0] == :text_color and d[1].strip != ""} # Only take up to the first "" alone on its line
753
+ .map{|d| d[1].strip}.join("").strip
754
+
755
+ found = false
756
+ (linetext || "").scan(URI::regexp).each do |matches|
757
+ begin
758
+ link = $& # ruby magic: $& is the whole regexp match
759
+ u = URI.parse(link)
760
+ next unless u.absolute?
761
+ next unless ["http", "https"].include?(u.scheme)
762
+
763
+ reallink = Shellwords.escape(u.to_s)
764
+ BufferManager.flash "Going to #{reallink} ..."
765
+ HookManager.run "goto", :uri => reallink
766
+ BufferManager.completely_redraw_screen
767
+ found = true
768
+
769
+ rescue URI::InvalidURIError => e
770
+ debug "not a uri: #{e}"
771
+ # Do nothing, this is an ok flow
772
+ end
773
+ end
774
+ BufferManager.flash "No URI found." unless found
775
+ end
776
+
725
777
  private
726
778
 
727
779
  def initial_state_for m
@@ -1,3 +1,3 @@
1
1
  module Redwood
2
- VERSION = "0.19.0"
2
+ VERSION = "0.20.0"
3
3
  end
@@ -25,16 +25,31 @@ DESC
25
25
  SUP: please note that our old mailing lists have been shut down,
26
26
  re-subscribe to supmua@googlegroups.com to discuss and follow
27
27
  updates on sup (send email to: supmua+subscribe@googlegroups.com).
28
+
29
+ OpenBSD users:
30
+ If your operating system is OpenBSD you have some
31
+ additional, manual steps to do before Sup will work, see:
32
+ https://github.com/sup-heliotrope/sup/wiki/Installation%3A-OpenBSD.
28
33
  EOF
29
34
 
30
35
  s.files = `git ls-files -z`.split("\x0")
31
36
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
32
37
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
33
38
  s.require_paths = ["lib"]
39
+ s.extra_rdoc_files = Dir.glob("man/*")
34
40
 
35
41
  s.required_ruby_version = '>= 1.9.3'
36
42
 
37
- s.add_runtime_dependency "xapian-ruby", "~> 1.2.15"
43
+ # this is here to support skipping the xapian-ruby installation on OpenBSD
44
+ # because the xapian-ruby gem doesn't install on OpenBSD, you must install
45
+ # xapian-core and xapian-bindings manually on OpenBSD
46
+ # see https://github.com/sup-heliotrope/sup/wiki/Installation%3A-OpenBSD
47
+ # and https://en.wikibooks.org/wiki/Ruby_Programming/RubyGems#How_to_install_different_versions_of_gems_depending_on_which_version_of_ruby_the_installee_is_using
48
+ s.extensions = %w[ext/mkrf_conf_xapian.rb]
49
+
50
+ ## remember to update the xapian dependency in
51
+ ## ext/mkrf_conf_xapian.rb and Gemfile.
52
+
38
53
  s.add_runtime_dependency "ncursesw", "~> 1.4.0"
39
54
  s.add_runtime_dependency "rmail-sup", "~> 1.0.1"
40
55
  s.add_runtime_dependency "highline"
@@ -50,4 +65,5 @@ SUP: please note that our old mailing lists have been shut down,
50
65
  s.add_development_dependency "minitest", "~> 4.7"
51
66
  s.add_development_dependency "rr", "~> 1.0.5"
52
67
  s.add_development_dependency "gpgme", ">= 2.0.2"
68
+
53
69
  end
@@ -1 +1,2 @@
1
- default-key 789E7011
1
+ trust-model always
2
+
@@ -0,0 +1,15 @@
1
+ %echo Generating a standard key
2
+ Key-Type: DSA
3
+ Key-Length: 1024
4
+ Subkey-Type: ELG-E
5
+ Subkey-Length: 1024
6
+ Name-Real: Sup Test Sender 1
7
+ Name-Comment: Test sender key
8
+ Name-Email: sup-test-1@foo.bar
9
+ Expire-Date: 1y
10
+ %no-protection
11
+ %pubring pubring.gpg
12
+ %secring secring.gpg
13
+ # Do a commit here, so that we can later print "done" :-)
14
+ %commit
15
+ %echo done
@@ -0,0 +1,15 @@
1
+ %echo Generating a standard key
2
+ Key-Type: DSA
3
+ Key-Length: 1024
4
+ Subkey-Type: ELG-E
5
+ Subkey-Length: 1024
6
+ Name-Real: Sup Test Receiver
7
+ Name-Comment: Test receiver for Sup
8
+ Name-Email: sup-test-2@foo.bar
9
+ Expire-Date: 1y
10
+ %no-protection
11
+ %pubring pubring.gpg
12
+ %secring secring.gpg
13
+ # Do a commit here, so that we can later print "done" :-)
14
+ %commit
15
+ %echo done
@@ -0,0 +1,35 @@
1
+ #! /bin/bash
2
+ #
3
+ # re-generate test keys for the sup test base
4
+ #
5
+ # https://github.com/sup-heliotrope/sup/wiki/Development%3A-Crypto
6
+
7
+ pushd $(dirname $0)
8
+
9
+ export GNUPGHOME="$(pwd)"
10
+
11
+ echo "genrating keys in: $GNUPGHOME.."
12
+
13
+ rm *.gpg *.asc
14
+
15
+ echo "generate receiver key.."
16
+ gpg --batch --gen-key key2.gen
17
+
18
+ echo "export receiver key.."
19
+
20
+ gpg --output sup-test-2@foo.bar.asc --armor --export sup-test-2@foo.bar
21
+
22
+ mv trustdb.gpg receiver_trustdb.gpg
23
+ mv secring.gpg receiver_secring.gpg
24
+ mv pubring.gpg receiver_pubring.gpg
25
+
26
+ echo "generate sender key.."
27
+ gpg --batch --gen-key key1.gen
28
+
29
+ echo "import receiver key.."
30
+ gpg --import sup-test-2@foo.bar.asc
31
+
32
+
33
+
34
+ popd
35
+
@@ -1,20 +1,25 @@
1
1
  -----BEGIN PGP PUBLIC KEY BLOCK-----
2
- Version: GnuPG v2.0.20 (GNU/Linux)
2
+ Version: GnuPG v2
3
3
 
4
- mI0EUgi0fAEEAOLAcQW96NEUSB7YE/la8X56jGW5BMX3aAixOF8LvOwMBbUK1T+U
5
- 0H2PGIrXVcYyHcPqWRpRahbsIAldBqzffPlzMa+aqJaB1xKkNruxSoIzwPdidZMe
6
- l0Dxz2FDsoXD0KPyWnAYhGmQyz2MFpZxu2tlYqvwWVW//XGnk/KHvIXbABEBAAG0
7
- PlN1cCBUZXN0IFJlY2VpdmVyIChUZXN0IHJlY2VpdmVyIGZvciBTdXApIDxzdXAt
8
- dGVzdC0yQGZvby5iYXI+iL8EEwECACkFAlIItHwCGwMFCQHhM4AHCwkIBwMCAQYV
9
- CAIJCgsEFgIDAQIeAQIXgAAKCRAsABl+cWpykMMVBADHkQPgTz0CqKKp3k+z3dbm
10
- ocmI4tYNn1dOkDQqyfoBTfs6L3g4j5OE2UrguntRYyg5oon+uO5d18CQ5dY0sCw/
11
- o5IwyzTrxI8IocbtZvBdSb+XjLndynGuIQoqaJq9i6n1V4klFHVOna8Q9JstLfRX
12
- H1d4xPhnvKcaDDx/NV3X/biNBFIItHwBBADBpb43MpkrUWlg7HWJ1ZfOlxnOxrJ3
13
- Gz9WFNV06UbcZEuFKA/vHRjM6gWzUn5903FLuCWu3eBrq5xQfWipbp187PmocpoG
14
- skJ6gosLs1fMYRBjv2VbG9xJVKdKJMjqZw5FUpXKAaHr8P9jN6g2STQrbeQ8CVUK
15
- h7zOWRXAXSKUgwARAQABiKUEGAECAA8FAlIItHwCGwwFCQHhM4AACgkQLAAZfnFq
16
- cpDV1QQAzcxFXznEX92DjWxWRC7gRHgIsQk9WJnDzjtnDjSWCp3H85qeTZGZrn9W
17
- NoneV/S5Y7K3Mkceh4rFaANQ3zx4b05y1LFt5N/lPwIe5VB0vcPumtZum2fSGfpK
18
- nTXvzelcWcm2aGyUSaWvOkntWKEEt1kB5Oq6EtZoRZLMzAxLd7s=
19
- =aKsV
4
+ mQGiBFP3VogRBADVBEkaZQXj728C1HUIaTRDCFoKzojwC79Z1BLsD72qQYE8z1ic
5
+ 5P9CJpJU5wbhQFDTGBjw+i1nNTWy01z4q5bfFqok+KorT3XNp5IJRcRIEOkj+Twq
6
+ 7ZaSODwXGsUmdzSoOVDYmtUpVzRQe0IM0rPQQV4vGzgw55FdJBe7a63nIwCg+WvR
7
+ iQN09PlhpGG7SIEmx0psEqUEAL/t1c5oC9RC7L4a0GM+2AcgFRBMXvzpdnytrzgt
8
+ 73Ud6CcUplQp6WODrUYhX0RLzSJPO4zWDsBmkBad/iQCwbCKpFPfAFdBMArJpknx
9
+ rc6vRED4a9dLfCNTT1g86CkiElge9t36juZgOoFT3xt/XP7BxhU1fCFshZNR6VK6
10
+ tN9eA/9G4fUX6XvEGIrNiBYKyU4QvM1nyMXCBujm7vYF6KfSlYyAvVXxG4h+mvUy
11
+ ZXQ/WHMQJSbPTY3dd4hmo0p0GUMlSvXU8JLf7qienW1IccD9Pv88J1XjkbFd+wgw
12
+ feoSx1sAfc36gH+aE17lvsU+PPAP4Bc9CSiScNo0iQv7v/KZjrQ+U3VwIFRlc3Qg
13
+ UmVjZWl2ZXIgKFRlc3QgcmVjZWl2ZXIgZm9yIFN1cCkgPHN1cC10ZXN0LTJAZm9v
14
+ LmJhcj6IaQQTEQIAKQUCU/dWiAIbIwUJAeEzgAcLCQgHAwIBBhUIAgkKCwQWAgMB
15
+ Ah4BAheAAAoJEKfs+g8ACvQGPxIAnj1CSZCzjwyIFLgNEQnIhntU+b28AKDsMEVN
16
+ gf9mHqwhabN+UKgBwX0U3LkBDQRT91aIEAQAjQZEnDK++SKp/l2Oiku6H9IuCsi4
17
+ lv+MhLQP0bMuD4DrPk3mauZNc8BB+U0wgAMh/kZoCKySEdMK1mcf2iOsd5yOCrK+
18
+ sJQAMsALAnrYjCE9QA2xIQs8gHF4PrKopycF55iRHQMDNa1QWfs+j4WJaXderlGQ
19
+ S0dGfLyoqtZsFusAAwUEAIi0+aDZlAVVIdDO2cvR0lu6eDW2Mr2ExZzuwTfAI6dS
20
+ tJLoPzoA2OAVW7cFVVpCOHcVLiF2GOHvtJPw1MgpxaNjzpNdJPTiP2sYZg253dfR
21
+ v66Cw9IuWKgZcElWXmIy5vFWqWWbLyTBOuwEQxCsFnjN9UUZauSADOJSPFy1sekf
22
+ iE8EGBECAA8FAlP3VogCGwwFCQHhM4AACgkQp+z6DwAK9Ab/swCg8LWNwfMwNk+H
23
+ gLgnS1LVsesZ8D4An2Ie2P0/oYuSmPPFV44kbWySX9wW
24
+ =Jo82
20
25
  -----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,75 @@
1
+ require "test_helper"
2
+
3
+ class TestMaildir < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @path = Dir.mktmpdir
7
+
8
+ @test_message_1 = <<EOS
9
+ From: Bob <bob@bob.com>
10
+ To: a dear friend
11
+
12
+ Hello there friend. How are you? Blah is blah blah.
13
+ Wow. Maildir FTW, am I right?
14
+ EOS
15
+
16
+ end
17
+
18
+ def teardown
19
+ ObjectSpace.each_object(Class).select {|a| a < Redwood::Singleton}.each do |klass|
20
+ klass.deinstantiate! unless klass == Redwood::Logger
21
+ end
22
+ FileUtils.rm_r @path
23
+ end
24
+
25
+ def create_a_maildir(extra='')
26
+ maildir = File.join @path, "test_maildir#{extra}"
27
+ ['', 'cur', 'new', 'tmp'].each do |dir|
28
+ Dir.mkdir(File.join maildir, dir)
29
+ end
30
+ maildir
31
+ end
32
+
33
+ def create_a_maildir_email(folder, content)
34
+ File.write(File.join(folder, "#{Time.now.to_f}.hostname:2,S"), content)
35
+ end
36
+
37
+ def start_sup_and_add_source(source)
38
+ start
39
+ Index.init @path
40
+ Index.load
41
+ SourceManager.instance.instance_eval '@sources = {}'
42
+ SourceManager.instance.add_source source
43
+ PollManager.poll_from source
44
+ end
45
+
46
+ # and now, let the tests begin!
47
+
48
+ def test_can_index_a_maildir_directory
49
+
50
+ maildir = create_a_maildir
51
+ create_a_maildir_email(File.join(maildir, 'cur'), @test_message_1)
52
+ start_sup_and_add_source Maildir.new "maildir:#{maildir}"
53
+
54
+ messages_in_index = []
55
+ Index.instance.each_message {|a| messages_in_index << a}
56
+ refute_empty messages_in_index, 'There are no messages in the index'
57
+ assert_equal(messages_in_index.first.raw_message, @test_message_1)
58
+
59
+ end
60
+
61
+ def test_can_index_a_maildir_directory_with_special_characters
62
+
63
+ maildir = create_a_maildir URI_ENCODE_CHARS
64
+ create_a_maildir_email(File.join(maildir, 'cur'), @test_message_1)
65
+ start_sup_and_add_source Maildir.new "maildir:#{maildir}"
66
+
67
+ messages_in_index = []
68
+ Index.instance.each_message {|a| messages_in_index << a}
69
+ refute_empty messages_in_index, 'There are no messages in the index'
70
+ assert_equal(messages_in_index.first.raw_message, @test_message_1)
71
+
72
+ end
73
+
74
+ end
75
+
@@ -0,0 +1,69 @@
1
+ require "test_helper"
2
+
3
+ class TestMbox < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @path = Dir.mktmpdir
7
+
8
+ @test_message_1 = <<EOS
9
+ From sup-talk-bounces@rubyforge.org Mon Apr 27 12:56:18 2009
10
+ From: Bob <bob@bob.com>
11
+ To: Joe <joe@joe.com>
12
+
13
+ Hello there friend. How are you? Blah is blah blah.
14
+ I like mboxes, don't you?
15
+ EOS
16
+
17
+ end
18
+
19
+ def teardown
20
+ ObjectSpace.each_object(Class).select {|a| a < Redwood::Singleton}.each do |klass|
21
+ klass.deinstantiate! unless klass == Redwood::Logger
22
+ end
23
+ FileUtils.rm_r @path
24
+ end
25
+
26
+ def create_a_mbox(extra='')
27
+ mbox = File.join(@path, "test_mbox#{extra}.mbox")
28
+ File.write(mbox, @test_message_1)
29
+ mbox
30
+ end
31
+
32
+ def start_sup_and_add_source(source)
33
+ start
34
+ Index.init @path
35
+ Index.load
36
+ SourceManager.instance.instance_eval '@sources = {}'
37
+ SourceManager.instance.add_source source
38
+ PollManager.poll_from source
39
+ end
40
+
41
+ # and now, let the tests begin!
42
+
43
+ def test_can_index_a_mbox_directory
44
+
45
+ mbox = create_a_mbox
46
+ start_sup_and_add_source MBox.new "mbox:#{mbox}"
47
+
48
+ messages_in_index = []
49
+ Index.instance.each_message {|a| messages_in_index << a}
50
+ refute_empty messages_in_index, 'There are no messages in the index'
51
+ test_message_without_first_line = @test_message_1.sub(/^.*\n/,'')
52
+ assert_equal(messages_in_index.first.raw_message, test_message_without_first_line)
53
+
54
+ end
55
+
56
+ def test_can_index_a_mbox_directory_with_special_characters
57
+
58
+ mbox = create_a_mbox URI_ENCODE_CHARS
59
+ start_sup_and_add_source MBox.new "mbox:#{mbox}"
60
+
61
+ messages_in_index = []
62
+ Index.instance.each_message {|a| messages_in_index << a}
63
+ refute_empty messages_in_index, 'There are no messages in the index'
64
+ test_message_without_first_line = @test_message_1.sub(/^.*\n/,'')
65
+ assert_equal(messages_in_index.first.raw_message, test_message_without_first_line)
66
+
67
+ end
68
+
69
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Morgan
@@ -11,22 +11,8 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-07-05 00:00:00.000000000 Z
14
+ date: 2014-10-06 00:00:00.000000000 Z
15
15
  dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: xapian-ruby
18
- requirement: !ruby/object:Gem::Requirement
19
- requirements:
20
- - - "~>"
21
- - !ruby/object:Gem::Version
22
- version: 1.2.15
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: 1.2.15
30
16
  - !ruby/object:Gem::Dependency
31
17
  name: ncursesw
32
18
  requirement: !ruby/object:Gem::Requirement
@@ -244,10 +230,22 @@ executables:
244
230
  - sup-sync
245
231
  - sup-sync-back-maildir
246
232
  - sup-tweak-labels
247
- extensions: []
248
- extra_rdoc_files: []
233
+ extensions:
234
+ - ext/mkrf_conf_xapian.rb
235
+ extra_rdoc_files:
236
+ - man/sup-tweak-labels.1
237
+ - man/sup-sync.1
238
+ - man/sup-psych-ify-config-files.1
239
+ - man/sup-config.1
240
+ - man/sup-import-dump.1
241
+ - man/sup-dump.1
242
+ - man/sup-sync-back-maildir.1
243
+ - man/sup-add.1
244
+ - man/sup-recover-sources.1
245
+ - man/sup.1
249
246
  files:
250
247
  - ".gitignore"
248
+ - ".gitmodules"
251
249
  - ".travis.yml"
252
250
  - CONTRIBUTORS
253
251
  - Gemfile
@@ -277,6 +275,7 @@ files:
277
275
  - doc/FAQ.txt
278
276
  - doc/Hooks.txt
279
277
  - doc/Philosophy.txt
278
+ - ext/mkrf_conf_xapian.rb
280
279
  - lib/sup.rb
281
280
  - lib/sup/account.rb
282
281
  - lib/sup/buffer.rb
@@ -342,17 +341,30 @@ files:
342
341
  - lib/sup/util/query.rb
343
342
  - lib/sup/util/uri.rb
344
343
  - lib/sup/version.rb
344
+ - man/sup-add.1
345
+ - man/sup-config.1
346
+ - man/sup-dump.1
347
+ - man/sup-import-dump.1
348
+ - man/sup-psych-ify-config-files.1
349
+ - man/sup-recover-sources.1
350
+ - man/sup-sync-back-maildir.1
351
+ - man/sup-sync.1
352
+ - man/sup-tweak-labels.1
353
+ - man/sup.1
345
354
  - sup.gemspec
346
355
  - test/dummy_source.rb
347
356
  - test/gnupg_test_home/gpg.conf
357
+ - test/gnupg_test_home/key1.gen
358
+ - test/gnupg_test_home/key2.gen
348
359
  - test/gnupg_test_home/pubring.gpg
349
360
  - test/gnupg_test_home/receiver_pubring.gpg
350
361
  - test/gnupg_test_home/receiver_secring.gpg
351
- - test/gnupg_test_home/receiver_trustdb.gpg
362
+ - test/gnupg_test_home/regen_keys.sh
352
363
  - test/gnupg_test_home/secring.gpg
353
364
  - test/gnupg_test_home/sup-test-2@foo.bar.asc
354
- - test/gnupg_test_home/trustdb.gpg
355
365
  - test/integration/test_label_service.rb
366
+ - test/integration/test_maildir.rb
367
+ - test/integration/test_mbox.rb
356
368
  - test/messages/bad-content-transfer-encoding-1.eml
357
369
  - test/messages/binary-content-transfer-encoding-2.eml
358
370
  - test/messages/missing-line.eml
@@ -376,6 +388,11 @@ post_install_message: |
376
388
  SUP: please note that our old mailing lists have been shut down,
377
389
  re-subscribe to supmua@googlegroups.com to discuss and follow
378
390
  updates on sup (send email to: supmua+subscribe@googlegroups.com).
391
+
392
+ OpenBSD users:
393
+ If your operating system is OpenBSD you have some
394
+ additional, manual steps to do before Sup will work, see:
395
+ https://github.com/sup-heliotrope/sup/wiki/Installation%3A-OpenBSD.
379
396
  rdoc_options: []
380
397
  require_paths:
381
398
  - lib
@@ -398,14 +415,17 @@ summary: A console-based email client with the best features of GMail, mutt and
398
415
  test_files:
399
416
  - test/dummy_source.rb
400
417
  - test/gnupg_test_home/gpg.conf
418
+ - test/gnupg_test_home/key1.gen
419
+ - test/gnupg_test_home/key2.gen
401
420
  - test/gnupg_test_home/pubring.gpg
402
421
  - test/gnupg_test_home/receiver_pubring.gpg
403
422
  - test/gnupg_test_home/receiver_secring.gpg
404
- - test/gnupg_test_home/receiver_trustdb.gpg
423
+ - test/gnupg_test_home/regen_keys.sh
405
424
  - test/gnupg_test_home/secring.gpg
406
425
  - test/gnupg_test_home/sup-test-2@foo.bar.asc
407
- - test/gnupg_test_home/trustdb.gpg
408
426
  - test/integration/test_label_service.rb
427
+ - test/integration/test_maildir.rb
428
+ - test/integration/test_mbox.rb
409
429
  - test/messages/bad-content-transfer-encoding-1.eml
410
430
  - test/messages/binary-content-transfer-encoding-2.eml
411
431
  - test/messages/missing-line.eml