glima 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Dockerfile +49 -0
- data/README.org +35 -0
- data/Rakefile +18 -0
- data/emacs/axman.el +156 -0
- data/exe/glima +37 -13
- data/exe/glima-docker.sh +6 -0
- data/glima.gemspec +1 -1
- data/lib/glima/gmail_client.rb +4 -1
- data/lib/glima/imap.rb +81 -39
- data/lib/glima/version.rb +1 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0260fea2c5f1589c7ea8cf305e1f77c724be667a
|
4
|
+
data.tar.gz: f6cc75417943bb19e01050dace7ac9af881962f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7249a0885cbcf95760e7204adbbf90c5f7a4b99dcd4e512110c358aa7cef23929b90e88d6366ac11339716e870741d5b489473bb499cc3fb0998cfe03daed75b
|
7
|
+
data.tar.gz: f745b82e4aa88c6e7493a9e47573cf03b035cd760ae7d6f22942e973c00593834a1ef9e75e5223f0667a10c64511310c62995decb72bd02df0af8b0aca78f88a
|
data/.gitignore
CHANGED
@@ -41,7 +41,7 @@ build/
|
|
41
41
|
# for a library or gem, you might want to ignore these files since the code is
|
42
42
|
# intended to run in multiple environments; otherwise, check them in:
|
43
43
|
# Gemfile.lock
|
44
|
-
|
44
|
+
.ruby-version
|
45
45
|
# .ruby-gemset
|
46
46
|
|
47
47
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
data/Dockerfile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# * Dockerfile for glima
|
2
|
+
# https://github.com/yoshinari-nomura/glima
|
3
|
+
#
|
4
|
+
# * How to buld
|
5
|
+
# ** from command line
|
6
|
+
# bundle exec rake build
|
7
|
+
# docker build --build-arg GLIMA_VERSION=$(bundle exec glima version) -t nom4476/glima .
|
8
|
+
#
|
9
|
+
# ** from Rakefile
|
10
|
+
# bundle exec rake docker:build
|
11
|
+
#
|
12
|
+
# * How to run
|
13
|
+
# mkdir -p ~/.config/glima ~/.cache/glima
|
14
|
+
#
|
15
|
+
# docker run -it --rm \
|
16
|
+
# -v $HOME/.config/glima:/root/.config/glima \
|
17
|
+
# -v $HOME/.cache/glima:/root/.cache/glima \
|
18
|
+
# nom4476/glima init
|
19
|
+
#
|
20
|
+
# docker run -it --rm \
|
21
|
+
# -v $HOME/.config/glima:/root/.config/glima \
|
22
|
+
# -v $HOME/.cache/glima:/root/.cache/glima \
|
23
|
+
# nom4476/glima init
|
24
|
+
#
|
25
|
+
# * For debug
|
26
|
+
# docker run -it --rm -v $HOME/.config/glima:/root/.config/glima --entrypoint "sh" nom4476/glima
|
27
|
+
#
|
28
|
+
#
|
29
|
+
FROM alpine:3.6
|
30
|
+
|
31
|
+
MAINTAINER nom@quickhack.net
|
32
|
+
|
33
|
+
RUN mkdir -p $HOME/.config/glima
|
34
|
+
RUN mkdir -p $HOME/.cache/glima
|
35
|
+
|
36
|
+
RUN echo 'gem: --no-ri --no-rdoc' > $HOME/.gemrc
|
37
|
+
|
38
|
+
RUN apk --update add ruby ruby-json && rm -rf /var/cache/apk/*
|
39
|
+
|
40
|
+
ARG GLIMA_VERSION
|
41
|
+
ENV GLIMA_VERSION $GLIMA_VERSION
|
42
|
+
ENV RUBYOPT "-W0"
|
43
|
+
RUN test -n "$GLIMA_VERSION"
|
44
|
+
|
45
|
+
COPY pkg/glima-${GLIMA_VERSION}.gem /tmp
|
46
|
+
RUN gem install /tmp/glima-$GLIMA_VERSION.gem
|
47
|
+
|
48
|
+
ENTRYPOINT [ "glima" ]
|
49
|
+
CMD [ "help" ]
|
data/README.org
CHANGED
@@ -45,6 +45,15 @@
|
|
45
45
|
$ export PATH=/path/to/install/glima/exe:$PATH
|
46
46
|
#+END_SRC
|
47
47
|
|
48
|
+
** Install from Docker image
|
49
|
+
#+BEGIN_SRC sh
|
50
|
+
$ docker pull nom4476/glima
|
51
|
+
$ curl https://raw.githubusercontent.com/yoshinari-nomura/glima/master/exe/glima-docker.sh > glima
|
52
|
+
$ chmod +x glima
|
53
|
+
$ mkdir -p ~/.config/glima ~/.cache/glima
|
54
|
+
$ ./glima help
|
55
|
+
#+END_SRC
|
56
|
+
|
48
57
|
* Setup
|
49
58
|
1) Get OAuth CLIENT_ID/CLIENT_SECRET
|
50
59
|
|
@@ -89,3 +98,29 @@
|
|
89
98
|
2 09/27 14:00 15ec1b716bbb6bdc Yeah...
|
90
99
|
:
|
91
100
|
#+END_SRC
|
101
|
+
|
102
|
+
* Invoke decrypter from emacs mailer (Mew)
|
103
|
+
Minimum setup: add belows in your .emacs:
|
104
|
+
#+BEGIN_SRC emacs-lisp
|
105
|
+
(setq load-path
|
106
|
+
(cons "~/path/to/this/file load-path"))
|
107
|
+
(autoload 'axman-mew-decrypt-current-message-gmail "axman")
|
108
|
+
(autoload 'axman-mew-decrypt-current-message-local "axman")
|
109
|
+
#+END_SRC
|
110
|
+
|
111
|
+
How to use:
|
112
|
+
1) In mew-summary buffer (ie. %inbox),
|
113
|
+
point at an email with encrypted-ZIP attachment.
|
114
|
+
|
115
|
+
2) M-x axman-mew-decrypt-current-message-local
|
116
|
+
|
117
|
+
3) It will find the password from the current folder (%inbox)
|
118
|
+
inspecting in passwordish-emails.
|
119
|
+
|
120
|
+
axman-mew-decrypt-current-message-gmail is another version that works
|
121
|
+
with Gmail server. It would be useful if your email server is
|
122
|
+
Gmail with IMAP enabled.
|
123
|
+
|
124
|
+
* Japanese blog entry about glima xzip.
|
125
|
+
+ [[http://quickhack.net/nom/blog/2017-11-06-password-is-in-another-mail.html][「パスワードは別途お送りします」をなんとかしたい]]
|
126
|
+
+ [[http://quickhack.net/nom/blog/2017-11-29-mail-decrypter-for-mew.html][「パスワードは別途お送りします」を Mew でなんとかしたい]]
|
data/Rakefile
CHANGED
@@ -3,4 +3,22 @@ require "rspec/core/rake_task"
|
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
+
|
7
|
+
|
8
|
+
namespace :docker do
|
9
|
+
tag = "nom4476/glima"
|
10
|
+
|
11
|
+
desc "Build Docker image from Dockerfile"
|
12
|
+
task :build do
|
13
|
+
version = Glima::VERSION
|
14
|
+
system "docker build --build-arg GLIMA_VERSION=#{version} -t #{tag} ."
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Push current Docker image to Docker Hub"
|
18
|
+
task :push do
|
19
|
+
system "docker push #{tag}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
task "docker:build" => "^build"
|
6
24
|
task :default => :spec
|
data/emacs/axman.el
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
;;; axman.el --- Automatic decrypter for attachments in emails.
|
2
|
+
|
3
|
+
;; Description: Automatic decrypter for attachments in emails.
|
4
|
+
;; Author: Yoshinari Nomura <nom@quickhack.net>
|
5
|
+
;; Created: 2016-08-24
|
6
|
+
;; Version: 0.1.0
|
7
|
+
;; Keywords: Mail Decrypter Zip
|
8
|
+
;; URL: https://github.com/yoshinari-nomura/axman
|
9
|
+
;; Package-Requires:
|
10
|
+
|
11
|
+
;;;
|
12
|
+
;;; Commentary:
|
13
|
+
;;;
|
14
|
+
|
15
|
+
;; Minimum setup:
|
16
|
+
;; 1) setup axzip ruby script in glima.
|
17
|
+
;; https://github.com/yoshinari-nomura/glima
|
18
|
+
;;
|
19
|
+
;; 2) add belows in your .emacs:
|
20
|
+
;; (setq load-path
|
21
|
+
;; (cons "~/path/to/this/file load-path"))
|
22
|
+
;; (autoload 'axman-mew-decrypt-current-message-gmail "axman")
|
23
|
+
;; (autoload 'axman-mew-decrypt-current-message-local "axman")
|
24
|
+
;;
|
25
|
+
;; How to use:
|
26
|
+
;; 1) In mew-summary buffer (ie. %inbox),
|
27
|
+
;; point at an email with encrypted-ZIP attachment.
|
28
|
+
;;
|
29
|
+
;; 2) M-x axman-mew-decrypt-current-message-local
|
30
|
+
;;
|
31
|
+
;; 3) It will find the password from the current folder (%inbox)
|
32
|
+
;; inspecting in passwordish-emails.
|
33
|
+
;;
|
34
|
+
;; axman-mew-decrypt-current-message-gmail is another version that works
|
35
|
+
;; with Gmail server. It would be useful if your email server is
|
36
|
+
;; Gmail with IMAP enabled.
|
37
|
+
;;
|
38
|
+
|
39
|
+
;;; Code:
|
40
|
+
|
41
|
+
(defcustom axman-attachment-store-directory "~/Downloads"
|
42
|
+
"Where to store unlocked zip file."
|
43
|
+
:group 'axman
|
44
|
+
:type 'directory)
|
45
|
+
|
46
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
47
|
+
;; Helper function works with Mew.
|
48
|
+
|
49
|
+
(defvar mew-regex-sumsyn-long)
|
50
|
+
(defvar mew-regex-sumsyn-short)
|
51
|
+
|
52
|
+
(declare-function mew-header-get-value "mew")
|
53
|
+
(declare-function mew-sumsyn-match "mew")
|
54
|
+
(declare-function mew-sumsyn-folder-name "mew")
|
55
|
+
(declare-function mew-sumsyn-message-number "mew")
|
56
|
+
(declare-function mew-msg-get-filename "mew")
|
57
|
+
(declare-function mew-expand-msg "mew")
|
58
|
+
(declare-function mew-expand-folder "mew")
|
59
|
+
(declare-function mew-summary-goto-message "mew")
|
60
|
+
(declare-function mew-summary-set-message-buffer "mew")
|
61
|
+
|
62
|
+
(defmacro mewx-with-current-message-buffer (&rest body)
|
63
|
+
"Eval BODY after switch from summary to message."
|
64
|
+
`(save-excursion
|
65
|
+
(mew-summary-goto-message)
|
66
|
+
(mew-sumsyn-match mew-regex-sumsyn-short)
|
67
|
+
(mew-summary-set-message-buffer
|
68
|
+
(mew-sumsyn-folder-name)
|
69
|
+
(mew-sumsyn-message-number))
|
70
|
+
,@body))
|
71
|
+
|
72
|
+
(defun mewx-current-info (property)
|
73
|
+
"Get PROPERTY of pointed messsage."
|
74
|
+
(when (mew-sumsyn-match mew-regex-sumsyn-long)
|
75
|
+
(let* ((folder (mew-sumsyn-folder-name))
|
76
|
+
(number (mew-sumsyn-message-number))
|
77
|
+
(path (mew-msg-get-filename (mew-expand-msg folder number)))
|
78
|
+
(directory (mew-expand-folder folder)))
|
79
|
+
(cdr (assoc
|
80
|
+
property
|
81
|
+
`((folder . ,folder)
|
82
|
+
(number . ,number)
|
83
|
+
(path . ,path)
|
84
|
+
(directory . ,directory)))))))
|
85
|
+
|
86
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
87
|
+
;; Decrypt attachments
|
88
|
+
|
89
|
+
(defmacro axman-with-decrypter-buffer (buffer message &rest body)
|
90
|
+
"Wrap decrypter in BUFFER with MESSAGE.
|
91
|
+
BODY should returns process object of ``start-process''."
|
92
|
+
`(let ((,buffer (get-buffer-create " *Axman*")))
|
93
|
+
(save-selected-window
|
94
|
+
(pop-to-buffer ,buffer)
|
95
|
+
(delete-region (point-min) (point-max))
|
96
|
+
(insert "Decrypting " (or ,message "") "...\n")
|
97
|
+
(recenter -1))
|
98
|
+
(set-process-sentinel
|
99
|
+
,@body
|
100
|
+
(lambda (proc event)
|
101
|
+
(let ((,buffer (process-buffer proc)))
|
102
|
+
(with-current-buffer ,buffer
|
103
|
+
(if (save-excursion
|
104
|
+
(re-search-backward "^Wrote to \\(.*\\)\\." nil t))
|
105
|
+
(start-process "open" ,buffer "open" "-R" (match-string 1)))))))))
|
106
|
+
|
107
|
+
(put 'axman-with-decrypter-buffer 'lisp-indent-function 2)
|
108
|
+
|
109
|
+
(defun axman-start-gmail-decrypter (target-mail extract-directory)
|
110
|
+
"Invoke Gmail decrypter process. Return process object.
|
111
|
+
It decrypts zip-attachments in TARGET-MAIL and stores the decrypted zip-files
|
112
|
+
into EXTRACT-DIRECTORY. TARGET-MAIL should be in the form of Gmail message-id
|
113
|
+
like: 15c5723f8d3dba57."
|
114
|
+
(axman-with-decrypter-buffer process-buffer target-mail
|
115
|
+
(start-process "glima" process-buffer
|
116
|
+
"glima" "dezip" target-mail extract-directory)))
|
117
|
+
|
118
|
+
(defun axman-start-mh-decrypter (target-mail password-source extract-directory)
|
119
|
+
"Invoke MH decrypter process. Return process object.
|
120
|
+
It decrypts zip-attachments in TARGET-MAIL using PASSWORD-SOURCE,
|
121
|
+
and stores the decrypted zip-files into EXTRACT-DIRECTORY.
|
122
|
+
TARGET-MAIL a filename of MHC-style mail.
|
123
|
+
MH decrypter takes PASSWORD-SOURCE as a MH-style folder directory
|
124
|
+
from where piking password mails."
|
125
|
+
(axman-with-decrypter-buffer process-buffer target-mail
|
126
|
+
(start-process "axezip" process-buffer
|
127
|
+
"axezip" target-mail password-source extract-directory)))
|
128
|
+
|
129
|
+
;;;###autoload
|
130
|
+
(defun axman-mew-decrypt-current-message-gmail ()
|
131
|
+
"Decrypt attachment from Gmail."
|
132
|
+
(interactive)
|
133
|
+
(let ((message-id
|
134
|
+
(mewx-with-current-message-buffer
|
135
|
+
(mew-header-get-value "X-GM-MSGID:"))))
|
136
|
+
(if message-id
|
137
|
+
(axman-start-gmail-decrypter
|
138
|
+
message-id
|
139
|
+
axman-attachment-store-directory)
|
140
|
+
(message "No message found."))))
|
141
|
+
|
142
|
+
;;;###autoload
|
143
|
+
(defun axman-mew-decrypt-current-message-local ()
|
144
|
+
"Decrypt current zip attachments."
|
145
|
+
(interactive)
|
146
|
+
(let ((path (mewx-current-info 'path))
|
147
|
+
(password-source (mewx-current-info 'directory)))
|
148
|
+
(if path
|
149
|
+
(axman-start-mh-decrypter
|
150
|
+
path password-source
|
151
|
+
axman-attachment-store-directory)
|
152
|
+
(message "No message found."))))
|
153
|
+
|
154
|
+
(provide 'axman)
|
155
|
+
|
156
|
+
;;; axman.el ends here
|
data/exe/glima
CHANGED
@@ -30,6 +30,18 @@ require "logger"
|
|
30
30
|
|
31
31
|
Encoding.default_external="UTF-8"
|
32
32
|
|
33
|
+
# For debug
|
34
|
+
Signal.trap('USR2') do
|
35
|
+
pid = Process.pid
|
36
|
+
STDERR.puts "[#{pid}] Received USR2 at #{Time.now}. Dumping threads:"
|
37
|
+
Thread.list.each do |t|
|
38
|
+
trace = t.backtrace.join("\n[#{pid}] ")
|
39
|
+
STDERR.puts "[#{pid}] #{trace}"
|
40
|
+
STDERR.puts "[#{pid}] ---"
|
41
|
+
end
|
42
|
+
STDERR.puts "[#{pid}] -------------------"
|
43
|
+
end
|
44
|
+
|
33
45
|
class GlimaCLI < Clian::Cli
|
34
46
|
package_name 'GLIMA'
|
35
47
|
remove_command :configuration
|
@@ -238,9 +250,9 @@ class GlimaCLI < Clian::Cli
|
|
238
250
|
|
239
251
|
error_count = 0
|
240
252
|
begin
|
253
|
+
timestamp = Time.now
|
241
254
|
ql = parse_label_names(queue_label).first
|
242
255
|
ml = parse_label_names(mark_label).first
|
243
|
-
timestamp = Time.now
|
244
256
|
Glima::Command::Watch.new(ql, ml, default_passwords)
|
245
257
|
rescue => err
|
246
258
|
@logger.info err
|
@@ -317,28 +329,31 @@ class GlimaCLI < Clian::Cli
|
|
317
329
|
$GLIMA_DEBUG_FOR_DEVELOPER = true if ENV["GLIMA_DEBUG_FOR_DEVELOPER"]
|
318
330
|
end
|
319
331
|
|
320
|
-
@logger
|
321
|
-
|
322
|
-
|
332
|
+
unless @logger
|
333
|
+
@logger = ::Logger.new($stderr)
|
334
|
+
@logger.formatter = proc {|severity, datetime, progname, msg| "#{datetime} #{msg}\n"}
|
335
|
+
Glima::Command.logger = @logger
|
336
|
+
end
|
323
337
|
|
324
338
|
@config_path = options[:config] || DEFAULT_CONFIG_PATH
|
325
339
|
|
326
340
|
return true if ["init", "help"].member?(command.name)
|
327
341
|
|
328
|
-
@config
|
329
|
-
@datastore
|
342
|
+
@config ||= Glima::Config.create_from_file(@config_path)
|
343
|
+
@datastore ||= Glima::DataStore.new(File.expand_path(config.general.cache_directory))
|
330
344
|
@user = options[:user] || config.general.default_user
|
331
|
-
@context
|
332
|
-
@client
|
333
|
-
|
334
|
-
|
335
|
-
|
345
|
+
@context ||= Glima::Context.new(File.expand_path(DEFAULT_CONFIG_HOME))
|
346
|
+
@client ||= Glima::GmailClient.new(config.general.client_id,
|
347
|
+
config.general.client_secret,
|
348
|
+
File.expand_path("token_store.yml", File.dirname(@config_path)),
|
349
|
+
@user, @datastore, @logger)
|
336
350
|
|
337
|
-
Glima::Command.client
|
351
|
+
Glima::Command.client ||= @client
|
338
352
|
|
339
353
|
unless ["auth"].member?(command.name)
|
340
354
|
begin
|
341
|
-
@client.auth
|
355
|
+
@client.auth unless @client_already_authorized
|
356
|
+
@client_already_authorized = true
|
342
357
|
rescue Glima::GmailClient::AuthorizationError
|
343
358
|
Thor.new.say "ERROR: access token expired? try: glima auth --user=#{@user}", :red
|
344
359
|
exit(1)
|
@@ -346,6 +361,15 @@ class GlimaCLI < Clian::Cli
|
|
346
361
|
end
|
347
362
|
end
|
348
363
|
end
|
364
|
+
|
365
|
+
def custom_completion_for_banner(banner)
|
366
|
+
case banner
|
367
|
+
when /^USER/
|
368
|
+
"(#{config.general.default_user})"
|
369
|
+
else
|
370
|
+
nil
|
371
|
+
end
|
372
|
+
end
|
349
373
|
end
|
350
374
|
|
351
375
|
GlimaCLI.start(ARGV)
|
data/exe/glima-docker.sh
ADDED
data/glima.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.required_ruby_version = ">= 2.3.0"
|
28
28
|
|
29
29
|
spec.add_runtime_dependency "thor", ">= 0.19.1"
|
30
|
-
spec.add_runtime_dependency "clian", ">= 0.
|
30
|
+
spec.add_runtime_dependency "clian", ">= 0.4.0"
|
31
31
|
spec.add_runtime_dependency "mail"
|
32
32
|
spec.add_runtime_dependency "rubyzip"
|
33
33
|
|
data/lib/glima/gmail_client.rb
CHANGED
@@ -265,9 +265,12 @@ module Glima
|
|
265
265
|
|
266
266
|
begin
|
267
267
|
@imap.wait(label&.name, timeout_sec)
|
268
|
-
|
268
|
+
|
269
|
+
rescue => err
|
269
270
|
@imap = nil
|
270
271
|
@logger.info "[#{self.class}#wait] imap connection error. abandon current imap connection."
|
272
|
+
@logger.info err
|
273
|
+
@logger.info err.backtrace
|
271
274
|
end
|
272
275
|
@logger.info "[#{self.class}#wait] Exit"
|
273
276
|
end
|
data/lib/glima/imap.rb
CHANGED
@@ -12,6 +12,42 @@ module Glima
|
|
12
12
|
usessl = false, certs = nil, verify = true)
|
13
13
|
super
|
14
14
|
@parser = Glima::IMAP::ResponseParser.new
|
15
|
+
|
16
|
+
set_keepalive(@sock, 30) # set *TCP* Keepalive
|
17
|
+
end
|
18
|
+
|
19
|
+
# https://www.winehq.org/pipermail/wine-devel/2015-July/108583.html
|
20
|
+
# TCP_KEEPALIVE on Darwin corresponds to Linux TCP_KEEPIDLE, not TCP_KEEPINTVL.
|
21
|
+
#
|
22
|
+
# * Darwin (macOS)
|
23
|
+
# /usr/include/netinet/tcp.h:
|
24
|
+
# : #define TCP_KEEPALIVE 0x10 /* idle time used when SO_KEEPALIVE is enabled */
|
25
|
+
# : TCP_KEEPALIVE = 0x10
|
26
|
+
# : TCP_KEEPCNT = 0x102
|
27
|
+
# : TCP_KEEPINTVL = 0x101
|
28
|
+
# * Linux
|
29
|
+
# : TCP_KEEPIDLE
|
30
|
+
# : TCP_KEEPCNT
|
31
|
+
# : TCP_KEEPINTVL
|
32
|
+
#
|
33
|
+
# Configurable TCP keepalives by normelton: PR #262 redis/redis-rb
|
34
|
+
# https://github.com/redis/redis-rb/pull/262
|
35
|
+
#
|
36
|
+
def set_keepalive(sock, sec)
|
37
|
+
xTCP_KEEPIDLE = if RUBY_PLATFORM =~ /darwin/ then 0x10 else :TCP_KEEPIDLE end
|
38
|
+
|
39
|
+
idle, interval, probes = if sec >= 60
|
40
|
+
[sec - 20, 10, 2]
|
41
|
+
elsif sec >= 30
|
42
|
+
[sec - 10, 5, 2]
|
43
|
+
elsif sec >= 5
|
44
|
+
[sec - 2, 2, 1]
|
45
|
+
end
|
46
|
+
|
47
|
+
sock.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)
|
48
|
+
sock.setsockopt(:IPPROTO_TCP, xTCP_KEEPIDLE, idle)
|
49
|
+
sock.setsockopt(:IPPROTO_TCP, :TCP_KEEPINTVL, interval)
|
50
|
+
sock.setsockopt(:IPPROTO_TCP, :TCP_KEEPCNT, probes)
|
15
51
|
end
|
16
52
|
|
17
53
|
class Xoauth2Authenticator
|
@@ -89,63 +125,69 @@ module Glima
|
|
89
125
|
|
90
126
|
def_delegators :@imap,
|
91
127
|
:fetch,
|
92
|
-
:select,
|
93
128
|
:disconnected?
|
94
129
|
|
95
130
|
def initialize(imap_server, authorization, logger)
|
96
131
|
@imap_server, @authorization, @logger = imap_server, authorization, logger
|
132
|
+
@current_folder = nil
|
97
133
|
connect(imap_server, authorization)
|
98
134
|
end
|
99
135
|
|
100
136
|
def wait(folder = nil, timeout_sec = 60)
|
101
|
-
|
102
|
-
|
103
|
-
if folder
|
104
|
-
folder = Net::IMAP.encode_utf7(folder)
|
105
|
-
else
|
106
|
-
# select "[Gmail]/All Mail" or localized one like "[Gmail]/すべてのメール"
|
107
|
-
folder = @imap.list("", "[Gmail]/*").find {|f| f.attr.include?(:All)}.name
|
108
|
-
end
|
137
|
+
select(folder || :all) unless @current_folder
|
109
138
|
|
110
|
-
|
139
|
+
logger.info "[#{self.class}#wait] Enter"
|
111
140
|
begin
|
112
|
-
|
113
|
-
|
114
|
-
sleep timeout
|
115
|
-
ensure
|
116
|
-
imap.idle_done
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
@imap.idle do |resp|
|
141
|
+
logger.info "[#{self.class}#wait] IMAP IDLE start (timeout: #{timeout_sec})"
|
142
|
+
@imap.idle(timeout_sec) do |resp|
|
121
143
|
logger.info "[#{self.class}#wait] got event #{resp.name} in IMAP IDLE"
|
122
|
-
|
123
|
-
end
|
124
|
-
rescue Net::IMAP::Error => e
|
125
|
-
if e.inspect.include? "connection closed"
|
126
|
-
reconnect
|
127
|
-
else
|
128
|
-
raise
|
144
|
+
@imap.idle_done
|
129
145
|
end
|
146
|
+
logger.info "[#{self.class}#wait] IMAP IDLE done"
|
147
|
+
|
148
|
+
# rescue Net::IMAP::Error => e
|
149
|
+
# if e.inspect.include? "connection closed"
|
150
|
+
# reconnect
|
151
|
+
# else
|
152
|
+
# raise
|
153
|
+
# end
|
130
154
|
end
|
131
155
|
logger.info "[#{self.class}#wait] Exit"
|
132
156
|
end # def wait
|
133
157
|
|
134
158
|
private
|
135
159
|
|
160
|
+
def select(folder)
|
161
|
+
@current_folder = folder
|
162
|
+
|
163
|
+
if folder == :all
|
164
|
+
# select "[Gmail]/All Mail" or localized one like "[Gmail]/すべてのメール"
|
165
|
+
folder = @imap.list("", "[Gmail]/*").find {|f| f.attr.include?(:All)}.name
|
166
|
+
else
|
167
|
+
folder = Net::IMAP.encode_utf7(folder)
|
168
|
+
end
|
169
|
+
|
170
|
+
logger.info "[#{self.class}#wait] IMAP Selecting #{Net::IMAP.decode_utf7(folder)}..."
|
171
|
+
@imap.select(folder)
|
172
|
+
logger.info "[#{self.class}#wait] IMAP Selected #{Net::IMAP.decode_utf7(folder)}"
|
173
|
+
end
|
174
|
+
|
136
175
|
def connect(imap_server, authorization)
|
137
176
|
logger.info "[#{self.class}#connect] Enter"
|
138
177
|
retry_count = 0
|
139
178
|
|
140
179
|
begin
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
180
|
+
Timeout.timeout(10) do
|
181
|
+
# @imap = Glima::IMAP.new(imap_server, 993, true)
|
182
|
+
@imap = Glima::IMAP.new(imap_server, :port => 993, :ssl => {:timeout => 10})
|
183
|
+
|
184
|
+
@imap.authenticate('XOAUTH2',
|
185
|
+
authorization.username,
|
186
|
+
authorization.access_token)
|
187
|
+
logger.info "[#{self.class}#connect] connected"
|
188
|
+
end
|
189
|
+
rescue Timeout::Error, Net::IMAP::NoResponseError => e
|
190
|
+
logger.info "[#{self.class}#connect] rescue #{e}"
|
149
191
|
|
150
192
|
if e.inspect.include? "Invalid credentials" && retry_count < 2
|
151
193
|
logger.info "[#{self.class}#connect] Refreshing access token for #{imap_server}."
|
@@ -159,11 +201,11 @@ module Glima
|
|
159
201
|
logger.info "[#{self.class}#connect] Exit"
|
160
202
|
end
|
161
203
|
|
162
|
-
def reconnect
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
204
|
+
# def reconnect
|
205
|
+
# logger.info "[#{self.class}#reconnect] Enter"
|
206
|
+
# connect(@imap_server, @authorization)
|
207
|
+
# logger.info "[#{self.class}#reconnect] Exit"
|
208
|
+
# end
|
167
209
|
|
168
210
|
def logger
|
169
211
|
@logger
|
data/lib/glima/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glima
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoshinari Nomura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.4.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 0.4.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mail
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,20 +114,24 @@ email:
|
|
114
114
|
executables:
|
115
115
|
- axezip
|
116
116
|
- glima
|
117
|
+
- glima-docker.sh
|
117
118
|
extensions: []
|
118
119
|
extra_rdoc_files: []
|
119
120
|
files:
|
120
121
|
- ".gitignore"
|
121
122
|
- ".rspec"
|
122
123
|
- ".travis.yml"
|
124
|
+
- Dockerfile
|
123
125
|
- Gemfile
|
124
126
|
- LICENSE.txt
|
125
127
|
- README.org
|
126
128
|
- Rakefile
|
127
129
|
- bin/console
|
128
130
|
- bin/setup
|
131
|
+
- emacs/axman.el
|
129
132
|
- exe/axezip
|
130
133
|
- exe/glima
|
134
|
+
- exe/glima-docker.sh
|
131
135
|
- glima.gemspec
|
132
136
|
- lib/glima.rb
|
133
137
|
- lib/glima/command.rb
|
@@ -180,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
184
|
version: '0'
|
181
185
|
requirements: []
|
182
186
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.5.2
|
187
|
+
rubygems_version: 2.5.2.2
|
184
188
|
signing_key:
|
185
189
|
specification_version: 4
|
186
190
|
summary: Gmail CLI client
|