mournmail 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/lib/mournmail/commands.rb +11 -2
- data/lib/mournmail/config.rb +8 -0
- data/lib/mournmail/draft_mode.rb +23 -2
- data/lib/mournmail/message_mode.rb +16 -10
- data/lib/mournmail/message_rendering.rb +78 -18
- data/lib/mournmail/summary.rb +2 -1
- data/lib/mournmail/summary_mode.rb +19 -12
- data/lib/mournmail/utils.rb +26 -4
- data/lib/mournmail/version.rb +1 -1
- data/mournmail.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cbf82ccf54ab48f7596d24aaacb4673ca8f8271f304264df7aa96a932dac2fb
|
4
|
+
data.tar.gz: facbe695e21c68a1b5c50a9bb9d50894f948e09bab2a436b2174656953b809bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49c6ba544f435ea5eb150b510e26d18ab0bcd0fddd1a1a147dc0aee84bde05656bb153f44628ee0828b2e02c8f6ccc27b75c7e61b34ca0511c0eb2f074240e1e
|
7
|
+
data.tar.gz: 43accf4207ec48914c79940d2c45ce931beab826759b3e64174257891bf70d741913800aa976b41c19a2b47d1a0c8e32a00215995889058fdee5c82b4bc6e5e0
|
data/README.md
CHANGED
@@ -33,7 +33,11 @@ CONFIG[:mournmail_accounts] = {
|
|
33
33
|
},
|
34
34
|
spam_mailbox: "spam",
|
35
35
|
outbox_mailbox: "outbox",
|
36
|
-
archive_mailbox_format: "archive/%Y"
|
36
|
+
archive_mailbox_format: "archive/%Y",
|
37
|
+
signature: <<~EOF
|
38
|
+
--
|
39
|
+
Shugo Maeda <shugo@example.com>
|
40
|
+
EOF
|
37
41
|
},
|
38
42
|
"gmail.com" => {
|
39
43
|
from: "Example <example@gmail.com>",
|
@@ -54,7 +58,7 @@ CONFIG[:mournmail_accounts] = {
|
|
54
58
|
password: File.read(File.expand_path("~/.textbringer/gmail_passwd")).chomp,
|
55
59
|
ssl: true
|
56
60
|
},
|
57
|
-
spam_mailbox: "
|
61
|
+
spam_mailbox: "[Gmail]/迷惑メール",
|
58
62
|
archive_mailbox_format: false
|
59
63
|
},
|
60
64
|
}
|
data/lib/mournmail/commands.rb
CHANGED
@@ -11,6 +11,14 @@ define_command(:mournmail_visit_mailbox, doc: "Visit mailbox") do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
define_command(:mournmail_visit_spam_mailbox, doc: "Visit spam mailbox") do
|
15
|
+
mailbox = Mournmail.account_config[:spam_mailbox]
|
16
|
+
if mailbox.nil?
|
17
|
+
raise EditorError, "spam_mailbox is not specified"
|
18
|
+
end
|
19
|
+
mournmail_visit_mailbox(Net::IMAP.encode_utf7(mailbox))
|
20
|
+
end
|
21
|
+
|
14
22
|
define_command(:mournmail_summary_sync, doc: "Sync summary.") do
|
15
23
|
|mailbox = (Mournmail.current_mailbox || "INBOX"),
|
16
24
|
all = current_prefix_arg|
|
@@ -61,9 +69,10 @@ define_command(:mail, doc: "Write a new mail.") do
|
|
61
69
|
User-Agent: Mournmail/#{Mournmail::VERSION} Textbringer/#{Textbringer::VERSION} Ruby/#{RUBY_VERSION}
|
62
70
|
--text follows this line--
|
63
71
|
EOF
|
64
|
-
|
65
|
-
|
72
|
+
beginning_of_buffer
|
73
|
+
re_search_forward(/^To: */)
|
66
74
|
if run_hooks
|
75
|
+
Mournmail.insert_signature
|
67
76
|
run_hooks(:mournmail_draft_setup_hook)
|
68
77
|
end
|
69
78
|
end
|
data/lib/mournmail/config.rb
CHANGED
@@ -14,6 +14,13 @@ module Textbringer
|
|
14
14
|
"X-Mailer",
|
15
15
|
"Content-Type"
|
16
16
|
]
|
17
|
+
CONFIG[:mournmail_quote_header_fields] = [
|
18
|
+
"Subject",
|
19
|
+
"Date",
|
20
|
+
"From",
|
21
|
+
"To",
|
22
|
+
"Cc"
|
23
|
+
]
|
17
24
|
CONFIG[:mournmail_imap_connect_timeout] = 10
|
18
25
|
CONFIG[:mournmail_keep_alive_interval] = 60
|
19
26
|
case RUBY_PLATFORM
|
@@ -28,4 +35,5 @@ module Textbringer
|
|
28
35
|
CONFIG[:mournmail_link_open_comamnd] = "xdg-open"
|
29
36
|
end
|
30
37
|
CONFIG[:mournmail_addresses_path] = File.expand_path("~/.addresses")
|
38
|
+
CONFIG[:mournmail_signature_regexp] = /^\n-- /
|
31
39
|
end
|
data/lib/mournmail/draft_mode.rb
CHANGED
@@ -8,6 +8,7 @@ module Mournmail
|
|
8
8
|
MAIL_MODE_MAP.define_key("\C-c\C-xv", :draft_pgp_sign_command)
|
9
9
|
MAIL_MODE_MAP.define_key("\C-c\C-xe", :draft_pgp_encrypt_command)
|
10
10
|
MAIL_MODE_MAP.define_key("\C-c\t", :insert_signature_command)
|
11
|
+
MAIL_MODE_MAP.define_key("\C-c@", :draft_change_account_command)
|
11
12
|
|
12
13
|
define_syntax :field_name, /^[A-Za-z\-]+: /
|
13
14
|
define_syntax :quotation, /^>.*/
|
@@ -68,12 +69,15 @@ module Mournmail
|
|
68
69
|
content: File.read(file),
|
69
70
|
encoding: "binary")
|
70
71
|
end
|
71
|
-
|
72
|
+
account = @buffer[:mournmail_delivery_account] ||
|
73
|
+
Mournmail.current_account
|
74
|
+
conf = CONFIG[:mournmail_accounts][account]
|
72
75
|
options = @buffer[:mournmail_delivery_options] ||
|
73
76
|
conf[:delivery_options]
|
74
77
|
if options[:authentication] == "gmail"
|
78
|
+
token = Mournmail.google_access_token(account)
|
75
79
|
options = options.merge(authentication: "xoauth2",
|
76
|
-
password:
|
80
|
+
password: token)
|
77
81
|
end
|
78
82
|
m.delivery_method(@buffer[:mournmail_delivery_method] ||
|
79
83
|
conf[:delivery_method],
|
@@ -186,6 +190,23 @@ module Mournmail
|
|
186
190
|
@buffer.insert(CONFIG[:signature])
|
187
191
|
end
|
188
192
|
|
193
|
+
define_local_command(:draft_change_account, doc: "Change account.") do
|
194
|
+
|account = Mournmail.read_account_name("Change account: ")|
|
195
|
+
from = CONFIG[:mournmail_accounts][account][:from]
|
196
|
+
@buffer[:mournmail_delivery_account] = account
|
197
|
+
@buffer.save_excursion do
|
198
|
+
@buffer.beginning_of_buffer
|
199
|
+
@buffer.re_search_forward(/^From:.*/)
|
200
|
+
@buffer.replace_match("From: " + from)
|
201
|
+
@buffer.end_of_buffer
|
202
|
+
if @buffer.re_search_backward(CONFIG[:mournmail_signature_regexp],
|
203
|
+
raise_error: false)
|
204
|
+
@buffer.delete_region(@buffer.point, @buffer.point_max)
|
205
|
+
end
|
206
|
+
Mournmail.insert_signature
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
189
210
|
private
|
190
211
|
|
191
212
|
def end_of_header
|
@@ -12,7 +12,7 @@ module Mournmail
|
|
12
12
|
|
13
13
|
# See http://nihongo.jp/support/mail_guide/dev_guide.txt
|
14
14
|
MAILTO_REGEXP = URI.regexp("mailto")
|
15
|
-
URI_REGEXP = /(https?|ftp):\/\/[^ \t\n>)"]*[
|
15
|
+
URI_REGEXP = /(https?|ftp):\/\/[^ \t\n>)"]*[^\] \t\n>.,:)"]+|#{MAILTO_REGEXP}/
|
16
16
|
MIME_REGEXP = /^\[(([0-9.]+) [A-Za-z._\-]+\/[A-Za-z._\-]+.*|PGP\/MIME .*)\]$/
|
17
17
|
URI_OR_MIME_REGEXP = /#{URI_REGEXP}|#{MIME_REGEXP}/
|
18
18
|
|
@@ -24,6 +24,7 @@ module Mournmail
|
|
24
24
|
def initialize(buffer)
|
25
25
|
super(buffer)
|
26
26
|
buffer.keymap = MESSAGE_MODE_MAP
|
27
|
+
@attached_file = nil
|
27
28
|
end
|
28
29
|
|
29
30
|
define_local_command(:message_open_link_or_part,
|
@@ -52,6 +53,9 @@ module Mournmail
|
|
52
53
|
|
53
54
|
define_local_command(:message_next_link_or_part,
|
54
55
|
doc: "Go to the next link or MIME part.") do
|
56
|
+
if @buffer.looking_at?(URI_OR_MIME_REGEXP)
|
57
|
+
@buffer.forward_char
|
58
|
+
end
|
55
59
|
if @buffer.re_search_forward(URI_OR_MIME_REGEXP, raise_error: false)
|
56
60
|
goto_char(@buffer.match_beginning(0))
|
57
61
|
else
|
@@ -76,8 +80,8 @@ module Mournmail
|
|
76
80
|
|
77
81
|
def part_file_name(part)
|
78
82
|
file_name =
|
79
|
-
part["content-disposition"]&.parameters&.[]("filename") ||
|
80
|
-
part["content-type"]&.parameters&.[]("name") ||
|
83
|
+
(part["content-disposition"]&.parameters&.[]("filename") rescue nil) ||
|
84
|
+
(part["content-type"]&.parameters&.[]("name") rescue nil) ||
|
81
85
|
part_default_file_name(part)
|
82
86
|
decoded_file_name = Mail::Encodings.decode_encode(file_name, :decode)
|
83
87
|
if /\A([A-Za-z0-9_\-]+)'(?:[A-Za-z0-9_\-])*'(.*)/ =~ decoded_file_name
|
@@ -130,18 +134,20 @@ module Mournmail
|
|
130
134
|
else
|
131
135
|
file_name = "mournmail"
|
132
136
|
end
|
133
|
-
|
137
|
+
@attached_file = Tempfile.open(file_name, binmode: true)
|
134
138
|
s = part.decoded
|
135
|
-
if part.
|
139
|
+
if part.content_type == "text/html"
|
140
|
+
s = s.sub(/<meta http-equiv="content-type".*?>/i, "")
|
141
|
+
elsif part.charset
|
136
142
|
s = s.encode(part.charset)
|
137
143
|
end
|
138
|
-
|
139
|
-
|
140
|
-
if
|
141
|
-
find_file(
|
144
|
+
@attached_file.write(s)
|
145
|
+
@attached_file.close
|
146
|
+
if part.main_type == "text" && part.sub_type != "html"
|
147
|
+
find_file(@attached_file.path)
|
142
148
|
else
|
143
149
|
background do
|
144
|
-
system(*CONFIG[:mournmail_file_open_comamnd],
|
150
|
+
system(*CONFIG[:mournmail_file_open_comamnd], @attached_file.path,
|
145
151
|
out: File::NULL, err: File::NULL)
|
146
152
|
end
|
147
153
|
end
|
@@ -8,8 +8,8 @@ module Mournmail
|
|
8
8
|
render_header + "\n" + render_body(indices)
|
9
9
|
end
|
10
10
|
|
11
|
-
def render_header
|
12
|
-
|
11
|
+
def render_header(fields = CONFIG[:mournmail_display_header_fields])
|
12
|
+
fields.map { |name|
|
13
13
|
val = self[name]&.to_s&.gsub(/\t/, " ")
|
14
14
|
val ? "#{name}: #{val}\n" : ""
|
15
15
|
}.join
|
@@ -41,11 +41,36 @@ module Mournmail
|
|
41
41
|
else
|
42
42
|
type = Mail::Encodings.decode_encode(self["content-type"].to_s,
|
43
43
|
:decode) rescue
|
44
|
-
|
44
|
+
"broken/type; error=\"#{$!} (#{$!.class})\""
|
45
45
|
"[0 #{type}]\n"
|
46
46
|
end + pgp_signature
|
47
47
|
end
|
48
48
|
|
49
|
+
def render_text(indices = [])
|
50
|
+
if HAVE_MAIL_GPG && encrypted?
|
51
|
+
mail = decrypt(verify: true)
|
52
|
+
return mail.render_text(indices)
|
53
|
+
end
|
54
|
+
if multipart?
|
55
|
+
parts.each_with_index.map { |part, i|
|
56
|
+
if sub_type == "alternative" && i > 0
|
57
|
+
""
|
58
|
+
else
|
59
|
+
part.render_text([*indices, i])
|
60
|
+
end
|
61
|
+
}.join("\n")
|
62
|
+
elsif main_type.nil? || main_type == "text"
|
63
|
+
s = Mournmail.to_utf8(body.decoded, charset)
|
64
|
+
if sub_type == "html"
|
65
|
+
Html2Text.convert(s)
|
66
|
+
else
|
67
|
+
s
|
68
|
+
end
|
69
|
+
else
|
70
|
+
""
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
49
74
|
def dig_part(i, *rest_indices)
|
50
75
|
if HAVE_MAIL_GPG && encrypted?
|
51
76
|
mail = decrypt(verify: true)
|
@@ -91,7 +116,39 @@ module Mournmail
|
|
91
116
|
:decode) rescue
|
92
117
|
"broken/type; error=\"#{$!} (#{$!.class})\""
|
93
118
|
"[#{index} #{type}]\n" +
|
94
|
-
|
119
|
+
render_content(indices, no_content)
|
120
|
+
end
|
121
|
+
|
122
|
+
def render_text(indices)
|
123
|
+
if multipart?
|
124
|
+
parts.each_with_index.map { |part, i|
|
125
|
+
if sub_type == "alternative" && i > 0
|
126
|
+
""
|
127
|
+
else
|
128
|
+
part.render_text([*indices, i])
|
129
|
+
end
|
130
|
+
}.join("\n")
|
131
|
+
else
|
132
|
+
if main_type == "message" && sub_type == "rfc822"
|
133
|
+
mail = Mail.new(body.raw_source)
|
134
|
+
mail.render_header(CONFIG[:mournmail_quote_header_fields]) +
|
135
|
+
"\n" + mail.render_text(indices)
|
136
|
+
elsif attachment?
|
137
|
+
""
|
138
|
+
else
|
139
|
+
if main_type == "text"
|
140
|
+
if sub_type == "html"
|
141
|
+
Html2Text.convert(decoded).sub(/(?<!\n)\z/, "\n")
|
142
|
+
else
|
143
|
+
decoded.sub(/(?<!\n)\z/, "\n").gsub(/\r\n/, "\n")
|
144
|
+
end
|
145
|
+
else
|
146
|
+
""
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
rescue => e
|
151
|
+
""
|
95
152
|
end
|
96
153
|
|
97
154
|
def dig_part(i, *rest_indices)
|
@@ -110,26 +167,29 @@ module Mournmail
|
|
110
167
|
|
111
168
|
private
|
112
169
|
|
113
|
-
def render_content(indices)
|
170
|
+
def render_content(indices, no_content)
|
114
171
|
if multipart?
|
115
172
|
parts.each_with_index.map { |part, i|
|
116
|
-
|
117
|
-
|
173
|
+
part.render([*indices, i],
|
174
|
+
no_content || sub_type == "alternative" && i > 0)
|
118
175
|
}.join
|
119
|
-
elsif main_type == "message" && sub_type == "rfc822"
|
120
|
-
mail = Mail.new(body.raw_source)
|
121
|
-
mail.render(indices)
|
122
|
-
elsif attachment?
|
123
|
-
""
|
124
176
|
else
|
125
|
-
|
126
|
-
|
127
|
-
|
177
|
+
return "" if no_content
|
178
|
+
if main_type == "message" && sub_type == "rfc822"
|
179
|
+
mail = Mail.new(body.raw_source)
|
180
|
+
mail.render(indices)
|
181
|
+
elsif attachment?
|
182
|
+
""
|
183
|
+
else
|
184
|
+
if main_type == "text"
|
185
|
+
if sub_type == "html"
|
186
|
+
Html2Text.convert(decoded).sub(/(?<!\n)\z/, "\n")
|
187
|
+
else
|
188
|
+
decoded.sub(/(?<!\n)\z/, "\n").gsub(/\r\n/, "\n")
|
189
|
+
end
|
128
190
|
else
|
129
|
-
|
191
|
+
""
|
130
192
|
end
|
131
|
-
else
|
132
|
-
""
|
133
193
|
end
|
134
194
|
end
|
135
195
|
rescue => e
|
data/lib/mournmail/summary.rb
CHANGED
@@ -141,7 +141,8 @@ module Mournmail
|
|
141
141
|
end
|
142
142
|
s = data[0].attr["BODY[]"]
|
143
143
|
mail = Mournmail.parse_mail(s)
|
144
|
-
|
144
|
+
spam_mailbox = Mournmail.account_config[:spam_mailbox]
|
145
|
+
if @mailbox != Net::IMAP.encode_utf7(spam_mailbox)
|
145
146
|
item.cache_id = Mournmail.write_mail_cache(s)
|
146
147
|
Mournmail.index_mail(item.cache_id, mail)
|
147
148
|
end
|
@@ -25,6 +25,7 @@ module Mournmail
|
|
25
25
|
SUMMARY_MODE_MAP.define_key("*t", :summary_mark_unflagged_command)
|
26
26
|
SUMMARY_MODE_MAP.define_key("y", :summary_archive_command)
|
27
27
|
SUMMARY_MODE_MAP.define_key("o", :summary_refile_command)
|
28
|
+
SUMMARY_MODE_MAP.define_key("!", :summary_refile_spam_command)
|
28
29
|
SUMMARY_MODE_MAP.define_key("p", :summary_prefetch_command)
|
29
30
|
SUMMARY_MODE_MAP.define_key("X", :summary_expunge_command)
|
30
31
|
SUMMARY_MODE_MAP.define_key("v", :summary_view_source_command)
|
@@ -33,6 +34,7 @@ module Mournmail
|
|
33
34
|
SUMMARY_MODE_MAP.define_key("k", :previous_line)
|
34
35
|
SUMMARY_MODE_MAP.define_key("j", :next_line)
|
35
36
|
SUMMARY_MODE_MAP.define_key("m", :mournmail_visit_mailbox)
|
37
|
+
SUMMARY_MODE_MAP.define_key("S", :mournmail_visit_spam_mailbox)
|
36
38
|
SUMMARY_MODE_MAP.define_key("/", :summary_search_command)
|
37
39
|
SUMMARY_MODE_MAP.define_key("t", :summary_show_thread_command)
|
38
40
|
SUMMARY_MODE_MAP.define_key("@", :summary_change_account_command)
|
@@ -98,7 +100,7 @@ module Mournmail
|
|
98
100
|
|reply_all = current_prefix_arg|
|
99
101
|
Mournmail.background do
|
100
102
|
mail = read_current_mail[0]
|
101
|
-
body = mail.
|
103
|
+
body = mail.render_text
|
102
104
|
foreground do
|
103
105
|
Window.current = Mournmail.message_window
|
104
106
|
Commands.mail(run_hooks: false)
|
@@ -137,6 +139,7 @@ module Mournmail
|
|
137
139
|
On #{mail['date']}
|
138
140
|
#{mail['from']} wrote:
|
139
141
|
EOF
|
142
|
+
Mournmail.insert_signature
|
140
143
|
exchange_point_and_mark
|
141
144
|
run_hooks(:mournmail_draft_setup_hook)
|
142
145
|
end
|
@@ -373,10 +376,23 @@ module Mournmail
|
|
373
376
|
end
|
374
377
|
end
|
375
378
|
|
379
|
+
define_local_command(:summary_refile_spam,
|
380
|
+
doc: "Refile marked mails as spam.") do
|
381
|
+
mailbox = Mournmail.account_config[:spam_mailbox]
|
382
|
+
if mailbox.nil?
|
383
|
+
raise EditorError, "spam_mailbox is not specified"
|
384
|
+
end
|
385
|
+
summary_refile(Net::IMAP.encode_utf7(mailbox))
|
386
|
+
end
|
387
|
+
|
376
388
|
define_local_command(:summary_prefetch,
|
377
389
|
doc: "Prefetch mails.") do
|
378
390
|
summary = Mournmail.current_summary
|
379
391
|
mailbox = Mournmail.current_mailbox
|
392
|
+
spam_mailbox = Mournmail.account_config[:spam_mailbox]
|
393
|
+
if mailbox == Net::IMAP.encode_utf7(spam_mailbox)
|
394
|
+
raise EditorError, "Can't prefetch spam"
|
395
|
+
end
|
380
396
|
target_uids = @buffer.to_s.scan(/^ *\d+/).map { |s|
|
381
397
|
s.to_i
|
382
398
|
}.select { |uid|
|
@@ -394,9 +410,7 @@ module Mournmail
|
|
394
410
|
s = i.attr["BODY[]"]
|
395
411
|
if s
|
396
412
|
cache_id = Mournmail.write_mail_cache(s)
|
397
|
-
|
398
|
-
Mournmail.index_mail(cache_id, Mail.new(s))
|
399
|
-
end
|
413
|
+
Mournmail.index_mail(cache_id, Mail.new(s))
|
400
414
|
summary[uid].cache_id = cache_id
|
401
415
|
end
|
402
416
|
end
|
@@ -450,7 +464,7 @@ module Mournmail
|
|
450
464
|
|
451
465
|
define_local_command(:summary_change_account,
|
452
466
|
doc: "Change the current account.") do
|
453
|
-
|account = read_account_name("Change account: ")|
|
467
|
+
|account = Mournmail.read_account_name("Change account: ")|
|
454
468
|
unless CONFIG[:mournmail_accounts].key?(account)
|
455
469
|
raise EditorError, "No such account: #{account}"
|
456
470
|
end
|
@@ -651,13 +665,6 @@ module Mournmail
|
|
651
665
|
message
|
652
666
|
end
|
653
667
|
|
654
|
-
def read_account_name(prompt, **opts)
|
655
|
-
f = ->(s) {
|
656
|
-
complete_for_minibuffer(s, CONFIG[:mournmail_accounts].keys)
|
657
|
-
}
|
658
|
-
read_from_minibuffer(prompt, completion_proc: f, **opts)
|
659
|
-
end
|
660
|
-
|
661
668
|
def delete_from_summary(summary, uids, msg)
|
662
669
|
summary.delete_item_if do |item|
|
663
670
|
uids.include?(item.uid)
|
data/lib/mournmail/utils.rb
CHANGED
@@ -225,15 +225,16 @@ module Mournmail
|
|
225
225
|
end
|
226
226
|
end
|
227
227
|
|
228
|
-
def self.google_access_token
|
229
|
-
auth_path = File.expand_path("cache/#{
|
228
|
+
def self.google_access_token(account = current_account)
|
229
|
+
auth_path = File.expand_path("cache/#{account}/google_auth.json",
|
230
230
|
CONFIG[:mournmail_directory])
|
231
231
|
FileUtils.mkdir_p(File.dirname(auth_path))
|
232
232
|
store = Google::APIClient::FileStore.new(auth_path)
|
233
233
|
storage = Google::APIClient::Storage.new(store)
|
234
234
|
storage.authorize
|
235
235
|
if storage.authorization.nil?
|
236
|
-
|
236
|
+
conf = CONFIG[:mournmail_accounts][account]
|
237
|
+
path = File.expand_path(conf[:client_secret_path])
|
237
238
|
client_secrets = Google::APIClient::ClientSecrets.load(path)
|
238
239
|
auth_client = client_secrets.to_authorization
|
239
240
|
auth_client.update!(
|
@@ -382,7 +383,8 @@ module Mournmail
|
|
382
383
|
dir = File.dirname(path)
|
383
384
|
base = File.basename(path)
|
384
385
|
begin
|
385
|
-
f = Tempfile.create(["#{base}-", ".tmp"], dir
|
386
|
+
f = Tempfile.create(["#{base}-", ".tmp"], dir,
|
387
|
+
external_encoding: "ASCII-8BIT", binmode: true)
|
386
388
|
begin
|
387
389
|
f.write(s)
|
388
390
|
ensure
|
@@ -554,4 +556,24 @@ module Mournmail
|
|
554
556
|
def self.parse_mail(s)
|
555
557
|
Mail.new(s.scrub("??"))
|
556
558
|
end
|
559
|
+
|
560
|
+
def self.read_account_name(prompt, **opts)
|
561
|
+
f = ->(s) {
|
562
|
+
complete_for_minibuffer(s, CONFIG[:mournmail_accounts].keys)
|
563
|
+
}
|
564
|
+
read_from_minibuffer(prompt, completion_proc: f, **opts)
|
565
|
+
end
|
566
|
+
|
567
|
+
def self.insert_signature
|
568
|
+
account = Buffer.current[:mournmail_delivery_account] ||
|
569
|
+
Mournmail.current_account
|
570
|
+
signature = CONFIG[:mournmail_accounts][account][:signature]
|
571
|
+
if signature
|
572
|
+
Buffer.current.save_excursion do
|
573
|
+
end_of_buffer
|
574
|
+
insert("\n")
|
575
|
+
insert(signature)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
557
579
|
end
|
data/lib/mournmail/version.rb
CHANGED
data/mournmail.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mournmail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: textbringer
|
@@ -126,14 +126,14 @@ dependencies:
|
|
126
126
|
name: rake
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '12.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '12.0'
|
139
139
|
description: A message user agent for Textbringer.
|