imap-backup 1.2.2 → 1.2.3

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -0
  3. data/Gemfile +1 -1
  4. data/Rakefile +4 -4
  5. data/bin/imap-backup +23 -25
  6. data/imap-backup.gemspec +14 -14
  7. data/lib/email/mboxrd/message.rb +23 -5
  8. data/lib/email/provider.rb +4 -4
  9. data/lib/imap/backup.rb +18 -18
  10. data/lib/imap/backup/account/connection.rb +6 -6
  11. data/lib/imap/backup/account/folder.rb +4 -5
  12. data/lib/imap/backup/configuration/account.rb +20 -22
  13. data/lib/imap/backup/configuration/asker.rb +8 -10
  14. data/lib/imap/backup/configuration/connection_tester.rb +3 -5
  15. data/lib/imap/backup/configuration/folder_chooser.rb +10 -12
  16. data/lib/imap/backup/configuration/list.rb +1 -3
  17. data/lib/imap/backup/configuration/setup.rb +13 -14
  18. data/lib/imap/backup/configuration/store.rb +7 -8
  19. data/lib/imap/backup/downloader.rb +0 -2
  20. data/lib/imap/backup/serializer/base.rb +0 -2
  21. data/lib/imap/backup/serializer/directory.rb +3 -4
  22. data/lib/imap/backup/serializer/mbox.rb +11 -12
  23. data/lib/imap/backup/utils.rb +2 -3
  24. data/lib/imap/backup/version.rb +2 -2
  25. data/spec/spec_helper.rb +6 -6
  26. data/spec/support/higline_test_helpers.rb +1 -1
  27. data/spec/support/shared_examples/account_flagging.rb +6 -6
  28. data/spec/unit/account/connection_spec.rb +50 -51
  29. data/spec/unit/account/folder_spec.rb +18 -19
  30. data/spec/unit/configuration/account_spec.rb +96 -97
  31. data/spec/unit/configuration/asker_spec.rb +33 -34
  32. data/spec/unit/configuration/connection_tester_spec.rb +18 -19
  33. data/spec/unit/configuration/folder_chooser_spec.rb +34 -35
  34. data/spec/unit/configuration/list_spec.rb +13 -14
  35. data/spec/unit/configuration/setup_spec.rb +46 -47
  36. data/spec/unit/configuration/store_spec.rb +56 -57
  37. data/spec/unit/downloader_spec.rb +18 -19
  38. data/spec/unit/email/mboxrd/message_spec.rb +55 -11
  39. data/spec/unit/email/provider_spec.rb +12 -12
  40. data/spec/unit/serializer/base_spec.rb +7 -9
  41. data/spec/unit/serializer/directory_spec.rb +18 -19
  42. data/spec/unit/serializer/mbox_spec.rb +35 -37
  43. data/spec/unit/utils_spec.rb +26 -27
  44. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85975662cee269fb87e3de1150cd3a02c123e729e2d2f4e1a2e4905de477a897
4
- data.tar.gz: 06aa1c25d470bc8f38cf78e124d00f90f498e9ba2e803804ebf7a58ce9f81579
3
+ metadata.gz: 55d07b2ed9eae209a118323f3e8c494b831183468ef92e05cfe2ae139177f82b
4
+ data.tar.gz: c76ad04b8363dd146fc2abdc5ba6243fe3cd446a107f946187bf45bf16689906
5
5
  SHA512:
6
- metadata.gz: c75aff4a749a5630fe86bca252f676be0338c30c492ce3fdbe654c895143dcd7846ab654733f2aeb3a4316fe4b8f630d3ca0a1db0227c7d06918e7362d17970b
7
- data.tar.gz: b3b267870e606d407931ac337c36865aaccf430b1b91ab0a9a3dfe49e1db65ae159ddaeaf2f22041715e6998a8d00db8d76b02dafc6ac0a11dcd91218129a62e
6
+ metadata.gz: cd396bf6b70d293ef00ac83bc4e3f3ac0efdfdbf56c835484abf5c503ec84d5690537c0f36c5d23cf9e18f27f64372b66157b45491954fa6dfd0c2779b8b7aac
7
+ data.tar.gz: 1af9c675e2641debc9e897b4a4ae1a13834550e234887bcdd8ef75cafd3aadde58b296fdd903c377bddf142b340f9ed32fd8e8d6305d673e7fde5a7acb4437a5
@@ -0,0 +1,7 @@
1
+ inherit_from: https://gist.githubusercontent.com/joeyates/4763b79425cf903fc70df3bc8fccda36/raw/356fa04037feedb212735d4e7002cbd8778a33e8/.rubocop.yaml
2
+
3
+ AllCops:
4
+ Exclude:
5
+ - "bin/stubs/*"
6
+ DisplayCopNames:
7
+ Enabled: true
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env rake
2
- require 'bundler/gem_tasks'
3
- require 'rspec/core/rake_task'
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
4
 
5
- task :default => :spec
5
+ task default: :spec
6
6
 
7
7
  RSpec::Core::RakeTask.new do |t|
8
- t.pattern = 'spec/**/*_spec.rb'
8
+ t.pattern = "spec/**/*_spec.rb"
9
9
  end
@@ -1,32 +1,30 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- encoding: utf-8 -*-
2
+ require "optparse"
3
3
 
4
- require 'optparse'
5
-
6
- $:.unshift(File.expand_path('../../lib/', __FILE__))
7
- require 'imap/backup'
4
+ $LOAD_PATH.unshift(File.expand_path("../../lib/", __FILE__))
5
+ require "imap/backup"
8
6
 
9
7
  KNOWN_COMMANDS = [
10
- {:name => 'setup', :help => 'Create/edit the configuration file'},
11
- {:name => 'backup', :help => 'Do the backup (default)'},
12
- {:name => 'folders', :help => 'List folders for all (or selected) accounts'},
13
- {:name => 'status', :help => 'List count of non backed-up emails per folder'},
14
- {:name => 'help', :help => 'Show usage'},
8
+ {name: "setup", help: "Create/edit the configuration file"},
9
+ {name: "backup", help: "Do the backup (default)"},
10
+ {name: "folders", help: "List folders for all (or selected) accounts"},
11
+ {name: "status", help: "List count of non backed-up emails per folder"},
12
+ {name: "help", help: "Show usage"}
15
13
  ]
16
14
 
17
- options = {:command => 'backup'}
15
+ options = {command: "backup"}
18
16
  opts = OptionParser.new do |opts|
19
- opts.banner = "Usage: #{$0} [options] COMMAND"
17
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options] COMMAND"
20
18
 
21
- opts.separator ''
22
- opts.separator 'Commands:'
19
+ opts.separator ""
20
+ opts.separator "Commands:"
23
21
  KNOWN_COMMANDS.each do |command|
24
22
  opts.separator "\t%- 20s %s" % [command[:name], command[:help]]
25
23
  end
26
- opts.separator ''
27
- opts.separator 'Common options:'
24
+ opts.separator ""
25
+ opts.separator "Common options:"
28
26
 
29
- opts.on('-a', '--accounts ACCOUNT1[,ACCOUNT2,...]', Array, 'only these accounts') do |account|
27
+ opts.on("-a", "--accounts ACCOUNT1[,ACCOUNT2,...]", Array, "only these accounts") do |account|
30
28
  options[:accounts] = account
31
29
  end
32
30
 
@@ -35,7 +33,7 @@ opts = OptionParser.new do |opts|
35
33
  exit
36
34
  end
37
35
 
38
- opts.on_tail("--version", "Show version" ) do
36
+ opts.on_tail("--version", "Show version") do
39
37
  puts Imap::Backup::VERSION
40
38
  exit
41
39
  end
@@ -46,11 +44,11 @@ if ARGV.size > 0
46
44
  options[:command] = ARGV.shift
47
45
  end
48
46
 
49
- if KNOWN_COMMANDS.find{ |c| c[:name] == options[:command] }.nil?
47
+ if KNOWN_COMMANDS.find { |c| c[:name] == options[:command] }.nil?
50
48
  raise "Unknown command '#{options[:command]}'"
51
49
  end
52
50
 
53
- if options[:command] == 'help'
51
+ if options[:command] == "help"
54
52
  puts opts
55
53
  exit
56
54
  end
@@ -65,23 +63,23 @@ end
65
63
  configuration.setup_logging
66
64
 
67
65
  case options[:command]
68
- when 'setup'
66
+ when "setup"
69
67
  Imap::Backup::Configuration::Setup.new.run
70
- when 'backup'
68
+ when "backup"
71
69
  configuration.each_connection do |connection|
72
70
  connection.run_backup
73
71
  end
74
- when 'folders'
72
+ when "folders"
75
73
  configuration.each_connection do |connection|
76
74
  puts connection.username
77
75
  folders = connection.folders
78
76
  if folders.nil?
79
- warn 'Unable to list account folders'
77
+ warn "Unable to list account folders"
80
78
  exit 1
81
79
  end
82
80
  folders.each { |f| puts "\t" + f.name }
83
81
  end
84
- when 'status'
82
+ when "status"
85
83
  configuration.each_connection do |connection|
86
84
  puts connection.username
87
85
  folders = connection.status
@@ -1,26 +1,26 @@
1
- # -*- encoding: utf-8 -*-
2
- $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
3
- require 'imap/backup/version'
1
+ $LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
2
+ require "imap/backup/version"
4
3
 
5
4
  Gem::Specification.new do |gem|
6
- gem.name = 'imap-backup'
5
+ gem.name = "imap-backup"
7
6
  gem.description = %q{Backup GMail, or any other IMAP email service, to disk.}
8
7
  gem.summary = %q{Backup GMail (or other IMAP) accounts to disk}
9
- gem.authors = ['Joe Yates']
10
- gem.email = ['joe.g.yates@gmail.com']
11
- gem.homepage = 'https://github.com/joeyates/imap-backup'
8
+ gem.authors = ["Joe Yates"]
9
+ gem.email = ["joe.g.yates@gmail.com"]
10
+ gem.homepage = "https://github.com/joeyates/imap-backup"
12
11
 
13
12
  gem.files = `git ls-files`.split($\)
14
13
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
14
  gem.test_files = gem.files.grep(%r{^spec/})
16
- gem.require_paths = ['lib']
15
+ gem.require_paths = ["lib"]
17
16
  gem.version = Imap::Backup::VERSION
18
17
 
19
- gem.add_runtime_dependency 'rake'
20
- gem.add_runtime_dependency 'highline'
21
- gem.add_runtime_dependency 'mail'
18
+ gem.add_runtime_dependency "rake"
19
+ gem.add_runtime_dependency "highline"
20
+ gem.add_runtime_dependency "mail"
22
21
 
23
- gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.8'
24
- gem.add_development_dependency 'rspec', '>= 3.0.0'
25
- gem.add_development_dependency 'simplecov'
22
+ gem.add_development_dependency "codeclimate-test-reporter", "~> 0.4.8"
23
+ gem.add_development_dependency "rspec", ">= 3.0.0"
24
+ gem.add_development_dependency "rubocop-rspec"
25
+ gem.add_development_dependency "simplecov"
26
26
  end
@@ -1,4 +1,4 @@
1
- require 'mail'
1
+ require "mail"
2
2
 
3
3
  module Email; end
4
4
 
@@ -8,11 +8,11 @@ module Email::Mboxrd
8
8
 
9
9
  def initialize(supplied_body)
10
10
  @supplied_body = supplied_body.clone
11
- @supplied_body.force_encoding('binary')
11
+ @supplied_body.force_encoding("binary")
12
12
  end
13
13
 
14
14
  def to_s
15
- 'From ' + from + "\n" + mboxrd_body + "\n"
15
+ "From " + from + "\n" + mboxrd_body + "\n"
16
16
  end
17
17
 
18
18
  private
@@ -21,8 +21,26 @@ module Email::Mboxrd
21
21
  @parsed ||= Mail.new(supplied_body)
22
22
  end
23
23
 
24
+ def best_from
25
+ if parsed.from.is_a? Enumerable
26
+ parsed.from.each do |addr|
27
+ if addr
28
+ return addr
29
+ end
30
+ end
31
+ end
32
+ if parsed.envelope_from
33
+ return parsed.envelope_from
34
+ end
35
+ if parsed.return_path
36
+ return parsed.return_path
37
+ end
38
+
39
+ return ''
40
+ end
41
+
24
42
  def from
25
- parsed.from[0] + ' ' + asctime
43
+ best_from + " " + asctime
26
44
  end
27
45
 
28
46
  def mboxrd_body
@@ -33,7 +51,7 @@ module Email::Mboxrd
33
51
  end
34
52
 
35
53
  def asctime
36
- date ? date.asctime : ''
54
+ date ? date.asctime : ""
37
55
  end
38
56
 
39
57
  def date
@@ -3,9 +3,9 @@ module Email; end
3
3
  class Email::Provider
4
4
  def self.for_address(address)
5
5
  case
6
- when address.end_with?('@gmail.com')
6
+ when address.end_with?("@gmail.com")
7
7
  new(:gmail)
8
- when address.end_with?('@fastmail.fm')
8
+ when address.end_with?("@fastmail.fm")
9
9
  new(:fastmail)
10
10
  else
11
11
  new(:default)
@@ -32,9 +32,9 @@ class Email::Provider
32
32
  def host
33
33
  case provider
34
34
  when :gmail
35
- 'imap.gmail.com'
35
+ "imap.gmail.com"
36
36
  when :fastmail
37
- 'mail.messagingengine.com'
37
+ "mail.messagingengine.com"
38
38
  end
39
39
  end
40
40
  end
@@ -1,23 +1,23 @@
1
1
  module Imap; end
2
2
 
3
- require 'imap/backup/utils'
4
- require 'imap/backup/account/connection'
5
- require 'imap/backup/account/folder'
6
- require 'imap/backup/configuration/account'
7
- require 'imap/backup/configuration/asker'
8
- require 'imap/backup/configuration/connection_tester'
9
- require 'imap/backup/configuration/folder_chooser'
10
- require 'imap/backup/configuration/list'
11
- require 'imap/backup/configuration/setup'
12
- require 'imap/backup/configuration/store'
13
- require 'imap/backup/downloader'
14
- require 'imap/backup/serializer/base'
15
- require 'imap/backup/serializer/directory'
16
- require 'imap/backup/serializer/mbox'
17
- require 'imap/backup/version'
18
- require 'email/provider'
19
-
20
- require 'logger'
3
+ require "imap/backup/utils"
4
+ require "imap/backup/account/connection"
5
+ require "imap/backup/account/folder"
6
+ require "imap/backup/configuration/account"
7
+ require "imap/backup/configuration/asker"
8
+ require "imap/backup/configuration/connection_tester"
9
+ require "imap/backup/configuration/folder_chooser"
10
+ require "imap/backup/configuration/list"
11
+ require "imap/backup/configuration/setup"
12
+ require "imap/backup/configuration/store"
13
+ require "imap/backup/downloader"
14
+ require "imap/backup/serializer/base"
15
+ require "imap/backup/serializer/directory"
16
+ require "imap/backup/serializer/mbox"
17
+ require "imap/backup/version"
18
+ require "email/provider"
19
+
20
+ require "logger"
21
21
 
22
22
  module Imap::Backup
23
23
  class ConfigurationNotFound < StandardError; end
@@ -1,4 +1,4 @@
1
- require 'net/imap'
1
+ require "net/imap"
2
2
 
3
3
  module Imap::Backup
4
4
  module Account; end
@@ -20,7 +20,7 @@ module Imap::Backup
20
20
 
21
21
  def folders
22
22
  return @folders if @folders
23
- @folders = imap.list('', '*')
23
+ @folders = imap.list("", "*")
24
24
  if @folders.nil?
25
25
  Imap::Backup.logger.warn "Unable to get folder list for account #{username}"
26
26
  end
@@ -31,7 +31,7 @@ module Imap::Backup
31
31
  backup_folders.map do |folder|
32
32
  f = Account::Folder.new(self, folder[:name])
33
33
  s = Serializer::Directory.new(local_path, folder[:name])
34
- {:name => folder[:name], :local => s.uids, :remote => f.uids}
34
+ {name: folder[:name], local: s.uids, remote: f.uids}
35
35
  end
36
36
  end
37
37
 
@@ -83,12 +83,12 @@ module Imap::Backup
83
83
  end
84
84
 
85
85
  def masked_password
86
- password.gsub(/./, 'x')
86
+ password.gsub(/./, "x")
87
87
  end
88
88
 
89
89
  def backup_folders
90
- return @backup_folders if @backup_folders and @backup_folders.size > 0
91
- (folders || []).map { |f| {:name => f.name} }
90
+ return @backup_folders if @backup_folders && (@backup_folders.size > 0)
91
+ (folders || []).map { |f| {name: f.name} }
92
92
  end
93
93
 
94
94
  def provider
@@ -1,5 +1,4 @@
1
- # encoding: utf-8
2
- require 'forwardable'
1
+ require "forwardable"
3
2
 
4
3
  module Imap::Backup
5
4
  module Account; end
@@ -7,7 +6,7 @@ module Imap::Backup
7
6
  class Account::Folder
8
7
  extend Forwardable
9
8
 
10
- REQUESTED_ATTRIBUTES = ['RFC822', 'FLAGS', 'INTERNALDATE']
9
+ REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"]
11
10
 
12
11
  attr_reader :connection
13
12
  attr_reader :name
@@ -25,7 +24,7 @@ module Imap::Backup
25
24
 
26
25
  def uids
27
26
  imap.examine(name)
28
- imap.uid_search(['ALL']).sort
27
+ imap.uid_search(["ALL"]).sort
29
28
  rescue Net::IMAP::NoResponseError => e
30
29
  Imap::Backup.logger.warn "Folder '#{name}' does not exist"
31
30
  []
@@ -37,7 +36,7 @@ module Imap::Backup
37
36
  return nil if fetch_data_items.nil?
38
37
  fetch_data_item = fetch_data_items[0]
39
38
  attributes = fetch_data_item.attr
40
- attributes['RFC822'].force_encoding('utf-8')
39
+ attributes["RFC822"].force_encoding("utf-8")
41
40
  attributes
42
41
  rescue Net::IMAP::NoResponseError => e
43
42
  Imap::Backup.logger.warn "Folder '#{name}' does not exist"
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Imap::Backup
4
2
  module Configuration; end
5
3
 
@@ -11,7 +9,7 @@ module Imap::Backup
11
9
  def run
12
10
  catch :done do
13
11
  loop do
14
- system('clear')
12
+ system("clear")
15
13
  create_menu
16
14
  end
17
15
  end
@@ -29,8 +27,8 @@ module Imap::Backup
29
27
  choose_folders menu
30
28
  test_connection menu
31
29
  delete_account menu
32
- menu.choice('return to main menu') { throw :done }
33
- menu.hidden('quit') { throw :done }
30
+ menu.choice("return to main menu") { throw :done }
31
+ menu.hidden("quit") { throw :done }
34
32
  end
35
33
  end
36
34
 
@@ -46,16 +44,16 @@ Account:
46
44
  end
47
45
 
48
46
  def modify_email(menu)
49
- menu.choice('modify email') do
47
+ menu.choice("modify email") do
50
48
  username = Configuration::Asker.email(username)
51
49
  puts "username: #{username}"
52
- others = store.accounts.select { |a| a != account}.map { |a| a[:username] }
50
+ others = store.accounts.select { |a| a != account }.map { |a| a[:username] }
53
51
  puts "others: #{others.inspect}"
54
52
  if others.include?(username)
55
- puts 'There is already an account set up with that email address'
53
+ puts "There is already an account set up with that email address"
56
54
  else
57
55
  account[:username] = username
58
- if account[:server].nil? or account[:server] == ''
56
+ if account[:server].nil? || (account[:server] == "")
59
57
  account[:server] = default_server(username)
60
58
  end
61
59
  account[:modified] = true
@@ -64,9 +62,9 @@ Account:
64
62
  end
65
63
 
66
64
  def modify_password(menu)
67
- menu.choice('modify password') do
65
+ menu.choice("modify password") do
68
66
  password = Configuration::Asker.password
69
- if ! password.nil?
67
+ if !password.nil?
70
68
  account[:password] = password
71
69
  account[:modified] = true
72
70
  end
@@ -74,9 +72,9 @@ Account:
74
72
  end
75
73
 
76
74
  def modify_server(menu)
77
- menu.choice('modify server') do
78
- server = highline.ask('server: ')
79
- if ! server.nil?
75
+ menu.choice("modify server") do
76
+ server = highline.ask("server: ")
77
+ if !server.nil?
80
78
  account[:server] = server
81
79
  account[:modified] = true
82
80
  end
@@ -84,7 +82,7 @@ Account:
84
82
  end
85
83
 
86
84
  def modify_backup_path(menu)
87
- menu.choice('modify backup path') do
85
+ menu.choice("modify backup path") do
88
86
  validator = lambda do |p|
89
87
  same = store.accounts.find do |a|
90
88
  a[:username] != account[:username] && a[:local_path] == p
@@ -103,21 +101,21 @@ Account:
103
101
  end
104
102
 
105
103
  def choose_folders(menu)
106
- menu.choice('choose backup folders') do
104
+ menu.choice("choose backup folders") do
107
105
  Configuration::FolderChooser.new(account).run
108
106
  end
109
107
  end
110
108
 
111
109
  def test_connection(menu)
112
- menu.choice('test connection') do
110
+ menu.choice("test connection") do
113
111
  result = Configuration::ConnectionTester.test(account)
114
112
  puts result
115
- highline.ask 'Press a key '
113
+ highline.ask "Press a key "
116
114
  end
117
115
  end
118
116
 
119
117
  def delete_account(menu)
120
- menu.choice('delete') do
118
+ menu.choice("delete") do
121
119
  if highline.agree("Are you sure? (y/n) ")
122
120
  account[:delete] = true
123
121
  throw :done
@@ -130,10 +128,10 @@ Account:
130
128
  end
131
129
 
132
130
  def masked_password
133
- if account[:password] == '' or account[:password].nil?
134
- '(unset)'
131
+ if (account[:password] == "") || account[:password].nil?
132
+ "(unset)"
135
133
  else
136
- account[:password].gsub(/./, 'x')
134
+ account[:password].gsub(/./, "x")
137
135
  end
138
136
  end
139
137