imap-backup 4.0.3 → 4.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/email/provider/apple_mail.rb +2 -2
- data/lib/email/provider/base.rb +8 -0
- data/lib/email/provider/fastmail.rb +2 -2
- data/lib/email/provider/gmail.rb +2 -2
- data/lib/email/provider/{default.rb → unknown.rb} +2 -3
- data/lib/email/provider.rb +2 -2
- data/lib/imap/backup/account/connection.rb +23 -31
- data/lib/imap/backup/account/folder.rb +1 -1
- data/lib/imap/backup/account.rb +98 -0
- data/lib/imap/backup/cli/helpers.rb +1 -1
- data/lib/imap/backup/cli/local.rb +1 -1
- data/lib/imap/backup/configuration/account.rb +38 -30
- data/lib/imap/backup/configuration/folder_chooser.rb +7 -9
- data/lib/imap/backup/configuration/list.rb +1 -1
- data/lib/imap/backup/configuration/setup.rb +10 -8
- data/lib/imap/backup/configuration/store.rb +33 -11
- data/lib/imap/backup/version.rb +1 -1
- data/lib/imap/backup.rb +1 -0
- data/spec/features/support/shared/connection_context.rb +7 -5
- data/spec/unit/email/provider/{default_spec.rb → base_spec.rb} +1 -7
- data/spec/unit/email/provider_spec.rb +2 -2
- data/spec/unit/imap/backup/account/connection_spec.rb +8 -17
- data/spec/unit/imap/backup/cli/local_spec.rb +9 -2
- data/spec/unit/imap/backup/cli/utils_spec.rb +44 -42
- data/spec/unit/imap/backup/configuration/account_spec.rb +47 -46
- data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +17 -18
- data/spec/unit/imap/backup/configuration/list_spec.rb +12 -5
- data/spec/unit/imap/backup/configuration/setup_spec.rb +33 -12
- data/spec/unit/imap/backup/configuration/store_spec.rb +21 -22
- metadata +32 -32
- data/spec/support/shared_examples/account_flagging.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5819f0b50ce3de10cfedb1cdb5381e51f2d94f00dc2bcdd99234f57855c9959d
|
4
|
+
data.tar.gz: a140267c179d6002a7186f8591743abbfea2dca7697b7f1761feaa359fd1521c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b7d49f159df4d29582cf98f01ce105769301bcf94fd019486f1e0b43321eb90594e16861e24fe9d7993a76eeba0c115d6d991b64c1188020b09d04ea8db0714
|
7
|
+
data.tar.gz: 7dacdd3c5c3835e1925cd36a3beaaf7cdf6bf98d4bf7f02bbdd4abe3635512708c03654c3da9dfbfcf35f4e94a46dd43a3fc9e6e4693dd2b943d34d4a9ec8b02
|
data/lib/email/provider/gmail.rb
CHANGED
data/lib/email/provider.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require "email/provider/default"
|
2
1
|
require "email/provider/apple_mail"
|
3
2
|
require "email/provider/fastmail"
|
4
3
|
require "email/provider/gmail"
|
4
|
+
require "email/provider/unknown"
|
5
5
|
|
6
6
|
module Email; end
|
7
7
|
|
@@ -21,7 +21,7 @@ class Email::Provider
|
|
21
21
|
when address.end_with?("@me.com")
|
22
22
|
Email::Provider::AppleMail.new
|
23
23
|
else
|
24
|
-
Email::Provider::
|
24
|
+
Email::Provider::Unknown.new
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -4,25 +4,17 @@ require "imap/backup/client/default"
|
|
4
4
|
require "retry_on_error"
|
5
5
|
|
6
6
|
module Imap::Backup
|
7
|
-
|
7
|
+
class Account; end
|
8
8
|
|
9
9
|
class Account::Connection
|
10
10
|
include RetryOnError
|
11
11
|
|
12
12
|
LOGIN_RETRY_CLASSES = [EOFError, Errno::ECONNRESET, SocketError].freeze
|
13
13
|
|
14
|
-
attr_reader :
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(options)
|
20
|
-
@username = options[:username]
|
21
|
-
@password = options[:password]
|
22
|
-
@local_path = options[:local_path]
|
23
|
-
@config_folders = options[:folders]
|
24
|
-
@server = options[:server]
|
25
|
-
@connection_options = options[:connection_options] || {}
|
14
|
+
attr_reader :account
|
15
|
+
|
16
|
+
def initialize(account)
|
17
|
+
@account = account
|
26
18
|
@folders = nil
|
27
19
|
create_account_folder
|
28
20
|
end
|
@@ -33,7 +25,7 @@ module Imap::Backup
|
|
33
25
|
folders = client.list
|
34
26
|
|
35
27
|
if folders.empty?
|
36
|
-
message = "Unable to get folder list for account #{username}"
|
28
|
+
message = "Unable to get folder list for account #{account.username}"
|
37
29
|
Imap::Backup.logger.info message
|
38
30
|
raise message
|
39
31
|
end
|
@@ -45,13 +37,13 @@ module Imap::Backup
|
|
45
37
|
def status
|
46
38
|
backup_folders.map do |backup_folder|
|
47
39
|
f = Account::Folder.new(self, backup_folder[:name])
|
48
|
-
s = Serializer::Mbox.new(local_path, backup_folder[:name])
|
40
|
+
s = Serializer::Mbox.new(account.local_path, backup_folder[:name])
|
49
41
|
{name: backup_folder[:name], local: s.uids, remote: f.uids}
|
50
42
|
end
|
51
43
|
end
|
52
44
|
|
53
45
|
def run_backup
|
54
|
-
Imap::Backup.logger.debug "Running backup of account: #{username}"
|
46
|
+
Imap::Backup.logger.debug "Running backup of account: #{account.username}"
|
55
47
|
# start the connection so we get logging messages in the right order
|
56
48
|
client
|
57
49
|
each_folder do |folder, serializer|
|
@@ -71,11 +63,11 @@ module Imap::Backup
|
|
71
63
|
def local_folders
|
72
64
|
return enum_for(:local_folders) if !block_given?
|
73
65
|
|
74
|
-
glob = File.join(local_path, "**", "*.imap")
|
75
|
-
base = Pathname.new(local_path)
|
66
|
+
glob = File.join(account.local_path, "**", "*.imap")
|
67
|
+
base = Pathname.new(account.local_path)
|
76
68
|
Pathname.glob(glob) do |path|
|
77
69
|
name = path.relative_path_from(base).to_s[0..-6]
|
78
|
-
serializer = Serializer::Mbox.new(local_path, name)
|
70
|
+
serializer = Serializer::Mbox.new(account.local_path, name)
|
79
71
|
folder = Account::Folder.new(self, name)
|
80
72
|
yield serializer, folder
|
81
73
|
end
|
@@ -109,15 +101,15 @@ module Imap::Backup
|
|
109
101
|
else
|
110
102
|
Client::Default.new(server, options)
|
111
103
|
end
|
112
|
-
Imap::Backup.logger.debug "Logging in: #{username}/#{masked_password}"
|
113
|
-
client.login(username, password)
|
104
|
+
Imap::Backup.logger.debug "Logging in: #{account.username}/#{masked_password}"
|
105
|
+
client.login(account.username, account.password)
|
114
106
|
Imap::Backup.logger.debug "Login complete"
|
115
107
|
client
|
116
108
|
end
|
117
109
|
end
|
118
110
|
|
119
111
|
def server
|
120
|
-
@server ||= provider.host
|
112
|
+
@server ||= account.server || provider.host
|
121
113
|
end
|
122
114
|
|
123
115
|
private
|
@@ -125,7 +117,7 @@ module Imap::Backup
|
|
125
117
|
def each_folder
|
126
118
|
backup_folders.each do |backup_folder|
|
127
119
|
folder = Account::Folder.new(self, backup_folder[:name])
|
128
|
-
serializer = Serializer::Mbox.new(local_path, backup_folder[:name])
|
120
|
+
serializer = Serializer::Mbox.new(account.local_path, backup_folder[:name])
|
129
121
|
yield folder, serializer
|
130
122
|
end
|
131
123
|
end
|
@@ -142,7 +134,7 @@ module Imap::Backup
|
|
142
134
|
Imap::Backup.logger.debug(
|
143
135
|
"Backup '#{old_name}' renamed and restored to '#{new_name}'"
|
144
136
|
)
|
145
|
-
new_serializer = Serializer::Mbox.new(local_path, new_name)
|
137
|
+
new_serializer = Serializer::Mbox.new(account.local_path, new_name)
|
146
138
|
new_folder = Account::Folder.new(self, new_name)
|
147
139
|
new_folder.create
|
148
140
|
new_serializer.force_uid_validity(new_folder.uid_validity)
|
@@ -159,21 +151,21 @@ module Imap::Backup
|
|
159
151
|
|
160
152
|
def create_account_folder
|
161
153
|
Utils.make_folder(
|
162
|
-
File.dirname(local_path),
|
163
|
-
File.basename(local_path),
|
154
|
+
File.dirname(account.local_path),
|
155
|
+
File.basename(account.local_path),
|
164
156
|
Serializer::DIRECTORY_PERMISSIONS
|
165
157
|
)
|
166
158
|
end
|
167
159
|
|
168
160
|
def masked_password
|
169
|
-
password.gsub(/./, "x")
|
161
|
+
account.password.gsub(/./, "x")
|
170
162
|
end
|
171
163
|
|
172
164
|
def backup_folders
|
173
165
|
@backup_folders ||=
|
174
166
|
begin
|
175
|
-
if
|
176
|
-
|
167
|
+
if account.folders&.any?
|
168
|
+
account.folders
|
177
169
|
else
|
178
170
|
folders.map { |name| {name: name} }
|
179
171
|
end
|
@@ -181,11 +173,11 @@ module Imap::Backup
|
|
181
173
|
end
|
182
174
|
|
183
175
|
def provider
|
184
|
-
@provider ||= Email::Provider.for_address(username)
|
176
|
+
@provider ||= Email::Provider.for_address(account.username)
|
185
177
|
end
|
186
178
|
|
187
179
|
def provider_options
|
188
|
-
provider.options.merge(connection_options)
|
180
|
+
provider.options.merge(account.connection_options || {})
|
189
181
|
end
|
190
182
|
end
|
191
183
|
end
|
@@ -0,0 +1,98 @@
|
|
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
|
+
changes.delete(field) if change[:from] == value
|
87
|
+
end
|
88
|
+
set_field!(field, value)
|
89
|
+
end
|
90
|
+
|
91
|
+
def set_field!(field, value)
|
92
|
+
key = :"@#{field}"
|
93
|
+
current = instance_variable_get(key)
|
94
|
+
changes[field] = {from: current, to: value}
|
95
|
+
instance_variable_set(key, value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -7,7 +7,7 @@ module Imap::Backup::CLI::Helpers
|
|
7
7
|
|
8
8
|
def account(email)
|
9
9
|
connections = Imap::Backup::Configuration::List.new
|
10
|
-
account = connections.accounts.find { |a| a
|
10
|
+
account = connections.accounts.find { |a| a.username == email }
|
11
11
|
raise "#{email} is not a configured account" if !account
|
12
12
|
|
13
13
|
account
|
@@ -6,7 +6,7 @@ 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| Kernel.puts a
|
9
|
+
connections.accounts.each { |a| Kernel.puts a.username }
|
10
10
|
end
|
11
11
|
|
12
12
|
desc "folders EMAIL", "List account folders"
|
@@ -22,9 +22,10 @@ module Imap::Backup
|
|
22
22
|
header menu
|
23
23
|
modify_email menu
|
24
24
|
modify_password menu
|
25
|
-
modify_server menu
|
26
25
|
modify_backup_path menu
|
27
26
|
choose_folders menu
|
27
|
+
modify_server menu
|
28
|
+
modify_connection_options menu
|
28
29
|
test_connection menu
|
29
30
|
delete_account menu
|
30
31
|
menu.choice("return to main menu") { throw :done }
|
@@ -33,13 +34,20 @@ module Imap::Backup
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def header(menu)
|
36
|
-
|
37
|
+
connection_options =
|
38
|
+
if account.connection_options
|
39
|
+
escaped =
|
40
|
+
JSON.generate(account.connection_options).
|
41
|
+
gsub('"', '\"')
|
42
|
+
"\n connection options: #{escaped}"
|
43
|
+
end
|
44
|
+
menu.header = <<~HEADER
|
37
45
|
Account:
|
38
|
-
email: #{account
|
39
|
-
server: #{account[:server]}
|
40
|
-
path: #{account[:local_path]}
|
41
|
-
folders: #{folders.map { |f| f[:name] }.join(', ')}
|
46
|
+
email: #{account.username}
|
42
47
|
password: #{masked_password}
|
48
|
+
path: #{account.local_path}
|
49
|
+
folders: #{folders.map { |f| f[:name] }.join(', ')}
|
50
|
+
server: #{account.server}#{connection_options}
|
43
51
|
HEADER
|
44
52
|
end
|
45
53
|
|
@@ -48,20 +56,20 @@ module Imap::Backup
|
|
48
56
|
username = Configuration::Asker.email(username)
|
49
57
|
Kernel.puts "username: #{username}"
|
50
58
|
other_accounts = store.accounts.reject { |a| a == account }
|
51
|
-
others = other_accounts.map { |a| a
|
59
|
+
others = other_accounts.map { |a| a.username }
|
52
60
|
Kernel.puts "others: #{others.inspect}"
|
53
61
|
if others.include?(username)
|
54
62
|
Kernel.puts(
|
55
63
|
"There is already an account set up with that email address"
|
56
64
|
)
|
57
65
|
else
|
58
|
-
account
|
66
|
+
account.username = username
|
59
67
|
# rubocop:disable Style/IfUnlessModifier
|
60
|
-
|
61
|
-
|
68
|
+
default = default_server(username)
|
69
|
+
if default && (account.server.nil? || (account.server == ""))
|
70
|
+
account.server = default
|
62
71
|
end
|
63
72
|
# rubocop:enable Style/IfUnlessModifier
|
64
|
-
account[:modified] = true
|
65
73
|
end
|
66
74
|
end
|
67
75
|
end
|
@@ -70,30 +78,31 @@ module Imap::Backup
|
|
70
78
|
menu.choice("modify password") do
|
71
79
|
password = Configuration::Asker.password
|
72
80
|
|
73
|
-
if !password.nil?
|
74
|
-
account[:password] = password
|
75
|
-
account[:modified] = true
|
76
|
-
end
|
81
|
+
account.password = password if !password.nil?
|
77
82
|
end
|
78
83
|
end
|
79
84
|
|
80
85
|
def modify_server(menu)
|
81
86
|
menu.choice("modify server") do
|
82
87
|
server = highline.ask("server: ")
|
83
|
-
if !server.nil?
|
84
|
-
|
85
|
-
|
86
|
-
|
88
|
+
account.server = server if !server.nil?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def modify_connection_options(menu)
|
93
|
+
menu.choice("modify connection options") do
|
94
|
+
connection_options = highline.ask("connections options (as JSON): ")
|
95
|
+
account.connection_options = connection_options if !connection_options.nil?
|
87
96
|
end
|
88
97
|
end
|
89
98
|
|
90
99
|
def path_modification_validator(path)
|
91
100
|
same = store.accounts.find do |a|
|
92
|
-
a
|
101
|
+
a.username != account.username && a.local_path == path
|
93
102
|
end
|
94
103
|
if same
|
95
104
|
Kernel.puts "The path '#{path}' is used to backup " \
|
96
|
-
"the account '#{same
|
105
|
+
"the account '#{same.username}'"
|
97
106
|
false
|
98
107
|
else
|
99
108
|
true
|
@@ -102,11 +111,10 @@ module Imap::Backup
|
|
102
111
|
|
103
112
|
def modify_backup_path(menu)
|
104
113
|
menu.choice("modify backup path") do
|
105
|
-
existing = account
|
106
|
-
account
|
107
|
-
account
|
114
|
+
existing = account.local_path.clone
|
115
|
+
account.local_path = Configuration::Asker.backup_path(
|
116
|
+
account.local_path, ->(path) { path_modification_validator(path) }
|
108
117
|
)
|
109
|
-
account[:modified] = true if existing != account[:local_path]
|
110
118
|
end
|
111
119
|
end
|
112
120
|
|
@@ -127,28 +135,28 @@ module Imap::Backup
|
|
127
135
|
def delete_account(menu)
|
128
136
|
menu.choice("delete") do
|
129
137
|
if highline.agree("Are you sure? (y/n) ")
|
130
|
-
account
|
138
|
+
account.mark_for_deletion!
|
131
139
|
throw :done
|
132
140
|
end
|
133
141
|
end
|
134
142
|
end
|
135
143
|
|
136
144
|
def folders
|
137
|
-
account
|
145
|
+
account.folders || []
|
138
146
|
end
|
139
147
|
|
140
148
|
def masked_password
|
141
|
-
if (account
|
149
|
+
if (account.password == "") || account.password.nil?
|
142
150
|
"(unset)"
|
143
151
|
else
|
144
|
-
account
|
152
|
+
account.password.gsub(/./, "x")
|
145
153
|
end
|
146
154
|
end
|
147
155
|
|
148
156
|
def default_server(username)
|
149
157
|
provider = Email::Provider.for_address(username)
|
150
158
|
|
151
|
-
if provider.is_a?(Email::Provider::
|
159
|
+
if provider.is_a?(Email::Provider::Unknown)
|
152
160
|
Kernel.puts "Can't decide provider for email address '#{username}'"
|
153
161
|
return nil
|
154
162
|
end
|
@@ -53,7 +53,7 @@ module Imap::Backup
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def selected?(folder_name)
|
56
|
-
config_folders = account
|
56
|
+
config_folders = account.folders
|
57
57
|
return false if config_folders.nil?
|
58
58
|
|
59
59
|
config_folders.find { |f| f[:name] == folder_name }
|
@@ -62,7 +62,7 @@ module Imap::Backup
|
|
62
62
|
def remove_missing
|
63
63
|
removed = []
|
64
64
|
config_folders = []
|
65
|
-
account
|
65
|
+
account.folders.each do |f|
|
66
66
|
found = imap_folders.find { |folder| folder == f[:name] }
|
67
67
|
if found
|
68
68
|
config_folders << f
|
@@ -73,8 +73,7 @@ module Imap::Backup
|
|
73
73
|
|
74
74
|
return if removed.empty?
|
75
75
|
|
76
|
-
account
|
77
|
-
account[:modified] = true
|
76
|
+
account.folders = config_folders
|
78
77
|
|
79
78
|
Kernel.puts <<~MESSAGE
|
80
79
|
The following folders have been removed: #{removed.join(', ')}
|
@@ -85,12 +84,11 @@ module Imap::Backup
|
|
85
84
|
|
86
85
|
def toggle_selection(folder_name)
|
87
86
|
if selected?(folder_name)
|
88
|
-
|
89
|
-
account
|
87
|
+
new_list = account.folders.select { |f| f[:name] != folder_name }
|
88
|
+
account.folders = new_list
|
90
89
|
else
|
91
|
-
account
|
92
|
-
account
|
93
|
-
account[:modified] = true
|
90
|
+
existing = account.folders || []
|
91
|
+
account.folders = existing + [{name: folder_name}]
|
94
92
|
end
|
95
93
|
end
|
96
94
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require "highline"
|
2
2
|
|
3
|
+
require "imap/backup/account"
|
4
|
+
|
3
5
|
module Imap::Backup
|
4
6
|
module Configuration; end
|
5
7
|
|
@@ -39,12 +41,12 @@ module Imap::Backup
|
|
39
41
|
|
40
42
|
def account_items(menu)
|
41
43
|
config.accounts.each do |account|
|
42
|
-
next if account
|
44
|
+
next if account.marked_for_deletion?
|
43
45
|
|
44
|
-
item = account
|
45
|
-
item << " *" if account
|
46
|
+
item = account.username.clone
|
47
|
+
item << " *" if account.modified?
|
46
48
|
menu.choice(item) do
|
47
|
-
edit_account account
|
49
|
+
edit_account account.username
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -70,19 +72,19 @@ module Imap::Backup
|
|
70
72
|
end
|
71
73
|
|
72
74
|
def default_account_config(username)
|
73
|
-
|
75
|
+
::Imap::Backup::Account.new(
|
74
76
|
username: username,
|
75
77
|
password: "",
|
76
78
|
local_path: File.join(config.path, username.tr("@", "_")),
|
77
79
|
folders: []
|
78
|
-
|
80
|
+
).tap do |a|
|
79
81
|
server = Email::Provider.for_address(username)
|
80
|
-
|
82
|
+
a.server = server.host if server.host
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
86
|
def edit_account(username)
|
85
|
-
account = config.accounts.find { |a| a
|
87
|
+
account = config.accounts.find { |a| a.username == username }
|
86
88
|
if account.nil?
|
87
89
|
account = default_account_config(username)
|
88
90
|
config.accounts << account
|