imap_notifier 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile +5 -8
- data/Gemfile.lock +3 -2
- data/bin/imap_notifier +8 -7
- data/imap_notifier.gemspec +1 -0
- data/lib/imap_notifier/base.rb +45 -51
- data/lib/imap_notifier/config.rb +26 -14
- data/lib/imap_notifier/growler.rb +6 -3
- data/lib/imap_notifier/notifier.rb +7 -3
- data/lib/imap_notifier/version.rb +1 -1
- data/lib/imap_notifier.rb +1 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
M2M4NjlmOTY0ZTUxNWRlY2JlOTUwNjY1ZDgyNGY5OTQ0YmZlNjE2YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZWE4OThiYjczOTM0MGY3YTVkN2Y4ZmFkZWQwMDI3YjEwM2M4YjQxZA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZGUwMmJhNDQ2ODJlNjM0Y2UxYTRlODlmZjY4ZWZiMzNlYmFhYTE5OTg1Njhh
|
10
|
+
MGQxOWQ0YmQzZjAzNmU2YTBiNzM3ODRjMzMwYjI0NmE4OGJlYWIxMzFlNzhl
|
11
|
+
NDVkMzhlODAxNWEyMTA5OGU5ZWM1MGIxYTJjMmU3ZTEzZjc4OTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NmVkNTA3YzlmMDU5Y2IyOGJhMmQ4Y2EzOWY0MjI0N2NhMGY3N2Q3YzE2OTk2
|
14
|
+
NzVhNDViZTU5Y2ViZjdjNjllMDdmZThmMGM4YjYwMTM2YzRlZDlhMmIzZDE3
|
15
|
+
MzEyZGNiZDMzMmNiZjYwN2VkN2Q1OTM4MGU5M2FkZjlmOTNmODY=
|
data/Gemfile
CHANGED
@@ -3,14 +3,11 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in imap_notifier.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
gem 'terminal-notifier'
|
9
|
-
else
|
10
|
-
gem 'ruby-growl'
|
11
|
-
end
|
12
|
-
else
|
13
|
-
raise "You must be running Mac OS X for imap_notifier to work!"
|
6
|
+
def is_mnt_lion?
|
7
|
+
@lion ||= (RUBY_PLATFORM.match /(\d+)\.\d+\.\d+$/)[0].to_i >= 12
|
14
8
|
end
|
15
9
|
|
10
|
+
gem 'terminal-notifier', :require => is_mnt_lion?
|
11
|
+
gem 'ruby-growl', :require => is_mnt_lion?
|
12
|
+
|
16
13
|
gem 'highline'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
imap_notifier (0.2.
|
4
|
+
imap_notifier (0.2.3)
|
5
5
|
highline
|
6
6
|
ruby-growl
|
7
7
|
terminal-notifier
|
@@ -16,7 +16,7 @@ GEM
|
|
16
16
|
ruby-growl (4.0)
|
17
17
|
uuid (~> 2.3, >= 2.3.5)
|
18
18
|
systemu (2.5.2)
|
19
|
-
terminal-notifier (1.
|
19
|
+
terminal-notifier (1.5.1)
|
20
20
|
uuid (2.3.7)
|
21
21
|
macaddr (~> 1.0)
|
22
22
|
|
@@ -28,4 +28,5 @@ DEPENDENCIES
|
|
28
28
|
highline
|
29
29
|
imap_notifier!
|
30
30
|
rake
|
31
|
+
ruby-growl
|
31
32
|
terminal-notifier
|
data/bin/imap_notifier
CHANGED
@@ -24,29 +24,30 @@ opt_parser = OptionParser.new do |opt|
|
|
24
24
|
opts[:debug] = true
|
25
25
|
end
|
26
26
|
|
27
|
-
opt.on('-f', '--file FILE', "Read configuration file
|
27
|
+
opt.on('-f', '--file FILE', "Read configuration file.\t[DEFAULT: ~/.imap_notifier]") do |c|
|
28
28
|
opts[:config] = c
|
29
29
|
end
|
30
30
|
|
31
|
-
opt.on('-s','--server STR', "Specify imap server
|
31
|
+
opt.on('-s','--server STR', "Specify imap server.\t[Default: #{$imap_server}]") do |s|
|
32
32
|
$imap_server = s
|
33
33
|
end
|
34
34
|
|
35
35
|
opt.on('-d','--domain STR',
|
36
|
-
"Specify email domain
|
37
|
-
opts[:domain] = d.gsub('
|
36
|
+
"Specify email domain.\t[Default: #{$imap_server.split('.').pop(2).join('.')}]") do |d|
|
37
|
+
opts[:domain] = d.gsub(/.+\@/,'')
|
38
38
|
end
|
39
39
|
|
40
|
-
opt.on('-u','--user STR', "Specify user login
|
41
|
-
opts[:
|
40
|
+
opt.on('-u','--user STR', "Specify user login.\t[Default: ENV['USER']]") do |u|
|
41
|
+
opts[:user] = u
|
42
42
|
end
|
43
43
|
|
44
|
-
opt.on('-m','--max INT', "
|
44
|
+
opt.on('-m','--max INT', "Group notify on N or more mails. [Default: #{MAX_MAIL}]") do |m|
|
45
45
|
opts[:max] = m.to_i
|
46
46
|
end
|
47
47
|
|
48
48
|
opt.on('-k', '--kill', "Kill currently running #{opt.program_name} process with SIGINT") do
|
49
49
|
IMAP_Notifier.kill_process
|
50
|
+
exit
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
data/imap_notifier.gemspec
CHANGED
@@ -20,6 +20,7 @@ If you're running Max OSX > 10.8, terminal-notifier is required, otherwise ruby-
|
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
+
spec.required_ruby_version = '>= 1.9.2'
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
25
|
spec.add_development_dependency "rake"
|
25
26
|
spec.add_dependency "highline"
|
data/lib/imap_notifier/base.rb
CHANGED
@@ -5,8 +5,6 @@ class IMAP_Notifier
|
|
5
5
|
Process.kill("SIGINT", pid)
|
6
6
|
rescue Errno::ESRCH, Errno::ENOENT => e
|
7
7
|
puts "#{e.message} - Exiting..."
|
8
|
-
ensure
|
9
|
-
exit
|
10
8
|
end
|
11
9
|
|
12
10
|
def initialize(opts={})
|
@@ -15,69 +13,52 @@ class IMAP_Notifier
|
|
15
13
|
|
16
14
|
pid = fork do
|
17
15
|
$stderr.reopen(ERRFILE, 'w')
|
18
|
-
|
19
|
-
$stdout.reopen(DEBUGFILE, 'w')
|
20
|
-
@notifier.alert("DEBUG MODE ENABLED", "DEBUG LOGFILE: #{DEBUGFILE}")
|
21
|
-
end
|
22
|
-
at_exit { File.delete(PIDFILE) if File.exists?(PIDFILE) }
|
16
|
+
at_exit { self.stop }
|
23
17
|
run
|
24
18
|
end
|
25
19
|
File.open(PIDFILE, 'w') { |f| f.write pid }
|
26
20
|
end
|
27
21
|
|
28
|
-
def imap
|
29
|
-
@imap ||= _imap
|
30
|
-
end
|
31
|
-
|
32
22
|
def run
|
33
23
|
begin
|
34
24
|
@folders.each do |f, ids|
|
35
|
-
|
36
|
-
|
37
|
-
p "Mailbox: #{f}" if @debug
|
38
|
-
unseen = imap.search(["UNSEEN"])
|
39
|
-
ungrowled = unseen - ids
|
40
|
-
ungrowled_count = ungrowled.length
|
41
|
-
p "All unseen mail ids: #{unseen}",
|
42
|
-
"All ungrowled mail ids: #{ungrowled}",
|
43
|
-
"Ungrowled count: #{ungrowled_count}" if @debug
|
44
|
-
|
45
|
-
if ungrowled_count > @max_mail
|
46
|
-
p "New Mail in #{f}!",
|
47
|
-
"New: #{ungrowled_count}\nTotal: #{unseen.length}" if @debug
|
48
|
-
@notifier.alert("New Mail in #{f}!", "New: #{ungrowled_count}")
|
49
|
-
else
|
50
|
-
ungrowled.each do |msg_id|
|
51
|
-
msg = imap.fetch(msg_id, "ENVELOPE")[0].attr["ENVELOPE"]
|
52
|
-
next if ids.include?(msg.message_id)
|
53
|
-
p "Growled about #{msg.message_id}" if @debug
|
54
|
-
@notifier.alert("Mail from #{msg.sender.first.mailbox}", "#{msg.subject}")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
@folders[f] = unseen
|
25
|
+
alert_folder(f, ids)
|
58
26
|
end
|
59
27
|
sleep SLEEP
|
60
|
-
rescue Interrupt
|
61
|
-
@notifier.alert("Goodbye!", '')
|
62
|
-
raise
|
63
28
|
rescue EOFError
|
64
|
-
imap
|
29
|
+
@imap = nil
|
65
30
|
rescue Exception => err
|
66
|
-
|
67
|
-
|
68
|
-
"See #{ERRFILE} for more info." if @debug
|
69
|
-
@notifier.alert(err.class, err.message)
|
70
|
-
|
71
|
-
warn Time.now
|
72
|
-
warn @user
|
73
|
-
warn $imap_server
|
74
|
-
warn err.class
|
75
|
-
warn err.message
|
76
|
-
err.backtrace.map{ |e| warn e }
|
77
|
-
raise
|
31
|
+
say_goodbye(err.class.to_s) || handle_exception(err)
|
32
|
+
exit
|
78
33
|
end while true
|
79
34
|
end
|
80
35
|
|
36
|
+
def alert_folder(f, ids)
|
37
|
+
imap.examine(f)
|
38
|
+
unseen = imap.search(["UNSEEN"])
|
39
|
+
unalerted = unseen - ids
|
40
|
+
|
41
|
+
if unalerted.length > @max_mail
|
42
|
+
@notifier.alert("#{f}: #{unalerted.length} new mails", :group => f)
|
43
|
+
else
|
44
|
+
unalerted.each do |msg_id|
|
45
|
+
msg = imap.fetch(msg_id, "ENVELOPE")[0].attr["ENVELOPE"]
|
46
|
+
next if ids.include?(msg.message_id)
|
47
|
+
@notifier.alert("#{f} #{msg.subject}", :title => "Mail from #{msg.sender.first.mailbox}", :group => msg_id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@folders[f] = unseen
|
51
|
+
end
|
52
|
+
|
53
|
+
def imap
|
54
|
+
@imap ||= _imap
|
55
|
+
end
|
56
|
+
|
57
|
+
def stop
|
58
|
+
IMAP_Notifier::Alert.remove
|
59
|
+
File.delete(PIDFILE) if File.exists?(PIDFILE)
|
60
|
+
end
|
61
|
+
|
81
62
|
private
|
82
63
|
def get_password(prompt="Enter Password: ")
|
83
64
|
ask(prompt) { |q| q.echo = false }
|
@@ -86,7 +67,20 @@ class IMAP_Notifier
|
|
86
67
|
def _imap
|
87
68
|
imap = Net::IMAP.new($imap_server, { :port => 993, :ssl => true } )
|
88
69
|
imap.login(@user, @password)
|
89
|
-
@notifier.alert("
|
70
|
+
@notifier.alert("#{@user} connected!", :group => @domain)
|
90
71
|
return imap
|
91
72
|
end
|
73
|
+
|
74
|
+
def say_goodbye(klass)
|
75
|
+
return if !(klass.eql? "Interrupt")
|
76
|
+
@notifier.alert("Goodbye!", :group => @domain)
|
77
|
+
File.delete(ERRFILE) if File.exists?(ERRFILE)
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_exception(err)
|
81
|
+
@notifier.alert(err.message, :title => err.class, :open => "file://#{ERRFILE}")
|
82
|
+
warn("#{Time.now} - #{@user}")
|
83
|
+
warn("#{err.class}: #{err.message}")
|
84
|
+
err.backtrace.map{ |e| warn e }
|
85
|
+
end
|
92
86
|
end
|
data/lib/imap_notifier/config.rb
CHANGED
@@ -1,21 +1,33 @@
|
|
1
1
|
class IMAP_Notifier
|
2
2
|
def config(opts={})
|
3
|
-
|
4
|
-
if File.exists? file
|
5
|
-
m = sprintf("%o", File.stat(file).mode).split('').last(3).join().to_i
|
6
|
-
if m != 600
|
7
|
-
warn "#{file} must have permissions 0644, not #{m}"
|
8
|
-
exit 1
|
9
|
-
end
|
10
|
-
YAML.load(File.open(file)).each do |k,v|
|
11
|
-
opts[k.to_sym] ||= v
|
12
|
-
end
|
13
|
-
end
|
3
|
+
read_conf opts
|
14
4
|
@domain = opts[:domain] || $imap_server.split('.').pop(2).join('.')
|
15
|
-
@user = "#{opts[:user]
|
5
|
+
@user = "#{opts[:user]}@#{@domain}"
|
16
6
|
@password = opts[:password] || get_password
|
17
|
-
@folders =
|
7
|
+
@folders = mbox_conf opts[:folders] || ['INBOX']
|
18
8
|
@debug = opts[:debug] || false
|
19
|
-
@max_mail = opts[:max]
|
9
|
+
@max_mail = opts[:max] || MAX_MAIL
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def mbox_conf ary
|
14
|
+
Hash[ary.map{ |f| [f,Array.new] }]
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_conf opts
|
18
|
+
file = File.expand_path("~/.imap_notifier")
|
19
|
+
return if ! File.exists? file
|
20
|
+
ensure_perms file
|
21
|
+
YAML.load(File.open(file)).each do |k,v|
|
22
|
+
opts[k.to_sym] ||= v
|
23
|
+
end
|
24
|
+
opts[:user] ||= ENV['USER']
|
25
|
+
end
|
26
|
+
|
27
|
+
def ensure_perms file
|
28
|
+
m = sprintf("%o", File.stat(file).mode).split('').last(3).join().to_i
|
29
|
+
return if m.eql? 600
|
30
|
+
warn "#{file} permissions should be set to 600 #{m}"
|
31
|
+
exit 1
|
20
32
|
end
|
21
33
|
end
|
@@ -1,13 +1,16 @@
|
|
1
1
|
require 'ruby-growl'
|
2
2
|
|
3
3
|
class IMAP_Notifier::Alert < Growl
|
4
|
+
def self.remove
|
5
|
+
end
|
6
|
+
|
4
7
|
def initialize
|
5
8
|
super("localhost", ::IMAP_Notifier::VERSION)
|
6
9
|
end
|
7
10
|
|
8
|
-
def alert(
|
11
|
+
def alert(body, opts={})
|
12
|
+
opts[:title] ||= self.class.name
|
9
13
|
add_notification ::IMAP_Notifier::VERSION
|
10
|
-
notify ::IMAP_Notifier::VERSION, title, body
|
14
|
+
notify ::IMAP_Notifier::VERSION, opts[:title], body
|
11
15
|
end
|
12
|
-
|
13
16
|
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
require 'terminal-notifier'
|
2
2
|
|
3
3
|
class IMAP_Notifier::Alert
|
4
|
-
|
4
|
+
def self.remove
|
5
|
+
return if (msgs = TerminalNotifier.list).nil?
|
6
|
+
msgs.map{ |a| TerminalNotifier.remove a[:group] }
|
7
|
+
end
|
5
8
|
|
6
|
-
def alert(
|
7
|
-
|
9
|
+
def alert(body, opts={})
|
10
|
+
opts[:title] ||= self.class.name
|
11
|
+
TerminalNotifier.notify(body, opts.merge({:sender => 'com.apple.Mail'}))
|
8
12
|
end
|
9
13
|
end
|
data/lib/imap_notifier.rb
CHANGED
@@ -6,11 +6,10 @@ require 'imap_notifier/version'
|
|
6
6
|
require 'imap_notifier/config'
|
7
7
|
require 'imap_notifier/base'
|
8
8
|
|
9
|
-
|
10
9
|
MAX_MAIL = 5 # Max new mails mentioned before they
|
11
10
|
# are grouped together
|
12
11
|
SLEEP = 30
|
13
|
-
ERRFILE = '/
|
12
|
+
ERRFILE = File.expand_path('~/Desktop/imap_notifier.log')
|
14
13
|
DEBUGFILE = '/tmp/imap_notifier.debug'
|
15
14
|
PIDFILE = '/tmp/imap_notifier.pid'
|
16
15
|
$imap_server = "imap.gmail.com" # could be anything with tweaks
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imap_notifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Campbell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -113,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
requirements:
|
114
114
|
- - ! '>='
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
116
|
+
version: 1.9.2
|
117
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
118
|
requirements:
|
119
119
|
- - ! '>='
|