mournmail 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/push_gem.yml +48 -0
- data/README.md +61 -0
- data/lib/mournmail/config.rb +11 -0
- data/lib/mournmail/draft_mode.rb +7 -3
- data/lib/mournmail/message_mode.rb +6 -4
- data/lib/mournmail/message_rendering.rb +8 -2
- data/lib/mournmail/summary.rb +1 -0
- data/lib/mournmail/summary_mode.rb +10 -5
- data/lib/mournmail/utils.rb +23 -10
- data/lib/mournmail/version.rb +1 -1
- data/mournmail.gemspec +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebc2414b32ab7005cc39801155dcfe26eb1381026a7750b80c28ae84db63dae0
|
4
|
+
data.tar.gz: 464beaa7109d55c1730baad310ac064974cf902fd43281c936721587edd175fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13eebd0a106ac2494793d379ab682091e2dcc6aff0cf5fe6c5c7eebb712c7ba0ddeb0f14d9e16278bebae72ee8a18747024bc64f5c9d42772ea50ec5a649f666
|
7
|
+
data.tar.gz: 1d6a84e080f9612c41201c6fa59856fee33e2a9c0a20159185ceef8e36f8b575ecd98762d77ea19a3de00e760925262e10ad5ec7630920fef9e6edbf4b83b2fb
|
@@ -0,0 +1,48 @@
|
|
1
|
+
name: Publish gem to rubygems.org
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- 'v*'
|
7
|
+
|
8
|
+
permissions:
|
9
|
+
contents: read
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
push:
|
13
|
+
if: github.repository == 'shugo/mournmail'
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
|
16
|
+
environment:
|
17
|
+
name: rubygems.org
|
18
|
+
url: https://rubygems.org/gems/mournmail
|
19
|
+
|
20
|
+
permissions:
|
21
|
+
contents: write
|
22
|
+
id-token: write
|
23
|
+
|
24
|
+
steps:
|
25
|
+
# Set up
|
26
|
+
- name: Harden Runner
|
27
|
+
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
28
|
+
with:
|
29
|
+
egress-policy: audit
|
30
|
+
|
31
|
+
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
32
|
+
|
33
|
+
- name: Set up Ruby
|
34
|
+
uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0
|
35
|
+
with:
|
36
|
+
bundler-cache: true
|
37
|
+
ruby-version: ruby
|
38
|
+
|
39
|
+
# Release
|
40
|
+
- name: Publish to RubyGems
|
41
|
+
uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1
|
42
|
+
|
43
|
+
- name: Create GitHub release
|
44
|
+
run: |
|
45
|
+
tag_name="$(git describe --tags --abbrev=0)"
|
46
|
+
gh release create "${tag_name}" --verify-tag --draft --generate-notes
|
47
|
+
env:
|
48
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
data/README.md
CHANGED
@@ -70,6 +70,67 @@ Type `M-x mail` to send a mail.
|
|
70
70
|
|
71
71
|
Type `M-x mournmail` to visit INBOX.
|
72
72
|
|
73
|
+
## Key bindings
|
74
|
+
|
75
|
+
### Summary
|
76
|
+
|
77
|
+
|Key |Command |Description |
|
78
|
+
|---|---|---|
|
79
|
+
|s |mournmail_summary_sync |Sync summary. With C-u sync all mails |
|
80
|
+
|SPC |summary_read_command |Read a mail |
|
81
|
+
|C-h |summary_scroll_down_command |Scroll down the current message |
|
82
|
+
|n |summary_next_command |Display the next mail |
|
83
|
+
|w |summary_write_command |Write a new mail |
|
84
|
+
|a |summary_reply_command |Reply to the current message |
|
85
|
+
|A |summary_reply_command |Reply to the current message |
|
86
|
+
|f |summary_forward_command |Forward the current message |
|
87
|
+
|u |summary_toggle_seen_command |Toggle Seen |
|
88
|
+
|$ |summary_toggle_flagged_command |Toggle Flagged |
|
89
|
+
|d |summary_toggle_deleted_command |Toggle Deleted |
|
90
|
+
|x |summary_toggle_mark_command |Toggle mark |
|
91
|
+
|* a |summary_mark_all_command |Mark all mails |
|
92
|
+
|* n |summary_unmark_all_command |Unmark all mails |
|
93
|
+
|* r |summary_mark_read_command |Mark read mails |
|
94
|
+
|* u |summary_mark_unread_command |Mark unread mails |
|
95
|
+
|* s |summary_mark_flagged_command |Mark flagged mails |
|
96
|
+
|* t |summary_mark_unflagged_command |Mark unflagged mails |
|
97
|
+
|y |summary_archive_command |Archive mails. Archived mails will be deleted or refiled from the server, and only shown by summary_search_command |
|
98
|
+
|o |summary_refile_command |Refile marked mails |
|
99
|
+
|! |summary_refile_spam_command |Refile marked mails as spam |
|
100
|
+
|p |summary_prefetch_command |Prefetch mails |
|
101
|
+
|X |summary_expunge_command |Expunge deleted mails |
|
102
|
+
|v |summary_view_source_command |View source of a mail |
|
103
|
+
|M |summary_merge_partial_command |Merge marked message/partial |
|
104
|
+
|q |mournmail_quit |Quit Mournmail |
|
105
|
+
|k |previous_line |Move up |
|
106
|
+
|j |next_line |Move down |
|
107
|
+
|m |mournmail_visit_mailbox |Visit mailbox |
|
108
|
+
|S |mournmail_visit_spam_mailbox |Visit spam mailbox |
|
109
|
+
|/ |summary_search_command |Search mails |
|
110
|
+
|t |summary_show_thread_command |Show the thread of the current mail |
|
111
|
+
|@ |summary_change_account_command |Change the current account |
|
112
|
+
|
113
|
+
### Message
|
114
|
+
|
115
|
+
|Key |Command |Description |
|
116
|
+
|---|---|---|
|
117
|
+
|RET |message_open_link_or_part_command |Open link or MIME part |
|
118
|
+
|s |message_save_part_command |Save the MIME part |
|
119
|
+
|TAB |message_next_link_or_part_command| Go to the next link or MIME part |
|
120
|
+
|
121
|
+
### Draft
|
122
|
+
|
123
|
+
|Key |Command |Description |
|
124
|
+
|---|---|---|
|
125
|
+
|C-c C-c |draft_send_command |Send a mail |
|
126
|
+
|C-c C-k |draft_kill_command |Kill the draft buffer |
|
127
|
+
|C-c C-x TAB |draft_attach_file_command |Attach a file |
|
128
|
+
|C-c C-x v |draft_pgp_sign_command |PGP sign |
|
129
|
+
|C-c C-x e |draft_pgp_encrypt_command |PGP encrypt |
|
130
|
+
|C-c TAB |insert_signature_command |Insert signature |
|
131
|
+
|C-c @ |draft_change_account_command |Change account |
|
132
|
+
|TAB |draft_complete_or_insert_tab_command |Complete a mail address or insert a tab |
|
133
|
+
|
73
134
|
## Development
|
74
135
|
|
75
136
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/mournmail/config.rb
CHANGED
@@ -54,4 +54,15 @@ module Textbringer
|
|
54
54
|
"ppt",
|
55
55
|
"zip"
|
56
56
|
]
|
57
|
+
CONFIG[:forgotten_attachment_re] =
|
58
|
+
Regexp.new(
|
59
|
+
"^(?!>).*" +
|
60
|
+
Regexp.union(
|
61
|
+
/I('ve| have) (attached|included)/,
|
62
|
+
/See the (attached|attachment)/,
|
63
|
+
/Attached file/,
|
64
|
+
/添付(する|した|します|しました|いたします|いたしました)/,
|
65
|
+
/ファイルを参照/
|
66
|
+
).to_s
|
67
|
+
)
|
57
68
|
end
|
data/lib/mournmail/draft_mode.rb
CHANGED
@@ -21,11 +21,15 @@ module Mournmail
|
|
21
21
|
|
22
22
|
define_local_command(:draft_send,
|
23
23
|
doc: "Send a mail and exit from mail buffer.") do
|
24
|
-
|
25
|
-
|
24
|
+
s = @buffer.to_s
|
25
|
+
if s.match?(CONFIG[:forgotten_attachment_re]) &&
|
26
|
+
!s.match?(/^Attached-File:/)
|
27
|
+
msg = "It seems like you forgot to attach a file. Send anyway?"
|
28
|
+
return unless yes_or_no?(msg)
|
29
|
+
else
|
30
|
+
return unless y_or_n?("Send this mail?")
|
26
31
|
end
|
27
32
|
run_hooks(:mournmail_pre_send_hook)
|
28
|
-
s = @buffer.to_s
|
29
33
|
charset = CONFIG[:mournmail_charset]
|
30
34
|
begin
|
31
35
|
s.encode(charset)
|
@@ -11,10 +11,12 @@ module Mournmail
|
|
11
11
|
MESSAGE_MODE_MAP.define_key("\t", :message_next_link_or_part_command)
|
12
12
|
|
13
13
|
# See http://nihongo.jp/support/mail_guide/dev_guide.txt
|
14
|
-
|
15
|
-
|
14
|
+
URI_REGEXP = Regexp.union(URI.regexp("http"),
|
15
|
+
URI.regexp("https"),
|
16
|
+
URI.regexp("ftp"),
|
17
|
+
URI.regexp("mailto"))
|
16
18
|
MIME_REGEXP = /^\[(([0-9.]+) [A-Za-z._\-]+\/[A-Za-z._\-]+.*|PGP\/MIME .*)\]$/
|
17
|
-
URI_OR_MIME_REGEXP =
|
19
|
+
URI_OR_MIME_REGEXP = Regexp.union(URI_REGEXP, MIME_REGEXP)
|
18
20
|
|
19
21
|
define_syntax :field_name, /^[A-Za-z\-]+: /
|
20
22
|
define_syntax :quotation, /^>.*/
|
@@ -128,7 +130,7 @@ module Mournmail
|
|
128
130
|
if part.multipart?
|
129
131
|
raise EditorError, "Can't open a multipart entity."
|
130
132
|
end
|
131
|
-
ext = part_file_name(part).slice(/\.([^.]+)\z/, 1)
|
133
|
+
ext = part_file_name(part).slice(/\.([^.]+)\z/, 1).downcase
|
132
134
|
if part.main_type != "text" || part.sub_type == "html"
|
133
135
|
if ext.nil?
|
134
136
|
raise EditorError, "The extension of the filename is not specified"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "mail"
|
2
|
-
require "
|
2
|
+
require "nokogiri"
|
3
3
|
|
4
4
|
module Mournmail
|
5
5
|
module MessageRendering
|
@@ -34,7 +34,9 @@ module Mournmail
|
|
34
34
|
elsif main_type.nil? || main_type == "text"
|
35
35
|
s = Mournmail.to_utf8(body.decoded, charset)
|
36
36
|
if sub_type == "html"
|
37
|
-
|
37
|
+
doc = Nokogiri::HTML(s)
|
38
|
+
doc.css("script, style, link").each { |node| node.remove }
|
39
|
+
"[0 text/html]\n" + doc.css("body").text.squeeze(" \n")
|
38
40
|
else
|
39
41
|
s
|
40
42
|
end
|
@@ -115,6 +117,10 @@ module Mournmail
|
|
115
117
|
type = Mail::Encodings.decode_encode(self["content-type"].to_s,
|
116
118
|
:decode) rescue
|
117
119
|
"broken/type; error=\"#{$!} (#{$!.class})\""
|
120
|
+
filename = self["content-disposition"]&.filename
|
121
|
+
if filename && !self["content-type"]&.filename
|
122
|
+
type += "; filename=#{filename}"
|
123
|
+
end
|
118
124
|
"[#{index} #{type}]\n" +
|
119
125
|
render_content(indices, no_content)
|
120
126
|
end
|
data/lib/mournmail/summary.rb
CHANGED
@@ -478,6 +478,11 @@ module Mournmail
|
|
478
478
|
|
479
479
|
private
|
480
480
|
|
481
|
+
def get_summary_item(uid)
|
482
|
+
summary = Mournmail.current_summary
|
483
|
+
summary && summary[uid]
|
484
|
+
end
|
485
|
+
|
481
486
|
def selected_uid
|
482
487
|
uid = @buffer.save_excursion {
|
483
488
|
@buffer.beginning_of_line
|
@@ -538,7 +543,7 @@ module Mournmail
|
|
538
543
|
end
|
539
544
|
|
540
545
|
def mark_as_seen(uid, update_server)
|
541
|
-
summary_item =
|
546
|
+
summary_item = get_summary_item(uid)
|
542
547
|
if summary_item && !summary_item.flags.include?(:Seen)
|
543
548
|
summary_item.set_flag(:Seen, update_server: update_server)
|
544
549
|
Mournmail.current_summary.save
|
@@ -547,7 +552,7 @@ module Mournmail
|
|
547
552
|
end
|
548
553
|
|
549
554
|
def toggle_flag(uid, flag)
|
550
|
-
summary_item =
|
555
|
+
summary_item = get_summary_item(uid)
|
551
556
|
if summary_item
|
552
557
|
Mournmail.background do
|
553
558
|
summary_item.toggle_flag(flag)
|
@@ -596,8 +601,8 @@ module Mournmail
|
|
596
601
|
summary_text = messages.map { |m|
|
597
602
|
format("%s [ %s ] %s\n",
|
598
603
|
m.date.strftime("%m/%d %H:%M"),
|
599
|
-
ljust(m.from.to_s, 16),
|
600
|
-
ljust(m.subject.to_s, 45))
|
604
|
+
ljust(m.from.to_s.gsub(/\n/, ""), 16),
|
605
|
+
ljust(m.subject.to_s.gsub(/\n/, ""), 45))
|
601
606
|
}.join
|
602
607
|
buffer = Buffer.find_or_new(buffer_name, undo_limit: 0,
|
603
608
|
read_only: true)
|
@@ -657,7 +662,7 @@ module Mournmail
|
|
657
662
|
|
658
663
|
def current_message
|
659
664
|
uid = selected_uid
|
660
|
-
item =
|
665
|
+
item = get_summary_item(uid)
|
661
666
|
message = Groonga["Messages"][item.cache_id]
|
662
667
|
if message.nil?
|
663
668
|
raise EditorError, "No message found"
|
data/lib/mournmail/utils.rb
CHANGED
@@ -13,15 +13,28 @@ require 'google/api_client/auth/storages/file_store'
|
|
13
13
|
require 'launchy'
|
14
14
|
require "socket"
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
16
|
+
if defined?(Net::SMTP::Authenticator)
|
17
|
+
class Net::SMTP
|
18
|
+
class AuthXOAuth2 < Net::SMTP::Authenticator
|
19
|
+
auth_type :xoauth2
|
20
|
+
|
21
|
+
def auth(user, secret)
|
22
|
+
s = Net::IMAP::XOauth2Authenticator.new(user, secret).process("")
|
23
|
+
finish('AUTH XOAUTH2 ' + base64_encode(s))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
else
|
28
|
+
class Net::SMTP
|
29
|
+
def auth_xoauth2(user, secret)
|
30
|
+
check_auth_args user, secret
|
31
|
+
res = critical {
|
32
|
+
s = Net::IMAP::XOauth2Authenticator.new(user, secret).process("")
|
33
|
+
get_response('AUTH XOAUTH2 ' + base64_encode(s))
|
34
|
+
}
|
35
|
+
check_auth_response res
|
36
|
+
res
|
37
|
+
end
|
25
38
|
end
|
26
39
|
end
|
27
40
|
|
@@ -184,7 +197,7 @@ module Mournmail
|
|
184
197
|
end
|
185
198
|
Timeout.timeout(CONFIG[:mournmail_imap_connect_timeout]) do
|
186
199
|
@imap = Net::IMAP.new(conf[:imap_host],
|
187
|
-
conf[:imap_options])
|
200
|
+
conf[:imap_options].except(:auth_type, :user_name))
|
188
201
|
@imap.authenticate(auth_type, conf[:imap_options][:user_name],
|
189
202
|
password)
|
190
203
|
@mailboxes = @imap.list("", "*").map { |mbox|
|
data/lib/mournmail/version.rb
CHANGED
data/mournmail.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_runtime_dependency "rroonga"
|
30
30
|
spec.add_runtime_dependency "google-apis-core"
|
31
31
|
spec.add_runtime_dependency "launchy"
|
32
|
-
spec.add_runtime_dependency "
|
32
|
+
spec.add_runtime_dependency "nokogiri"
|
33
33
|
|
34
34
|
spec.add_development_dependency "bundler"
|
35
35
|
spec.add_development_dependency "rake", ">= 12.0"
|
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: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: textbringer
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: nokogiri
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -172,6 +172,7 @@ executables:
|
|
172
172
|
extensions: []
|
173
173
|
extra_rdoc_files: []
|
174
174
|
files:
|
175
|
+
- ".github/workflows/push_gem.yml"
|
175
176
|
- ".gitignore"
|
176
177
|
- Gemfile
|
177
178
|
- LICENSE.txt
|
@@ -199,7 +200,7 @@ homepage: https://github.com/shugo/mournmail
|
|
199
200
|
licenses:
|
200
201
|
- MIT
|
201
202
|
metadata: {}
|
202
|
-
post_install_message:
|
203
|
+
post_install_message:
|
203
204
|
rdoc_options: []
|
204
205
|
require_paths:
|
205
206
|
- lib
|
@@ -214,8 +215,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
215
|
- !ruby/object:Gem::Version
|
215
216
|
version: '0'
|
216
217
|
requirements: []
|
217
|
-
rubygems_version: 3.
|
218
|
-
signing_key:
|
218
|
+
rubygems_version: 3.5.9
|
219
|
+
signing_key:
|
219
220
|
specification_version: 4
|
220
221
|
summary: A message user agent for Textbringer.
|
221
222
|
test_files: []
|