rgrove-larch 1.0.0.6 → 1.0.0.7

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.
data/HISTORY CHANGED
@@ -2,8 +2,10 @@ Larch History
2
2
  ================================================================================
3
3
 
4
4
  Version 1.0.1 (?)
5
+ * Ruby 1.9.1 support.
5
6
  * Much more robust handling of unexpected server disconnects and dropped
6
7
  connections.
8
+ * Option to verify server SSL certificates.
7
9
  * Fix excessive post-scan processing times for very large mailboxes.
8
10
  * Fetch message headers in blocks of up to 1024 at a time rather than all at
9
11
  once, to prevent potential problems with certain servers when a mailbox
data/bin/larch CHANGED
@@ -22,18 +22,21 @@ EOS
22
22
  opt :from, "URI of the source IMAP server.", :short => '-f', :type => :string, :required => true
23
23
  opt :to, "URI of the destination IMAP server.", :short => '-t', :type => :string, :required => true
24
24
 
25
- text "\nOptions:"
26
-
27
- # opt :dry_run, "Don't actually do anything.", :short => '-n'
28
- opt :fast_scan, "Use a faster (but less accurate) method to scan mailboxes. This may result in messages being re-copied.", :short => :none
25
+ text "\nCopy Options:"
29
26
  opt :from_folder, "Source folder to copy from", :short => :none, :default => 'INBOX'
30
27
  opt :from_pass, "Source server password (Default: prompt)", :short => :none, :type => :string
31
28
  opt :from_user, "Source server username (Default: prompt)", :short => :none, :type => :string
32
- opt :max_retries, "Maximum number of times to retry after a recoverable error", :short => :none, :default => 3
33
- opt :no_create_folder, "Don't create destination folders that don't already exist", :short => :none
34
29
  opt :to_folder, "Destination folder to copy to", :short => :none, :default => 'INBOX'
35
30
  opt :to_pass, "Destination server password (Default: prompt)", :short => :none, :type => :string
36
31
  opt :to_user, "Destination server username (Default: prompt)", :short => :none, :type => :string
32
+
33
+ text "\nGeneral Options:"
34
+ # opt :dry_run, "Don't actually do anything.", :short => '-n'
35
+ opt :fast_scan, "Use a faster (but less accurate) method to scan mailboxes. This may result in messages being re-copied.", :short => :none
36
+ opt :max_retries, "Maximum number of times to retry after a recoverable error", :short => :none, :default => 3
37
+ opt :no_create_folder, "Don't create destination folders that don't already exist", :short => :none
38
+ opt :ssl_certs, "Path to a trusted certificate bundle to use to verify server SSL certificates", :short => :none
39
+ opt :ssl_verify, "Verify server SSL certificates", :short => :none
37
40
  opt :verbosity, "Output verbosity: debug, info, warn, error, or fatal", :short => '-V', :default => 'info'
38
41
  end
39
42
 
@@ -78,17 +81,21 @@ EOS
78
81
 
79
82
  source = IMAP.new(options[:from], options[:from_user], options[:from_pass],
80
83
  :fast_scan => options[:fast_scan],
81
- :max_retries => options[:max_retries])
84
+ :max_retries => options[:max_retries],
85
+ :ssl_certs => options[:ssl_certs] || nil,
86
+ :ssl_verify => options[:ssl_verify])
82
87
 
83
88
  dest = IMAP.new(options[:to], options[:to_user], options[:to_pass],
84
89
  :create_mailbox => !options[:no_create_folder],
85
90
  :fast_scan => options[:fast_scan],
86
- :max_retries => options[:max_retries])
91
+ :max_retries => options[:max_retries],
92
+ :ssl_certs => options[:ssl_certs] || nil,
93
+ :ssl_verify => options[:ssl_verify])
87
94
 
88
95
  unless RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince|java/
89
96
  begin
90
97
  for sig in [:SIGINT, :SIGQUIT, :SIGTERM]
91
- trap(sig) { @log.fatal "Interrupted (#{sig})"; exit }
98
+ trap(sig) { @log.fatal "Interrupted (#{sig})"; Kernel.exit }
92
99
  end
93
100
  rescue => e
94
101
  end
data/lib/larch/imap.rb CHANGED
@@ -47,6 +47,17 @@ class IMAP
47
47
  # After a recoverable error occurs, retry the operation up to this many
48
48
  # times. Default is 3.
49
49
  #
50
+ # [:ssl_certs]
51
+ # Path to a trusted certificate bundle to use to verify server SSL
52
+ # certificates. You can download a bundle of certificate authority root
53
+ # certs at http://curl.haxx.se/ca/cacert.pem (it's up to you to verify that
54
+ # this bundle hasn't been tampered with, however; don't trust it blindly).
55
+ #
56
+ # [:ssl_verify]
57
+ # If +true+, server SSL certificates will be verified against the trusted
58
+ # certificate bundle specified in +ssl_certs+. By default, server SSL
59
+ # certificates are not verified.
60
+ #
50
61
  def initialize(uri, username, password, options = {})
51
62
  raise ArgumentError, "not an IMAP URI: #{uri}" unless uri.is_a?(URI) || uri =~ REGEX_URI
52
63
  raise ArgumentError, "must provide a username and password" unless username && password
@@ -55,7 +66,7 @@ class IMAP
55
66
  @uri = uri.is_a?(URI) ? uri : URI(uri)
56
67
  @username = username
57
68
  @password = password
58
- @options = {:max_retries => 3}.merge(options)
69
+ @options = {:max_retries => 3, :ssl_verify => false}.merge(options)
59
70
 
60
71
  @ids = {}
61
72
  @imap = nil
@@ -383,6 +394,11 @@ class IMAP
383
394
  OpenSSL::SSL::SSLError => e
384
395
 
385
396
  raise unless (retries += 1) <= @options[:max_retries]
397
+
398
+ # Special check to ensure that we don't retry on OpenSSL certificate
399
+ # verification errors.
400
+ raise if e.is_a?(OpenSSL::SSL::SSLError) && e.message =~ /certificate verify failed/
401
+
386
402
  info "#{e.class.name}: #{e.message} (will retry)"
387
403
 
388
404
  reset
@@ -449,7 +465,9 @@ class IMAP
449
465
 
450
466
  Thread.new do
451
467
  begin
452
- @imap = Net::IMAP.new(host, port, ssl?)
468
+ @imap = Net::IMAP.new(host, port, ssl?,
469
+ ssl? && @options[:ssl_verify] ? @options[:ssl_certs] : nil,
470
+ @options[:ssl_verify])
453
471
 
454
472
  info "connected on port #{port}" << (ssl? ? ' using SSL' : '')
455
473
 
@@ -483,7 +501,6 @@ class IMAP
483
501
 
484
502
  rescue => e
485
503
  exception = e
486
- error e.message
487
504
  end
488
505
  end.join
489
506
 
data/lib/larch/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Larch
2
2
  APP_NAME = 'Larch'
3
- APP_VERSION = '1.0.0.6'
3
+ APP_VERSION = '1.0.0.7'
4
4
  APP_AUTHOR = 'Ryan Grove'
5
5
  APP_EMAIL = 'ryan@wonko.com'
6
6
  APP_URL = 'http://github.com/rgrove/larch/'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgrove-larch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.6
4
+ version: 1.0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Grove