imap-backup 4.0.1 → 4.0.5
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 +4 -4
- data/README.md +9 -1
- data/docs/development.md +5 -12
- data/imap-backup.gemspec +1 -4
- data/lib/email/mboxrd/message.rb +6 -2
- data/lib/email/provider/apple_mail.rb +7 -0
- data/lib/email/provider/base.rb +8 -0
- data/lib/email/provider/fastmail.rb +7 -0
- data/lib/email/provider/gmail.rb +7 -0
- data/lib/email/provider/unknown.rb +11 -0
- data/lib/email/provider.rb +16 -26
- data/lib/imap/backup/account/connection.rb +19 -29
- data/lib/imap/backup/account/folder.rb +9 -10
- data/lib/imap/backup/account.rb +103 -0
- data/lib/imap/backup/cli/helpers.rb +14 -0
- data/lib/imap/backup/cli/local.rb +19 -25
- data/lib/imap/backup/cli/utils.rb +67 -10
- data/lib/imap/backup/client/apple_mail.rb +11 -0
- data/lib/imap/backup/client/default.rb +51 -0
- data/lib/imap/backup/configuration/account.rb +3 -1
- data/lib/imap/backup/configuration/connection_tester.rb +1 -1
- data/lib/imap/backup/configuration/store.rb +10 -5
- data/lib/imap/backup/downloader.rb +3 -4
- data/lib/imap/backup/serializer/mbox.rb +5 -0
- data/lib/imap/backup/serializer/mbox_store.rb +8 -8
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +58 -0
- data/lib/imap/backup/version.rb +1 -1
- data/lib/imap/backup.rb +1 -0
- data/lib/thunderbird/install.rb +16 -0
- data/lib/thunderbird/local_folder.rb +65 -0
- data/lib/thunderbird/profile.rb +30 -0
- data/lib/thunderbird/profiles.rb +71 -0
- data/lib/thunderbird/subdirectory.rb +96 -0
- data/lib/thunderbird/subdirectory_placeholder.rb +21 -0
- data/lib/thunderbird.rb +14 -0
- data/spec/features/restore_spec.rb +1 -1
- data/spec/features/support/email_server.rb +2 -2
- data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
- data/spec/unit/email/provider/base_spec.rb +11 -0
- data/spec/unit/email/provider/fastmail_spec.rb +7 -0
- data/spec/unit/email/provider/gmail_spec.rb +7 -0
- data/spec/unit/email/provider_spec.rb +12 -25
- data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
- data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
- data/spec/unit/imap/backup/cli/local_spec.rb +70 -0
- data/spec/unit/imap/backup/cli/utils_spec.rb +50 -0
- data/spec/unit/imap/backup/client/default_spec.rb +22 -0
- data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
- data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
- data/spec/unit/imap/backup/downloader_spec.rb +1 -2
- metadata +68 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6eebcf60acbb2e97a007e5da03c63fb7c32e24413397f28d3ec9f94154b8def5
|
4
|
+
data.tar.gz: 5f81961b55811c8c9fadabf2def11e1e00ab8572fd844f44b8fda371aa190bbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ebb0d93413c0911487235584837f76f6409d66cc06a64ad9e7db7ec0a4ccca2694b9be363e02922bbf1c981d944a9772e6705190ad92b461252d7b57bf1e4b0
|
7
|
+
data.tar.gz: 6f29640122bf11c098050476e60caa073ebb868a0859624d6e7b74df435e85a1d6ebbcf964840058c6978a42d16034d86341741caead66d99722554ffc2ca4a3
|
data/README.md
CHANGED
@@ -134,7 +134,15 @@ in the configuration file.
|
|
134
134
|
|
135
135
|
The directory ~/.imap-backup, the configuration file and all backup
|
136
136
|
directories have their access permissions set to only allow access
|
137
|
-
by your user.
|
137
|
+
by your user. This is not done on Windows - see below.
|
138
|
+
|
139
|
+
## Windows
|
140
|
+
|
141
|
+
Due to the complexity of managing permissions on Windows,
|
142
|
+
directory and file access permissions are not set explicity.
|
143
|
+
|
144
|
+
A pull request that implements permissions management on Windows
|
145
|
+
would be welcome!
|
138
146
|
|
139
147
|
# Run Backup
|
140
148
|
|
data/docs/development.md
CHANGED
@@ -2,18 +2,12 @@
|
|
2
2
|
|
3
3
|
## Integration Tests
|
4
4
|
|
5
|
-
Integration tests (feature specs) are run against a
|
6
|
-
|
7
|
-
|
8
|
-
In one shell, run the Docker image:
|
5
|
+
Integration tests (feature specs) are run against a local IMAP server
|
6
|
+
controlled by Docker Compose, which needs to be started
|
7
|
+
before running the test suite.
|
9
8
|
|
10
9
|
```sh
|
11
|
-
$ docker
|
12
|
-
--env MAIL_ADDRESS=address@example.org \
|
13
|
-
--env MAIL_PASS=pass \
|
14
|
-
--env MAILNAME=example.org \
|
15
|
-
--publish 8993:993 \
|
16
|
-
antespi/docker-imap-devel:latest
|
10
|
+
$ docker-compose up -d
|
17
11
|
```
|
18
12
|
|
19
13
|
```sh
|
@@ -47,8 +41,7 @@ response = imap.append("INBOX", message, nil, nil)
|
|
47
41
|
imap.examine("INBOX")
|
48
42
|
uids = imap.uid_search(["ALL"]).sort
|
49
43
|
|
50
|
-
|
51
|
-
fetch_data_items = imap.uid_fetch(uids, REQUESTED_ATTRIBUTES)
|
44
|
+
fetch_data_items = imap.uid_fetch(uids, ["BODY[]"])
|
52
45
|
```
|
53
46
|
|
54
47
|
# Contributing
|
data/imap-backup.gemspec
CHANGED
@@ -17,10 +17,6 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.files += %w[imap-backup.gemspec]
|
18
18
|
gem.files += %w[LICENSE README.md]
|
19
19
|
|
20
|
-
gem.extra_rdoc_files += Dir.glob("README.md")
|
21
|
-
gem.extra_rdoc_files += Dir.glob("docs/*.md")
|
22
|
-
gem.rdoc_options = ["--main", "README.md"]
|
23
|
-
|
24
20
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
25
21
|
gem.test_files = Dir.glob("spec/**/*{.rb,.yml}")
|
26
22
|
gem.require_paths = ["lib"]
|
@@ -28,6 +24,7 @@ Gem::Specification.new do |gem|
|
|
28
24
|
|
29
25
|
gem.add_runtime_dependency "highline"
|
30
26
|
gem.add_runtime_dependency "mail"
|
27
|
+
gem.add_runtime_dependency "os"
|
31
28
|
gem.add_runtime_dependency "rake"
|
32
29
|
gem.add_runtime_dependency "thor", "~> 1.1"
|
33
30
|
|
data/lib/email/mboxrd/message.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require "forwardable"
|
1
2
|
require "mail"
|
2
3
|
|
3
4
|
module Email; end
|
4
5
|
|
5
6
|
module Email::Mboxrd
|
6
7
|
class Message
|
8
|
+
extend Forwardable
|
9
|
+
def_delegators :@parsed, :subject
|
10
|
+
|
7
11
|
attr_reader :supplied_body
|
8
12
|
|
9
13
|
def self.from_serialized(serialized)
|
@@ -36,12 +40,12 @@ module Email::Mboxrd
|
|
36
40
|
supplied_body.gsub(/(?<!\r)\n/, "\r\n")
|
37
41
|
end
|
38
42
|
|
43
|
+
private
|
44
|
+
|
39
45
|
def parsed
|
40
46
|
@parsed ||= Mail.new(supplied_body)
|
41
47
|
end
|
42
48
|
|
43
|
-
private
|
44
|
-
|
45
49
|
def from
|
46
50
|
@from ||=
|
47
51
|
begin
|
data/lib/email/provider.rb
CHANGED
@@ -1,37 +1,27 @@
|
|
1
|
+
require "email/provider/apple_mail"
|
2
|
+
require "email/provider/fastmail"
|
3
|
+
require "email/provider/gmail"
|
4
|
+
require "email/provider/unknown"
|
5
|
+
|
1
6
|
module Email; end
|
2
7
|
|
3
8
|
class Email::Provider
|
4
|
-
GMAIL_IMAP_SERVER = "imap.gmail.com".freeze
|
5
|
-
|
6
9
|
def self.for_address(address)
|
7
10
|
case
|
8
11
|
when address.end_with?("@fastmail.com")
|
9
|
-
new
|
10
|
-
when address.end_with?("@gmail.com")
|
11
|
-
new(:gmail)
|
12
|
+
Email::Provider::Fastmail.new
|
12
13
|
when address.end_with?("@fastmail.fm")
|
13
|
-
new
|
14
|
+
Email::Provider::Fastmail.new
|
15
|
+
when address.end_with?("@gmail.com")
|
16
|
+
Email::Provider::GMail.new
|
17
|
+
when address.end_with?("@icloud.com")
|
18
|
+
Email::Provider::AppleMail.new
|
19
|
+
when address.end_with?("@mac.com")
|
20
|
+
Email::Provider::AppleMail.new
|
21
|
+
when address.end_with?("@me.com")
|
22
|
+
Email::Provider::AppleMail.new
|
14
23
|
else
|
15
|
-
new
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
attr_reader :provider
|
20
|
-
|
21
|
-
def initialize(provider)
|
22
|
-
@provider = provider
|
23
|
-
end
|
24
|
-
|
25
|
-
def options
|
26
|
-
{port: 993, ssl: {ssl_version: :TLSv1_2}}
|
27
|
-
end
|
28
|
-
|
29
|
-
def host
|
30
|
-
case provider
|
31
|
-
when :gmail
|
32
|
-
GMAIL_IMAP_SERVER
|
33
|
-
when :fastmail
|
34
|
-
"imap.fastmail.com"
|
24
|
+
Email::Provider::Unknown.new
|
35
25
|
end
|
36
26
|
end
|
37
27
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require "
|
1
|
+
require "imap/backup/client/apple_mail"
|
2
|
+
require "imap/backup/client/default"
|
2
3
|
|
3
4
|
require "retry_on_error"
|
4
5
|
|
@@ -29,17 +30,15 @@ module Imap::Backup
|
|
29
30
|
def folders
|
30
31
|
@folders ||=
|
31
32
|
begin
|
32
|
-
|
33
|
-
mailbox_lists = imap.list(root, "*")
|
33
|
+
folders = client.list
|
34
34
|
|
35
|
-
if
|
35
|
+
if folders.empty?
|
36
36
|
message = "Unable to get folder list for account #{username}"
|
37
37
|
Imap::Backup.logger.info message
|
38
38
|
raise message
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
utf7_encoded.map { |n| Net::IMAP.decode_utf7(n) }
|
41
|
+
folders
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
@@ -54,7 +53,7 @@ module Imap::Backup
|
|
54
53
|
def run_backup
|
55
54
|
Imap::Backup.logger.debug "Running backup of account: #{username}"
|
56
55
|
# start the connection so we get logging messages in the right order
|
57
|
-
|
56
|
+
client
|
58
57
|
each_folder do |folder, serializer|
|
59
58
|
next if !folder.exist?
|
60
59
|
|
@@ -89,34 +88,36 @@ module Imap::Backup
|
|
89
88
|
end
|
90
89
|
|
91
90
|
def disconnect
|
92
|
-
|
91
|
+
client.disconnect if @client
|
93
92
|
end
|
94
93
|
|
95
94
|
def reconnect
|
96
95
|
disconnect
|
97
|
-
@
|
96
|
+
@client = nil
|
98
97
|
end
|
99
98
|
|
100
|
-
def
|
101
|
-
@
|
99
|
+
def client
|
100
|
+
@client ||=
|
102
101
|
retry_on_error(errors: LOGIN_RETRY_CLASSES) do
|
103
102
|
options = provider_options
|
104
103
|
Imap::Backup.logger.debug(
|
105
104
|
"Creating IMAP instance: #{server}, options: #{options.inspect}"
|
106
105
|
)
|
107
|
-
|
106
|
+
client =
|
107
|
+
if provider.is_a?(Email::Provider::AppleMail)
|
108
|
+
Client::AppleMail.new(server, options)
|
109
|
+
else
|
110
|
+
Client::Default.new(server, options)
|
111
|
+
end
|
108
112
|
Imap::Backup.logger.debug "Logging in: #{username}/#{masked_password}"
|
109
|
-
|
113
|
+
client.login(username, password)
|
110
114
|
Imap::Backup.logger.debug "Login complete"
|
111
|
-
|
115
|
+
client
|
112
116
|
end
|
113
117
|
end
|
114
118
|
|
115
119
|
def server
|
116
|
-
|
117
|
-
return nil if provider.nil?
|
118
|
-
|
119
|
-
@server = provider.host
|
120
|
+
@server ||= provider.host
|
120
121
|
end
|
121
122
|
|
122
123
|
private
|
@@ -186,16 +187,5 @@ module Imap::Backup
|
|
186
187
|
def provider_options
|
187
188
|
provider.options.merge(connection_options)
|
188
189
|
end
|
189
|
-
|
190
|
-
# 6.3.8. LIST Command
|
191
|
-
# An empty ("" string) mailbox name argument is a special request to
|
192
|
-
# return the hierarchy delimiter and the root name of the name given
|
193
|
-
# in the reference.
|
194
|
-
def provider_root
|
195
|
-
return @provider_root if @provider_root
|
196
|
-
|
197
|
-
root_info = imap.list("", "")[0]
|
198
|
-
@provider_root = root_info.name
|
199
|
-
end
|
200
190
|
end
|
201
191
|
end
|
@@ -11,13 +11,13 @@ module Imap::Backup
|
|
11
11
|
extend Forwardable
|
12
12
|
include RetryOnError
|
13
13
|
|
14
|
-
|
14
|
+
BODY_ATTRIBUTE = "BODY[]".freeze
|
15
15
|
UID_FETCH_RETRY_CLASSES = [EOFError].freeze
|
16
16
|
|
17
17
|
attr_reader :connection
|
18
18
|
attr_reader :name
|
19
19
|
|
20
|
-
delegate
|
20
|
+
delegate client: :connection
|
21
21
|
|
22
22
|
def initialize(connection, name)
|
23
23
|
@connection = connection
|
@@ -40,20 +40,20 @@ module Imap::Backup
|
|
40
40
|
def create
|
41
41
|
return if exist?
|
42
42
|
|
43
|
-
|
43
|
+
client.create(utf7_encoded_name)
|
44
44
|
end
|
45
45
|
|
46
46
|
def uid_validity
|
47
47
|
@uid_validity ||=
|
48
48
|
begin
|
49
49
|
examine
|
50
|
-
|
50
|
+
client.responses["UIDVALIDITY"][-1]
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
def uids
|
55
55
|
examine
|
56
|
-
|
56
|
+
client.uid_search(["ALL"]).sort
|
57
57
|
rescue FolderNotFound
|
58
58
|
[]
|
59
59
|
rescue NoMethodError
|
@@ -72,15 +72,14 @@ module Imap::Backup
|
|
72
72
|
examine
|
73
73
|
fetch_data_items =
|
74
74
|
retry_on_error(errors: UID_FETCH_RETRY_CLASSES) do
|
75
|
-
|
75
|
+
client.uid_fetch([uid.to_i], [BODY_ATTRIBUTE])
|
76
76
|
end
|
77
77
|
return nil if fetch_data_items.nil?
|
78
78
|
|
79
79
|
fetch_data_item = fetch_data_items[0]
|
80
80
|
attributes = fetch_data_item.attr
|
81
|
-
return nil if !attributes.key?("RFC822")
|
82
81
|
|
83
|
-
attributes
|
82
|
+
attributes[BODY_ATTRIBUTE]
|
84
83
|
rescue FolderNotFound
|
85
84
|
nil
|
86
85
|
end
|
@@ -88,14 +87,14 @@ module Imap::Backup
|
|
88
87
|
def append(message)
|
89
88
|
body = message.imap_body
|
90
89
|
date = message.date&.to_time
|
91
|
-
response =
|
90
|
+
response = client.append(utf7_encoded_name, body, nil, date)
|
92
91
|
extract_uid(response)
|
93
92
|
end
|
94
93
|
|
95
94
|
private
|
96
95
|
|
97
96
|
def examine
|
98
|
-
|
97
|
+
client.examine(utf7_encoded_name)
|
99
98
|
rescue Net::IMAP::NoResponseError
|
100
99
|
Imap::Backup.logger.warn "Folder '#{name}' does not exist on server"
|
101
100
|
raise FolderNotFound, "Folder '#{name}' does not exist on server"
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Imap::Backup
|
2
|
+
class Account
|
3
|
+
attr_reader :username
|
4
|
+
attr_reader :password
|
5
|
+
attr_reader :local_path
|
6
|
+
attr_reader :folders
|
7
|
+
attr_reader :server
|
8
|
+
attr_reader :connection_options
|
9
|
+
attr_reader :changes
|
10
|
+
attr_reader :marked_for_deletion
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@username = options[:username]
|
14
|
+
@password = options[:password]
|
15
|
+
@local_path = options[:local_path]
|
16
|
+
@folders = options[:folders]
|
17
|
+
@server = options[:server]
|
18
|
+
@connection_options = options[:connection_options]
|
19
|
+
@changes = {}
|
20
|
+
@marked_for_deletion = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
username && password
|
25
|
+
end
|
26
|
+
|
27
|
+
def modified?
|
28
|
+
changes.any?
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear_changes!
|
32
|
+
@changes = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def mark_for_deletion!
|
36
|
+
@marked_for_deletion = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def marked_for_deletion?
|
40
|
+
@marked_for_deletion
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_h
|
44
|
+
h = {
|
45
|
+
username: @username,
|
46
|
+
password: @password,
|
47
|
+
}
|
48
|
+
h[:local_path] = @local_path if @local_path
|
49
|
+
h[:folders] = @folders if @folders
|
50
|
+
h[:server] = @server if @server
|
51
|
+
h[:connection_options] = @connection_options if @connection_options
|
52
|
+
h
|
53
|
+
end
|
54
|
+
|
55
|
+
def username=(value)
|
56
|
+
update(:username, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
def password=(value)
|
60
|
+
update(:password, value)
|
61
|
+
end
|
62
|
+
|
63
|
+
def local_path=(value)
|
64
|
+
update(:local_path, value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def folders=(value)
|
68
|
+
raise "folders must be an Array" if !value.is_a?(Array)
|
69
|
+
update(:folders, value)
|
70
|
+
end
|
71
|
+
|
72
|
+
def server=(value)
|
73
|
+
update(:server, value)
|
74
|
+
end
|
75
|
+
|
76
|
+
def connection_options=(value)
|
77
|
+
parsed = JSON.parse(value)
|
78
|
+
update(:connection_options, parsed)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def update(field, value)
|
84
|
+
if changes[field]
|
85
|
+
change = changes[field]
|
86
|
+
if change[:from] == value
|
87
|
+
changes.delete(field)
|
88
|
+
else
|
89
|
+
set_field!(field, value)
|
90
|
+
end
|
91
|
+
else
|
92
|
+
set_field!(field, value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_field!(field, value)
|
97
|
+
key = :"@#{field}"
|
98
|
+
current = instance_variable_get(key)
|
99
|
+
changes[field] = {from: current, to: value}
|
100
|
+
instance_variable_set(key, value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -5,6 +5,20 @@ module Imap::Backup::CLI::Helpers
|
|
5
5
|
options.each.with_object({}) { |(k, v), acc| acc[k.intern] = v }
|
6
6
|
end
|
7
7
|
|
8
|
+
def account(email)
|
9
|
+
connections = Imap::Backup::Configuration::List.new
|
10
|
+
account = connections.accounts.find { |a| a[:username] == email }
|
11
|
+
raise "#{email} is not a configured account" if !account
|
12
|
+
|
13
|
+
account
|
14
|
+
end
|
15
|
+
|
16
|
+
def connection(email)
|
17
|
+
account = account(email)
|
18
|
+
|
19
|
+
Imap::Backup::Account::Connection.new(account)
|
20
|
+
end
|
21
|
+
|
8
22
|
def each_connection(names)
|
9
23
|
begin
|
10
24
|
connections = Imap::Backup::Configuration::List.new(names)
|
@@ -6,49 +6,46 @@ module Imap::Backup
|
|
6
6
|
desc "accounts", "List locally backed-up accounts"
|
7
7
|
def accounts
|
8
8
|
connections = Imap::Backup::Configuration::List.new
|
9
|
-
connections.accounts.each { |a| puts a[:username] }
|
9
|
+
connections.accounts.each { |a| Kernel.puts a[:username] }
|
10
10
|
end
|
11
11
|
|
12
12
|
desc "folders EMAIL", "List account folders"
|
13
13
|
def folders(email)
|
14
|
-
|
15
|
-
account = connections.accounts.find { |a| a[:username] == email }
|
16
|
-
raise "#{email} is not a configured account" if !account
|
14
|
+
connection = connection(email)
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
puts %("#{f.name}")
|
16
|
+
connection.local_folders.each do |_s, f|
|
17
|
+
Kernel.puts %("#{f.name}")
|
21
18
|
end
|
22
19
|
end
|
23
20
|
|
24
21
|
desc "list EMAIL FOLDER", "List emails in a folder"
|
25
22
|
def list(email, folder_name)
|
26
|
-
|
27
|
-
account = connections.accounts.find { |a| a[:username] == email }
|
28
|
-
raise "#{email} is not a configured account" if !account
|
23
|
+
connection = connection(email)
|
29
24
|
|
30
|
-
|
31
|
-
folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
|
25
|
+
folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
|
32
26
|
f.name == folder_name
|
33
27
|
end
|
34
28
|
raise "Folder '#{folder_name}' not found" if !folder_serializer
|
35
29
|
|
36
30
|
max_subject = 60
|
37
|
-
puts format(
|
38
|
-
|
31
|
+
Kernel.puts format(
|
32
|
+
"%-10<uid>s %-#{max_subject}<subject>s - %<date>s",
|
33
|
+
{uid: "UID", subject: "Subject", date: "Date"}
|
34
|
+
)
|
35
|
+
Kernel.puts "-" * (12 + max_subject + 28)
|
39
36
|
|
40
37
|
uids = folder_serializer.uids
|
41
38
|
|
42
39
|
folder_serializer.each_message(uids).map do |uid, message|
|
43
40
|
m = {
|
44
41
|
uid: uid,
|
45
|
-
date: message.
|
46
|
-
subject: message.
|
42
|
+
date: message.date.to_s,
|
43
|
+
subject: message.subject || ""
|
47
44
|
}
|
48
45
|
if m[:subject].length > max_subject
|
49
|
-
puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
|
46
|
+
Kernel.puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
|
50
47
|
else
|
51
|
-
puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
|
48
|
+
Kernel.puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
|
52
49
|
end
|
53
50
|
end
|
54
51
|
end
|
@@ -60,12 +57,9 @@ module Imap::Backup
|
|
60
57
|
the UID.
|
61
58
|
DESC
|
62
59
|
def show(email, folder_name, uids)
|
63
|
-
|
64
|
-
account = connections.accounts.find { |a| a[:username] == email }
|
65
|
-
raise "#{email} is not a configured account" if !account
|
60
|
+
connection = connection(email)
|
66
61
|
|
67
|
-
|
68
|
-
folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
|
62
|
+
folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
|
69
63
|
f.name == folder_name
|
70
64
|
end
|
71
65
|
raise "Folder '#{folder_name}' not found" if !folder_serializer
|
@@ -73,13 +67,13 @@ module Imap::Backup
|
|
73
67
|
uid_list = uids.split(",")
|
74
68
|
folder_serializer.each_message(uid_list).each do |uid, message|
|
75
69
|
if uid_list.count > 1
|
76
|
-
puts <<~HEADER
|
70
|
+
Kernel.puts <<~HEADER
|
77
71
|
#{'-' * 80}
|
78
72
|
#{format('| UID: %-71s |', uid)}
|
79
73
|
#{'-' * 80}
|
80
74
|
HEADER
|
81
75
|
end
|
82
|
-
puts message.supplied_body
|
76
|
+
Kernel.puts message.supplied_body
|
83
77
|
end
|
84
78
|
end
|
85
79
|
end
|