redimap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6246dc5776ca68c0c6585efab3b2d773159282c
4
+ data.tar.gz: 14115fac7c4380e57dab45124e5d0ba86f253748
5
+ SHA512:
6
+ metadata.gz: 3a5733f0bc7464b380e4af69a11da7ed2f8566447d8cfafe504a90a0c5af682471c5d45512b72579958be2acfdbe892693b3156639426479af145be5bec84992
7
+ data.tar.gz: b419f72c2753d896a335bbc6cb1130aec81c655df347733c59a5d146f8e81fdba52a2b318c8ae2014cef3eded26158e1368a1753910f1fed04187f49b89b8ec2
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ redimap
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redimap.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 tiredpixel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # Redimap
2
+
3
+ Redimap provides a simple executable for polling mailboxes
4
+ within an IMAP account. It keeps track of what it's seen using Redis. For new
5
+ messages, the mailbox and uid are queued in Redis. The format used should be
6
+ compatible with Resque.
7
+
8
+ More sleep lost by [tiredpixel](http://www.tiredpixel.com).
9
+
10
+
11
+ ## Installation
12
+
13
+ Install using:
14
+
15
+ $ gem install redimap
16
+
17
+
18
+ ## Usage
19
+
20
+ Ensure that you are setting the required environment variables, perhaps using
21
+ Foreman. You'll probably want to at least set:
22
+
23
+ IMAP_HOST=imap.gmail.com
24
+ IMAP_USERNAME=username@example.com
25
+ IMAP_PASSWORD=ssssshhhhhhh
26
+ IMAP_MAILBOXES=["INBOX","Sent"]
27
+
28
+ Check and queue new messages and quit:
29
+
30
+ $ bundle exec redimap
31
+
32
+ Check and queue new messages but run for eternity using crude polling:
33
+
34
+ $ bundle exec redimap 1
35
+
36
+
37
+ ## Contributions
38
+
39
+ Contributions are embraced with much love and affection! Please fork the
40
+ repository and wizard your magic, ensuring that any tests are not broken by the
41
+ changes. Then send a pull request. Simples! If you'd like to discuss what you're
42
+ doing or planning to do, or if you get stuck on something, then just wave. :)
43
+
44
+ Do whatever makes you happy. We'll probably still like you. :)
45
+
46
+ ## Blessing
47
+
48
+ May you find peace, and help others to do likewise.
49
+
50
+
51
+ ## Licence
52
+
53
+ © [tiredpixel](http://www.tiredpixel.com) 2013. It is free software, released
54
+ under the MIT License, and may be redistributed under the terms specified in
55
+ `LICENSE`.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/redimap ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/redimap')
4
+
5
+
6
+ running = true
7
+
8
+ while running
9
+ Redimap.read_mailboxes
10
+
11
+ if ARGV[0].to_i == 1 # Oh so crude.
12
+ sleep Redimap.config.polling_interval # Sleep awhile.
13
+ else
14
+ running = false
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ require 'json'
2
+
3
+
4
+ module Redimap
5
+ class Config
6
+
7
+ attr_reader :imap_host
8
+ attr_reader :imap_port
9
+ attr_reader :imap_username
10
+ attr_reader :imap_password
11
+
12
+ attr_reader :imap_mailboxes
13
+
14
+ attr_reader :redis_url
15
+ attr_reader :redis_ns_redimap
16
+ attr_reader :redis_ns_queue
17
+
18
+ attr_reader :polling_interval
19
+
20
+ def initialize
21
+ @imap_host = ENV['IMAP_HOST']
22
+ @imap_port = ENV['IMAP_PORT'] || 993
23
+ @imap_username = ENV['IMAP_USERNAME']
24
+ @imap_password = ENV['IMAP_PASSWORD']
25
+
26
+ @imap_mailboxes = JSON.parse(ENV['IMAP_MAILBOXES'] || '["INBOX"]')
27
+
28
+ @redis_url = ENV['REDIS_URL'] || "redis://127.0.0.1:6379/0"
29
+ @redis_ns_redimap = ENV['REDIS_NS_REDIMAP'] || "redimap"
30
+ @redis_ns_queue = ENV['REDIS_NS_QUEUE'] || "resque"
31
+
32
+ @polling_interval = ENV['POLLING_INTERVAL'].to_i || 60
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,29 @@
1
+ module Redimap
2
+
3
+ def self.config
4
+ @config ||= Redimap::Config.new
5
+ end
6
+
7
+ def self.configure
8
+ yield config if block_given?
9
+ end
10
+
11
+ def self.read_mailboxes
12
+ Redimap::ImapConn.new do |imap|
13
+ Redimap::RedisConn.new do |redis|
14
+ Redimap.config.imap_mailboxes.each do |mailbox|
15
+ last_seen_uid = redis.get_mailbox_uid(mailbox)
16
+
17
+ unseen_uids = imap.read_mailbox(mailbox, last_seen_uid)
18
+
19
+ unseen_uids.each do |uid|
20
+ redis.queue_mailbox_uid(mailbox, uid)
21
+
22
+ redis.set_mailbox_uid(mailbox, uid)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,43 @@
1
+ require 'net/imap'
2
+
3
+
4
+ module Redimap
5
+ class ImapConn
6
+
7
+ attr_accessor :imap
8
+
9
+ def initialize
10
+ @imap = Net::IMAP.new(Redimap.config.imap_host, {
11
+ :port => Redimap.config.imap_port,
12
+ :ssl => true
13
+ })
14
+
15
+ if @imap
16
+ @imap.login(Redimap.config.imap_username, Redimap.config.imap_password)
17
+ end
18
+
19
+ if block_given?
20
+ yield self
21
+
22
+ close
23
+ end
24
+ end
25
+
26
+ def close
27
+ if @imap
28
+ @imap.logout
29
+
30
+ @imap.disconnect
31
+ end
32
+ end
33
+
34
+ def read_mailbox(mailbox = "INBOX", last_seen_uid = 0)
35
+ @imap.select(mailbox)
36
+
37
+ uids = @imap.uid_search("#{last_seen_uid + 1}:*")
38
+
39
+ uids.find_all { |uid| uid > last_seen_uid } # IMAP search gets fun with edge cases.
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,62 @@
1
+ require 'redis'
2
+ require 'json'
3
+
4
+
5
+ module Redimap
6
+ class RedisConn
7
+
8
+ QUEUE_QUEUE = 'redimap'
9
+ QUEUE_CLASS = 'RedimapJob'
10
+
11
+ attr_accessor :redis
12
+
13
+ def initialize
14
+ @redis = Redis.connect(:url => Redimap.config.redis_url)
15
+
16
+ if block_given?
17
+ yield self
18
+
19
+ close
20
+ end
21
+ end
22
+
23
+ def close
24
+ if @redis
25
+ @redis.quit
26
+ end
27
+ end
28
+
29
+ def get_mailbox_uid(mailbox)
30
+ @redis.hget(
31
+ "#{Redimap.config.redis_ns_redimap}:mailboxes",
32
+ mailbox
33
+ ).to_i # Also handles nil.
34
+ end
35
+
36
+ def set_mailbox_uid(mailbox, uid)
37
+ @redis.hset(
38
+ "#{Redimap.config.redis_ns_redimap}:mailboxes",
39
+ mailbox,
40
+ uid
41
+ )
42
+ end
43
+
44
+ def queue_mailbox_uid(mailbox, uid)
45
+ @redis.sadd(
46
+ "#{Redimap.config.redis_ns_queue}:queues",
47
+ QUEUE_QUEUE
48
+ )
49
+
50
+ payload = {
51
+ :class => QUEUE_CLASS,
52
+ :args => [mailbox, uid]
53
+ }.to_json
54
+
55
+ @redis.rpush(
56
+ "#{Redimap.config.redis_ns_queue}:queue:#{QUEUE_QUEUE}",
57
+ payload
58
+ )
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ module Redimap
2
+
3
+ VERSION = "0.1.0"
4
+
5
+ end
data/lib/redimap.rb ADDED
@@ -0,0 +1,4 @@
1
+ require_relative 'redimap/config'
2
+ require_relative 'redimap/core'
3
+ require_relative 'redimap/imap_conn'
4
+ require_relative 'redimap/redis_conn'
data/redimap.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require './lib/redimap/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "redimap"
8
+ spec.version = Redimap::VERSION
9
+ spec.authors = ["tiredpixel"]
10
+ spec.email = ["tp@tiredpixel.com"]
11
+ spec.description = %q{Redimap provides a simple executable for polling mailboxes
12
+ within an IMAP account. It keeps track of what it's seen using Redis. For new
13
+ messages, the mailbox and uid are queued in Redis. The format used should be
14
+ compatible with Resque.}
15
+ spec.summary = %q{Redimap polls IMAP account mailboxes and queues in Redis.}
16
+ spec.homepage = ""
17
+ spec.license = "MIT"
18
+
19
+ spec.files = `git ls-files`.split($/)
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "redis", "~> 3.0.3"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rspec"
29
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redimap::Config do
4
+
5
+ context "Defaults" do
6
+ before(:each) do
7
+ ENV.stub(:[])
8
+
9
+ @config = Redimap::Config.new
10
+ end
11
+
12
+ it "imap_port should default to 993" do
13
+ @config.imap_port.should == 993
14
+ end
15
+
16
+ it "imap_mailboxes should default to [INBOX]" do
17
+ @config.imap_mailboxes.should == ['INBOX']
18
+ end
19
+
20
+ it "redis_url should default to redis://127.0.0.1:6379/0" do
21
+ @config.redis_url.should == "redis://127.0.0.1:6379/0"
22
+ end
23
+
24
+ it "redis_ns_redimap should default to redimap" do
25
+ @config.redis_ns_redimap.should == "redimap"
26
+ end
27
+
28
+ it "redis_ns_queue should default to resque" do
29
+ @config.redis_ns_queue.should == "resque"
30
+ end
31
+
32
+ it "redis_ns_queue should default to 60 seconds" do
33
+ @config.polling_interval.should == 60
34
+ end
35
+ end
36
+
37
+ context "Non-defaults" do
38
+ before(:each) do
39
+ ENV.stub(:[]).with("IMAP_HOST").and_return("imap.carrot.localhost")
40
+ ENV.stub(:[]).with("IMAP_PORT").and_return(666)
41
+ ENV.stub(:[]).with("IMAP_USERNAME").and_return("Pachelbel")
42
+ ENV.stub(:[]).with("IMAP_PASSWORD").and_return("Canon")
43
+ ENV.stub(:[]).with("IMAP_MAILBOXES").and_return('["INBOX","SENT"]')
44
+ ENV.stub(:[]).with("REDIS_URL").and_return("redis://127.0.0.1:6379/1")
45
+ ENV.stub(:[]).with("REDIS_NS_REDIMAP").and_return("brekyread")
46
+ ENV.stub(:[]).with("REDIS_NS_QUEUE").and_return("sidekiq")
47
+ ENV.stub(:[]).with("POLLING_INTERVAL").and_return(300)
48
+
49
+ @config = Redimap::Config.new
50
+ end
51
+
52
+ it "imap_host should get set from IMAP_HOST" do
53
+ @config.imap_host.should == "imap.carrot.localhost"
54
+ end
55
+
56
+ it "imap_port should get set from IMAP_PORT" do
57
+ @config.imap_port.should == 666
58
+ end
59
+
60
+ it "imap_username should get set from IMAP_USERNAME" do
61
+ @config.imap_username.should == "Pachelbel"
62
+ end
63
+
64
+ it "imap_password should get set from IMAP_PASSWORD" do
65
+ @config.imap_password.should == "Canon"
66
+ end
67
+
68
+ it "imap_mailboxes should get set from IMAP_MAILBOXES" do
69
+ @config.imap_mailboxes.should == ['INBOX', 'SENT']
70
+ end
71
+
72
+ it "redis_url should get set from REDIS_URL" do
73
+ @config.redis_url.should == "redis://127.0.0.1:6379/1"
74
+ end
75
+
76
+ it "redis_ns_redimap should get set from REDIS_NS_REDIMAP" do
77
+ @config.redis_ns_redimap.should == "brekyread"
78
+ end
79
+
80
+ it "redis_ns_queue should get set from REDIS_NS_QUEUE" do
81
+ @config.redis_ns_queue.should == "sidekiq"
82
+ end
83
+
84
+ it "polling_interval should get set from POLLING_INTERVAL" do
85
+ @config.polling_interval.should == 300
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redimap do
4
+
5
+ context "Constants" do
6
+ it "VERSION should be like major.minor.patch" do
7
+ Redimap::VERSION.should =~ /\A\d+\.\d+\.\d+\z/
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,49 @@
1
+ require 'net/imap'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Redimap::ImapConn do
6
+
7
+ before(:each) do
8
+ @fake_net_imap = double(Net::IMAP)
9
+
10
+ Net::IMAP.stub(:new).and_return(@fake_net_imap)
11
+
12
+ @fake_net_imap.stub(:login)
13
+ end
14
+
15
+ context "#initialize" do
16
+ it "should set imap as Net::IMAP" do
17
+ Redimap::ImapConn.new.imap.should == @fake_net_imap
18
+ end
19
+
20
+ it "should #close when block" do
21
+ Redimap::ImapConn.new do |imap|
22
+ imap.should_receive(:close)
23
+ end
24
+ end
25
+ end
26
+
27
+ context "#close" do
28
+ before(:each) do
29
+ @imap = Redimap::ImapConn.new
30
+ end
31
+
32
+ it "should disconnect from IMAP" do
33
+ @imap.imap.stub(:logout)
34
+
35
+ @imap.imap.should_receive(:disconnect)
36
+
37
+ @imap.close
38
+ end
39
+
40
+ it "should logout from IMAP" do
41
+ @imap.imap.stub(:disconnect)
42
+
43
+ @imap.imap.should_receive(:logout)
44
+
45
+ @imap.close
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec/autorun'
2
+
3
+ require File.expand_path("../../lib/redimap.rb", __FILE__)
4
+
5
+ Dir[File.join("../../spec/support/**/*.rb")].each { |f| require f }
6
+
7
+
8
+ RSpec.configure do |config|
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redimap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - tiredpixel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |-
70
+ Redimap provides a simple executable for polling mailboxes
71
+ within an IMAP account. It keeps track of what it's seen using Redis. For new
72
+ messages, the mailbox and uid are queued in Redis. The format used should be
73
+ compatible with Resque.
74
+ email:
75
+ - tp@tiredpixel.com
76
+ executables:
77
+ - redimap
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - .gitignore
82
+ - .ruby-gemset
83
+ - .ruby-version
84
+ - Gemfile
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - bin/redimap
89
+ - lib/redimap.rb
90
+ - lib/redimap/config.rb
91
+ - lib/redimap/core.rb
92
+ - lib/redimap/imap_conn.rb
93
+ - lib/redimap/redis_conn.rb
94
+ - lib/redimap/version.rb
95
+ - redimap.gemspec
96
+ - spec/lib/redimap/config_spec.rb
97
+ - spec/lib/redimap/core_spec.rb
98
+ - spec/lib/redimap/imap_conn_spec.rb
99
+ - spec/spec_helper.rb
100
+ homepage: ''
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.0.3
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Redimap polls IMAP account mailboxes and queues in Redis.
124
+ test_files:
125
+ - spec/lib/redimap/config_spec.rb
126
+ - spec/lib/redimap/core_spec.rb
127
+ - spec/lib/redimap/imap_conn_spec.rb
128
+ - spec/spec_helper.rb