sum 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +10 -12
- data/Rakefile +6 -7
- data/config/externals.yml +3 -3
- data/config/schedule.rb +0 -1
- data/features/step_definitions/when.rb +3 -3
- data/features/support/env.rb +9 -10
- data/gemspec.rb +13 -14
- data/lib/sum.rb +8 -8
- data/lib/sum/helper/cron.rb +1 -1
- data/lib/sum/model/user.rb +3 -3
- data/vendor/fetcher/MIT-LICENSE +20 -0
- data/vendor/fetcher/README.rdoc +94 -0
- data/vendor/fetcher/Rakefile +30 -0
- data/vendor/fetcher/fetcher.gemspec +27 -0
- data/vendor/fetcher/gemspec.rb +17 -0
- data/vendor/fetcher/init.rb +0 -0
- data/vendor/fetcher/lib/fetcher.rb +23 -0
- data/vendor/fetcher/lib/fetcher/base.rb +63 -0
- data/vendor/fetcher/lib/fetcher/imap.rb +79 -0
- data/vendor/fetcher/lib/fetcher/pop.rb +50 -0
- data/vendor/fetcher/lib/vendor/plain_imap.rb +21 -0
- data/vendor/fetcher/lib/vendor/secure_pop.rb +125 -0
- data/vendor/fetcher/test/fetcher_test.rb +74 -0
- metadata +40 -241
- data/sum.gemspec +0 -69
- data/vendor/webrat/History.txt +0 -358
- data/vendor/webrat/MIT-LICENSE.txt +0 -19
- data/vendor/webrat/README.rdoc +0 -85
- data/vendor/webrat/Rakefile +0 -200
- data/vendor/webrat/install.rb +0 -1
- data/vendor/webrat/lib/webrat.rb +0 -31
- data/vendor/webrat/lib/webrat/core.rb +0 -14
- data/vendor/webrat/lib/webrat/core/configuration.rb +0 -102
- data/vendor/webrat/lib/webrat/core/elements/area.rb +0 -31
- data/vendor/webrat/lib/webrat/core/elements/element.rb +0 -33
- data/vendor/webrat/lib/webrat/core/elements/field.rb +0 -409
- data/vendor/webrat/lib/webrat/core/elements/form.rb +0 -103
- data/vendor/webrat/lib/webrat/core/elements/label.rb +0 -31
- data/vendor/webrat/lib/webrat/core/elements/link.rb +0 -93
- data/vendor/webrat/lib/webrat/core/elements/select_option.rb +0 -35
- data/vendor/webrat/lib/webrat/core/locators.rb +0 -20
- data/vendor/webrat/lib/webrat/core/locators/area_locator.rb +0 -38
- data/vendor/webrat/lib/webrat/core/locators/button_locator.rb +0 -54
- data/vendor/webrat/lib/webrat/core/locators/field_by_id_locator.rb +0 -37
- data/vendor/webrat/lib/webrat/core/locators/field_labeled_locator.rb +0 -56
- data/vendor/webrat/lib/webrat/core/locators/field_locator.rb +0 -25
- data/vendor/webrat/lib/webrat/core/locators/field_named_locator.rb +0 -41
- data/vendor/webrat/lib/webrat/core/locators/form_locator.rb +0 -19
- data/vendor/webrat/lib/webrat/core/locators/label_locator.rb +0 -34
- data/vendor/webrat/lib/webrat/core/locators/link_locator.rb +0 -74
- data/vendor/webrat/lib/webrat/core/locators/locator.rb +0 -20
- data/vendor/webrat/lib/webrat/core/locators/select_option_locator.rb +0 -59
- data/vendor/webrat/lib/webrat/core/logging.rb +0 -24
- data/vendor/webrat/lib/webrat/core/matchers.rb +0 -4
- data/vendor/webrat/lib/webrat/core/matchers/have_content.rb +0 -73
- data/vendor/webrat/lib/webrat/core/matchers/have_selector.rb +0 -74
- data/vendor/webrat/lib/webrat/core/matchers/have_tag.rb +0 -21
- data/vendor/webrat/lib/webrat/core/matchers/have_xpath.rb +0 -147
- data/vendor/webrat/lib/webrat/core/methods.rb +0 -63
- data/vendor/webrat/lib/webrat/core/mime.rb +0 -29
- data/vendor/webrat/lib/webrat/core/save_and_open_page.rb +0 -48
- data/vendor/webrat/lib/webrat/core/scope.rb +0 -350
- data/vendor/webrat/lib/webrat/core/session.rb +0 -299
- data/vendor/webrat/lib/webrat/core/xml.rb +0 -115
- data/vendor/webrat/lib/webrat/core/xml/hpricot.rb +0 -19
- data/vendor/webrat/lib/webrat/core/xml/nokogiri.rb +0 -76
- data/vendor/webrat/lib/webrat/core/xml/rexml.rb +0 -24
- data/vendor/webrat/lib/webrat/core_extensions/blank.rb +0 -58
- data/vendor/webrat/lib/webrat/core_extensions/deprecate.rb +0 -8
- data/vendor/webrat/lib/webrat/core_extensions/detect_mapped.rb +0 -12
- data/vendor/webrat/lib/webrat/core_extensions/meta_class.rb +0 -6
- data/vendor/webrat/lib/webrat/core_extensions/nil_to_param.rb +0 -5
- data/vendor/webrat/lib/webrat/core_extensions/tcp_socket.rb +0 -27
- data/vendor/webrat/lib/webrat/mechanize.rb +0 -74
- data/vendor/webrat/lib/webrat/merb.rb +0 -9
- data/vendor/webrat/lib/webrat/merb_multipart_support.rb +0 -27
- data/vendor/webrat/lib/webrat/merb_session.rb +0 -82
- data/vendor/webrat/lib/webrat/rack.rb +0 -25
- data/vendor/webrat/lib/webrat/rails.rb +0 -106
- data/vendor/webrat/lib/webrat/rspec-rails.rb +0 -10
- data/vendor/webrat/lib/webrat/selenium.rb +0 -81
- data/vendor/webrat/lib/webrat/selenium/application_server_factory.rb +0 -40
- data/vendor/webrat/lib/webrat/selenium/application_servers.rb +0 -5
- data/vendor/webrat/lib/webrat/selenium/application_servers/base.rb +0 -46
- data/vendor/webrat/lib/webrat/selenium/application_servers/external.rb +0 -26
- data/vendor/webrat/lib/webrat/selenium/application_servers/merb.rb +0 -50
- data/vendor/webrat/lib/webrat/selenium/application_servers/rails.rb +0 -44
- data/vendor/webrat/lib/webrat/selenium/application_servers/sinatra.rb +0 -37
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/button.js +0 -19
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/label.js +0 -16
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webrat.js +0 -5
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratlink.js +0 -12
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +0 -15
- data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +0 -5
- data/vendor/webrat/lib/webrat/selenium/matchers.rb +0 -4
- data/vendor/webrat/lib/webrat/selenium/matchers/have_content.rb +0 -66
- data/vendor/webrat/lib/webrat/selenium/matchers/have_selector.rb +0 -49
- data/vendor/webrat/lib/webrat/selenium/matchers/have_tag.rb +0 -72
- data/vendor/webrat/lib/webrat/selenium/matchers/have_xpath.rb +0 -45
- data/vendor/webrat/lib/webrat/selenium/selenium_extensions.js +0 -6
- data/vendor/webrat/lib/webrat/selenium/selenium_rc_server.rb +0 -84
- data/vendor/webrat/lib/webrat/selenium/selenium_session.rb +0 -248
- data/vendor/webrat/lib/webrat/selenium/silence_stream.rb +0 -18
- data/vendor/webrat/lib/webrat/sinatra.rb +0 -11
- data/vendor/webrat/spec/fakes/test_session.rb +0 -34
- data/vendor/webrat/spec/integration/merb/Rakefile +0 -35
- data/vendor/webrat/spec/integration/merb/app/controllers/application.rb +0 -2
- data/vendor/webrat/spec/integration/merb/app/controllers/exceptions.rb +0 -13
- data/vendor/webrat/spec/integration/merb/app/controllers/testing.rb +0 -27
- data/vendor/webrat/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +0 -63
- data/vendor/webrat/spec/integration/merb/app/views/exceptions/not_found.html.erb +0 -47
- data/vendor/webrat/spec/integration/merb/app/views/layout/application.html.erb +0 -12
- data/vendor/webrat/spec/integration/merb/app/views/testing/show_form.html.erb +0 -27
- data/vendor/webrat/spec/integration/merb/app/views/testing/upload.html.erb +0 -9
- data/vendor/webrat/spec/integration/merb/config/environments/development.rb +0 -15
- data/vendor/webrat/spec/integration/merb/config/environments/rake.rb +0 -11
- data/vendor/webrat/spec/integration/merb/config/environments/test.rb +0 -14
- data/vendor/webrat/spec/integration/merb/config/init.rb +0 -25
- data/vendor/webrat/spec/integration/merb/config/rack.rb +0 -11
- data/vendor/webrat/spec/integration/merb/config/router.rb +0 -34
- data/vendor/webrat/spec/integration/merb/spec/spec.opts +0 -1
- data/vendor/webrat/spec/integration/merb/spec/spec_helper.rb +0 -24
- data/vendor/webrat/spec/integration/merb/spec/webrat_spec.rb +0 -39
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/app_script.rb +0 -31
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/common.rb +0 -64
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/gem_ext.rb +0 -124
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/main.thor +0 -150
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/ops.rb +0 -93
- data/vendor/webrat/spec/integration/merb/tasks/merb.thor/utils.rb +0 -40
- data/vendor/webrat/spec/integration/rack/Rakefile +0 -5
- data/vendor/webrat/spec/integration/rack/app.rb +0 -73
- data/vendor/webrat/spec/integration/rack/test/helper.rb +0 -20
- data/vendor/webrat/spec/integration/rack/test/webrat_rack_test.rb +0 -62
- data/vendor/webrat/spec/integration/rails/Rakefile +0 -30
- data/vendor/webrat/spec/integration/rails/app/controllers/application.rb +0 -15
- data/vendor/webrat/spec/integration/rails/app/controllers/buttons_controller.rb +0 -7
- data/vendor/webrat/spec/integration/rails/app/controllers/fields_controller.rb +0 -4
- data/vendor/webrat/spec/integration/rails/app/controllers/links_controller.rb +0 -7
- data/vendor/webrat/spec/integration/rails/app/controllers/webrat_controller.rb +0 -43
- data/vendor/webrat/spec/integration/rails/app/helpers/buttons_helper.rb +0 -2
- data/vendor/webrat/spec/integration/rails/app/helpers/fields_helper.rb +0 -2
- data/vendor/webrat/spec/integration/rails/app/helpers/links_helper.rb +0 -2
- data/vendor/webrat/spec/integration/rails/app/views/buttons/show.html.erb +0 -11
- data/vendor/webrat/spec/integration/rails/app/views/fields/show.html.erb +0 -9
- data/vendor/webrat/spec/integration/rails/app/views/links/show.html.erb +0 -5
- data/vendor/webrat/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +0 -4
- data/vendor/webrat/spec/integration/rails/app/views/webrat/buttons.html.erb +0 -11
- data/vendor/webrat/spec/integration/rails/app/views/webrat/form.html.erb +0 -28
- data/vendor/webrat/spec/integration/rails/config/boot.rb +0 -109
- data/vendor/webrat/spec/integration/rails/config/environment.rb +0 -12
- data/vendor/webrat/spec/integration/rails/config/environments/development.rb +0 -17
- data/vendor/webrat/spec/integration/rails/config/environments/selenium.rb +0 -22
- data/vendor/webrat/spec/integration/rails/config/environments/test.rb +0 -22
- data/vendor/webrat/spec/integration/rails/config/initializers/inflections.rb +0 -10
- data/vendor/webrat/spec/integration/rails/config/initializers/mime_types.rb +0 -5
- data/vendor/webrat/spec/integration/rails/config/initializers/new_rails_defaults.rb +0 -17
- data/vendor/webrat/spec/integration/rails/config/locales/en.yml +0 -5
- data/vendor/webrat/spec/integration/rails/config/routes.rb +0 -18
- data/vendor/webrat/spec/integration/rails/public/404.html +0 -30
- data/vendor/webrat/spec/integration/rails/public/422.html +0 -30
- data/vendor/webrat/spec/integration/rails/public/500.html +0 -33
- data/vendor/webrat/spec/integration/rails/script/about +0 -4
- data/vendor/webrat/spec/integration/rails/script/console +0 -3
- data/vendor/webrat/spec/integration/rails/script/dbconsole +0 -3
- data/vendor/webrat/spec/integration/rails/script/destroy +0 -3
- data/vendor/webrat/spec/integration/rails/script/generate +0 -3
- data/vendor/webrat/spec/integration/rails/script/performance/benchmarker +0 -3
- data/vendor/webrat/spec/integration/rails/script/performance/profiler +0 -3
- data/vendor/webrat/spec/integration/rails/script/performance/request +0 -3
- data/vendor/webrat/spec/integration/rails/script/plugin +0 -3
- data/vendor/webrat/spec/integration/rails/script/process/inspector +0 -3
- data/vendor/webrat/spec/integration/rails/script/process/reaper +0 -3
- data/vendor/webrat/spec/integration/rails/script/process/spawner +0 -3
- data/vendor/webrat/spec/integration/rails/script/runner +0 -3
- data/vendor/webrat/spec/integration/rails/script/server +0 -3
- data/vendor/webrat/spec/integration/rails/test/integration/button_click_test.rb +0 -80
- data/vendor/webrat/spec/integration/rails/test/integration/fill_in_test.rb +0 -24
- data/vendor/webrat/spec/integration/rails/test/integration/link_click_test.rb +0 -27
- data/vendor/webrat/spec/integration/rails/test/integration/webrat_test.rb +0 -97
- data/vendor/webrat/spec/integration/rails/test/test_helper.rb +0 -25
- data/vendor/webrat/spec/integration/sinatra/Rakefile +0 -5
- data/vendor/webrat/spec/integration/sinatra/classic_app.rb +0 -64
- data/vendor/webrat/spec/integration/sinatra/modular_app.rb +0 -16
- data/vendor/webrat/spec/integration/sinatra/test/classic_app_test.rb +0 -37
- data/vendor/webrat/spec/integration/sinatra/test/modular_app_test.rb +0 -18
- data/vendor/webrat/spec/integration/sinatra/test/test_helper.rb +0 -16
- data/vendor/webrat/spec/private/core/configuration_spec.rb +0 -116
- data/vendor/webrat/spec/private/core/field_spec.rb +0 -85
- data/vendor/webrat/spec/private/core/link_spec.rb +0 -24
- data/vendor/webrat/spec/private/core/logging_spec.rb +0 -10
- data/vendor/webrat/spec/private/core/session_spec.rb +0 -195
- data/vendor/webrat/spec/private/mechanize/mechanize_session_spec.rb +0 -81
- data/vendor/webrat/spec/private/merb/attaches_file_spec.rb +0 -93
- data/vendor/webrat/spec/private/merb/merb_session_spec.rb +0 -61
- data/vendor/webrat/spec/private/nokogiri_spec.rb +0 -77
- data/vendor/webrat/spec/private/rails/attaches_file_spec.rb +0 -81
- data/vendor/webrat/spec/private/rails/rails_session_spec.rb +0 -112
- data/vendor/webrat/spec/private/selenium/application_servers/rails_spec.rb +0 -26
- data/vendor/webrat/spec/public/basic_auth_spec.rb +0 -24
- data/vendor/webrat/spec/public/check_spec.rb +0 -191
- data/vendor/webrat/spec/public/choose_spec.rb +0 -118
- data/vendor/webrat/spec/public/click_area_spec.rb +0 -106
- data/vendor/webrat/spec/public/click_button_spec.rb +0 -496
- data/vendor/webrat/spec/public/click_link_spec.rb +0 -511
- data/vendor/webrat/spec/public/fill_in_spec.rb +0 -209
- data/vendor/webrat/spec/public/locators/field_by_xpath_spec.rb +0 -19
- data/vendor/webrat/spec/public/locators/field_labeled_spec.rb +0 -172
- data/vendor/webrat/spec/public/locators/field_with_id_spec.rb +0 -16
- data/vendor/webrat/spec/public/matchers/contain_spec.rb +0 -114
- data/vendor/webrat/spec/public/matchers/have_selector_spec.rb +0 -142
- data/vendor/webrat/spec/public/matchers/have_tag_spec.rb +0 -39
- data/vendor/webrat/spec/public/matchers/have_xpath_spec.rb +0 -136
- data/vendor/webrat/spec/public/reload_spec.rb +0 -10
- data/vendor/webrat/spec/public/save_and_open_spec.rb +0 -70
- data/vendor/webrat/spec/public/select_date_spec.rb +0 -112
- data/vendor/webrat/spec/public/select_datetime_spec.rb +0 -137
- data/vendor/webrat/spec/public/select_spec.rb +0 -249
- data/vendor/webrat/spec/public/select_time_spec.rb +0 -100
- data/vendor/webrat/spec/public/selenium/application_server_factory_spec.rb +0 -49
- data/vendor/webrat/spec/public/selenium/application_servers/external_spec.rb +0 -12
- data/vendor/webrat/spec/public/selenium/selenium_session_spec.rb +0 -37
- data/vendor/webrat/spec/public/set_hidden_field_spec.rb +0 -5
- data/vendor/webrat/spec/public/submit_form_spec.rb +0 -5
- data/vendor/webrat/spec/public/visit_spec.rb +0 -58
- data/vendor/webrat/spec/public/within_spec.rb +0 -177
- data/vendor/webrat/spec/rcov.opts +0 -1
- data/vendor/webrat/spec/spec.opts +0 -2
- data/vendor/webrat/spec/spec_helper.rb +0 -50
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
GEM_NAME = 'fetcher'
|
|
2
|
+
GEM_FILES = FileList['**/*'] - FileList['coverage', 'coverage/**/*', 'pkg', 'pkg/**/*']
|
|
3
|
+
GEM_SPEC = Gem::Specification.new do |s|
|
|
4
|
+
# == CONFIGURE ==
|
|
5
|
+
s.author = "Luke Francl"
|
|
6
|
+
s.email = "look@recursion.org"
|
|
7
|
+
s.homepage = "http://github.com/winton/#{GEM_NAME}"
|
|
8
|
+
s.summary = "download email from POP3 or IMAP and do stuff with it. gemified fork"
|
|
9
|
+
# == CONFIGURE ==
|
|
10
|
+
s.extra_rdoc_files = [ "README.rdoc" ]
|
|
11
|
+
s.files = GEM_FILES.to_a
|
|
12
|
+
s.has_rdoc = false
|
|
13
|
+
s.name = GEM_NAME
|
|
14
|
+
s.platform = Gem::Platform::RUBY
|
|
15
|
+
s.require_path = "lib"
|
|
16
|
+
s.version = "0.1.2"
|
|
17
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Fetcher
|
|
2
|
+
# Use factory-style initialization or insantiate directly from a subclass
|
|
3
|
+
#
|
|
4
|
+
# Options:
|
|
5
|
+
# * <tt>:type</tt> - Name of class as a symbol to instantiate
|
|
6
|
+
#
|
|
7
|
+
# Other options are the same as Fetcher::Base.new
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
#
|
|
11
|
+
# Fetcher.create(:type => :pop) is equivalent to
|
|
12
|
+
# Fetcher::Pop.new()
|
|
13
|
+
def self.create(options={})
|
|
14
|
+
options = options.dup
|
|
15
|
+
klass = options.delete(:type)
|
|
16
|
+
raise ArgumentError, 'Must supply a type' unless klass
|
|
17
|
+
module_eval "#{klass.to_s.capitalize}.new(options)"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require 'fetcher/base'
|
|
22
|
+
require 'fetcher/pop'
|
|
23
|
+
require 'fetcher/imap'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Fetcher
|
|
2
|
+
class Base
|
|
3
|
+
# Options:
|
|
4
|
+
# * <tt>:server</tt> - Server to connect to.
|
|
5
|
+
# * <tt>:username</tt> - Username to use when connecting to server.
|
|
6
|
+
# * <tt>:password</tt> - Password to use when connecting to server.
|
|
7
|
+
# * <tt>:receiver</tt> - Receiver object to pass messages to. Assumes the
|
|
8
|
+
# receiver object has a receive method that takes a message as it's argument
|
|
9
|
+
#
|
|
10
|
+
# Additional protocol-specific options implimented by sub-classes
|
|
11
|
+
#
|
|
12
|
+
# Example:
|
|
13
|
+
# Fetcher::Base.new(:server => 'mail.example.com',
|
|
14
|
+
# :username => 'pam',
|
|
15
|
+
# :password => 'test',
|
|
16
|
+
# :receiver => IncomingMailHandler)
|
|
17
|
+
def initialize(options={})
|
|
18
|
+
%w(server username password receiver).each do |opt|
|
|
19
|
+
raise ArgumentError, "#{opt} is required" unless options[opt.to_sym]
|
|
20
|
+
# convert receiver to a Class if it isn't already.
|
|
21
|
+
if opt == "receiver" && options[:receiver].is_a?(String)
|
|
22
|
+
options[:receiver] = Kernel.const_get(options[:receiver])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
instance_eval("@#{opt} = options[:#{opt}]")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Run the fetching process
|
|
30
|
+
def fetch
|
|
31
|
+
establish_connection
|
|
32
|
+
get_messages
|
|
33
|
+
close_connection
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
# Stub. Should be overridden by subclass.
|
|
39
|
+
def establish_connection #:nodoc:
|
|
40
|
+
raise NotImplementedError, "This method should be overridden by subclass"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Stub. Should be overridden by subclass.
|
|
44
|
+
def get_messages #:nodoc:
|
|
45
|
+
raise NotImplementedError, "This method should be overridden by subclass"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Stub. Should be overridden by subclass.
|
|
49
|
+
def close_connection #:nodoc:
|
|
50
|
+
raise NotImplementedError, "This method should be overridden by subclass"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Send message to receiver object
|
|
54
|
+
def process_message(message)
|
|
55
|
+
@receiver.receive(message)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Stub. Should be overridden by subclass.
|
|
59
|
+
def handle_bogus_message(message) #:nodoc:
|
|
60
|
+
raise NotImplementedError, "This method should be overridden by subclass"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../vendor/plain_imap'
|
|
2
|
+
|
|
3
|
+
module Fetcher
|
|
4
|
+
class Imap < Base
|
|
5
|
+
|
|
6
|
+
PORT = 143
|
|
7
|
+
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
# Additional Options:
|
|
11
|
+
# * <tt>:authentication</tt> - authentication type to use, defaults to PLAIN
|
|
12
|
+
# * <tt>:port</tt> - port to use (defaults to 143)
|
|
13
|
+
# * <tt>:ssl</tt> - use SSL to connect
|
|
14
|
+
# * <tt>:use_login</tt> - use LOGIN instead of AUTHENTICATE to connect (some IMAP servers, like GMail, do not support AUTHENTICATE)
|
|
15
|
+
# * <tt>:processed_folder</tt> - if set to the name of a mailbox, messages will be moved to that mailbox instead of deleted after processing. The mailbox will be created if it does not exist.
|
|
16
|
+
# * <tt>:error_folder:</tt> - the name of a mailbox where messages that cannot be processed (i.e., your receiver throws an exception) will be moved. Defaults to "bogus". The mailbox will be created if it does not exist.
|
|
17
|
+
def initialize(options={})
|
|
18
|
+
@authentication = options.delete(:authentication) || 'PLAIN'
|
|
19
|
+
@port = options.delete(:port) || PORT
|
|
20
|
+
@ssl = options.delete(:ssl)
|
|
21
|
+
@use_login = options.delete(:use_login)
|
|
22
|
+
@processed_folder = options.delete(:processed_folder)
|
|
23
|
+
@error_folder = options.delete(:error_folder) || 'bogus'
|
|
24
|
+
super(options)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Open connection and login to server
|
|
28
|
+
def establish_connection
|
|
29
|
+
@connection = Net::IMAP.new(@server, @port, @ssl)
|
|
30
|
+
if @use_login
|
|
31
|
+
@connection.login(@username, @password)
|
|
32
|
+
else
|
|
33
|
+
@connection.authenticate(@authentication, @username, @password)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Retrieve messages from server
|
|
38
|
+
def get_messages
|
|
39
|
+
@connection.select('INBOX')
|
|
40
|
+
@connection.uid_search(['ALL']).each do |uid|
|
|
41
|
+
msg = @connection.uid_fetch(uid,'RFC822').first.attr['RFC822']
|
|
42
|
+
begin
|
|
43
|
+
process_message(msg)
|
|
44
|
+
add_to_processed_folder(uid) if @processed_folder
|
|
45
|
+
rescue
|
|
46
|
+
handle_bogus_message(msg)
|
|
47
|
+
end
|
|
48
|
+
# Mark message as deleted
|
|
49
|
+
@connection.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Store the message for inspection if the receiver errors
|
|
54
|
+
def handle_bogus_message(message)
|
|
55
|
+
create_mailbox(@error_folder)
|
|
56
|
+
@connection.append(@error_folder, message)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Delete messages and log out
|
|
60
|
+
def close_connection
|
|
61
|
+
@connection.expunge
|
|
62
|
+
@connection.logout
|
|
63
|
+
@connection.disconnect
|
|
64
|
+
rescue
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def add_to_processed_folder(uid)
|
|
68
|
+
create_mailbox(@processed_folder)
|
|
69
|
+
@connection.uid_copy(uid, @processed_folder)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def create_mailbox(mailbox)
|
|
73
|
+
unless @connection.list("", mailbox)
|
|
74
|
+
@connection.create(mailbox)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../vendor/secure_pop'
|
|
2
|
+
|
|
3
|
+
module Fetcher
|
|
4
|
+
class Pop < Base
|
|
5
|
+
|
|
6
|
+
protected
|
|
7
|
+
|
|
8
|
+
# Additional Options:
|
|
9
|
+
# * <tt>:ssl</tt> - whether or not to use ssl encryption
|
|
10
|
+
# * <tt>:port</tt> - port to use (defaults to 110)
|
|
11
|
+
def initialize(options={})
|
|
12
|
+
@ssl = options.delete(:ssl)
|
|
13
|
+
@port = options.delete(:port) || Net::POP3.default_port
|
|
14
|
+
super(options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Open connection and login to server
|
|
18
|
+
def establish_connection
|
|
19
|
+
@connection = Net::POP3.new(@server, @port)
|
|
20
|
+
@connection.enable_ssl(OpenSSL::SSL::VERIFY_NONE) if @ssl
|
|
21
|
+
@connection.start(@username, @password)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Retrieve messages from server
|
|
25
|
+
def get_messages
|
|
26
|
+
unless @connection.mails.empty?
|
|
27
|
+
@connection.each_mail do |msg|
|
|
28
|
+
begin
|
|
29
|
+
process_message(msg.pop)
|
|
30
|
+
rescue
|
|
31
|
+
handle_bogus_message(msg.pop)
|
|
32
|
+
end
|
|
33
|
+
# Delete message from server
|
|
34
|
+
msg.delete
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Store the message for inspection if the receiver errors
|
|
40
|
+
def handle_bogus_message(message)
|
|
41
|
+
# This needs a good solution
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Close connection to server
|
|
45
|
+
def close_connection
|
|
46
|
+
@connection.finish
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'net/imap'
|
|
2
|
+
# add plain as an authentication type...
|
|
3
|
+
# This is taken from:
|
|
4
|
+
# http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/net/imap.rb?revision=7657&view=markup&pathrev=10966
|
|
5
|
+
|
|
6
|
+
# Authenticator for the "PLAIN" authentication type. See
|
|
7
|
+
# #authenticate().
|
|
8
|
+
class PlainAuthenticator
|
|
9
|
+
def process(data)
|
|
10
|
+
return "\0#{@user}\0#{@password}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def initialize(user, password)
|
|
16
|
+
@user = user
|
|
17
|
+
@password = password
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Net::IMAP.add_authenticator "PLAIN", PlainAuthenticator
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
require 'net/pop'
|
|
3
|
+
require 'net/protocol'
|
|
4
|
+
require 'openssl/ssl'
|
|
5
|
+
|
|
6
|
+
# Backport of ruby 1.9's POP3 SSL support
|
|
7
|
+
class Net::POP3
|
|
8
|
+
@@usessl = nil
|
|
9
|
+
@@verify = nil
|
|
10
|
+
@@certs = nil
|
|
11
|
+
PORT = 110
|
|
12
|
+
SSL_PORT = 995
|
|
13
|
+
|
|
14
|
+
def self.default_port
|
|
15
|
+
PORT
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.default_ssl_port
|
|
19
|
+
SSL_PORT
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Enable SSL for all new instances.
|
|
23
|
+
# +verify+ is the type of verification to do on the Server Cert; Defaults
|
|
24
|
+
# to OpenSSL::SSL::VERIFY_PEER.
|
|
25
|
+
# +certs+ is a file or directory holding CA certs to use to verify the
|
|
26
|
+
# server cert; Defaults to nil.
|
|
27
|
+
def self.enable_ssl( verify = OpenSSL::SSL::VERIFY_PEER, certs = nil )
|
|
28
|
+
@@usessl = true
|
|
29
|
+
@@verify = verify
|
|
30
|
+
@@certs = certs
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Disable SSL for all new instances.
|
|
34
|
+
def self.disable_ssl
|
|
35
|
+
@@usessl = nil
|
|
36
|
+
@@verify = nil
|
|
37
|
+
@@certs = nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Creates a new POP3 object.
|
|
41
|
+
# +addr+ is the hostname or ip address of your POP3 server.
|
|
42
|
+
# The optional +port+ is the port to connect to.
|
|
43
|
+
# The optional +isapop+ specifies whether this connection is going
|
|
44
|
+
# to use APOP authentication; it defaults to +false+.
|
|
45
|
+
# This method does *not* open the TCP connection.
|
|
46
|
+
def initialize(addr, port = nil, isapop = false)
|
|
47
|
+
@address = addr
|
|
48
|
+
@usessl = @@usessl
|
|
49
|
+
if @usessl
|
|
50
|
+
@port = port || SSL_PORT
|
|
51
|
+
else
|
|
52
|
+
@port = port || PORT
|
|
53
|
+
end
|
|
54
|
+
@apop = isapop
|
|
55
|
+
|
|
56
|
+
@certs = @@certs
|
|
57
|
+
@verify = @@verify
|
|
58
|
+
|
|
59
|
+
@command = nil
|
|
60
|
+
@socket = nil
|
|
61
|
+
@started = false
|
|
62
|
+
@open_timeout = 30
|
|
63
|
+
@read_timeout = 60
|
|
64
|
+
@debug_output = nil
|
|
65
|
+
|
|
66
|
+
@mails = nil
|
|
67
|
+
@n_mails = nil
|
|
68
|
+
@n_bytes = nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# does this instance use SSL?
|
|
72
|
+
def usessl?
|
|
73
|
+
@usessl
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Enables SSL for this instance. Must be called before the connection is
|
|
77
|
+
# established to have any effect.
|
|
78
|
+
# +verify+ is the type of verification to do on the Server Cert; Defaults
|
|
79
|
+
# to OpenSSL::SSL::VERIFY_PEER.
|
|
80
|
+
# +certs+ is a file or directory holding CA certs to use to verify the
|
|
81
|
+
# server cert; Defaults to nil.
|
|
82
|
+
# +port+ is port to establish the SSL conection on; Defaults to 995.
|
|
83
|
+
def enable_ssl(verify = OpenSSL::SSL::VERIFY_PEER, certs = nil,
|
|
84
|
+
port = SSL_PORT)
|
|
85
|
+
@usessl = true
|
|
86
|
+
@verify = verify
|
|
87
|
+
@certs = certs
|
|
88
|
+
@port = port
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def disable_ssl
|
|
92
|
+
@usessl = nil
|
|
93
|
+
@verify = nil
|
|
94
|
+
@certs = nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def do_start( account, password )
|
|
98
|
+
s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
|
|
99
|
+
if @usessl
|
|
100
|
+
unless defined?(OpenSSL)
|
|
101
|
+
raise "SSL extension not installed"
|
|
102
|
+
end
|
|
103
|
+
sslctx = OpenSSL::SSL::SSLContext.new
|
|
104
|
+
sslctx.verify_mode = @verify
|
|
105
|
+
sslctx.ca_file = @certs if @certs && FileTest::file?(@certs)
|
|
106
|
+
sslctx.ca_path = @certs if @certs && FileTest::directory?(@certs)
|
|
107
|
+
s = OpenSSL::SSL::SSLSocket.new(s, sslctx)
|
|
108
|
+
s.sync_close = true
|
|
109
|
+
s.connect
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
@socket = Net::InternetMessageIO.new(s)
|
|
113
|
+
on_connect
|
|
114
|
+
@command = Net::POP3Command.new(@socket)
|
|
115
|
+
if apop?
|
|
116
|
+
@command.apop account, password
|
|
117
|
+
else
|
|
118
|
+
@command.auth account, password
|
|
119
|
+
end
|
|
120
|
+
@started = true
|
|
121
|
+
ensure
|
|
122
|
+
do_finish if not @started
|
|
123
|
+
end
|
|
124
|
+
private :do_start
|
|
125
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# require File.dirname(__FILE__) + '/../../../../config/boot'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'mocha'
|
|
5
|
+
require 'fetcher'
|
|
6
|
+
|
|
7
|
+
class FetcherTest < Test::Unit::TestCase
|
|
8
|
+
|
|
9
|
+
def setup
|
|
10
|
+
@receiver = mock()
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_should_set_configuration_instance_variables
|
|
14
|
+
create_fetcher
|
|
15
|
+
assert_equal 'test.host', @fetcher.instance_variable_get(:@server)
|
|
16
|
+
assert_equal 'name', @fetcher.instance_variable_get(:@username)
|
|
17
|
+
assert_equal 'password', @fetcher.instance_variable_get(:@password)
|
|
18
|
+
assert_equal @receiver, @fetcher.instance_variable_get(:@receiver)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_should_require_subclass
|
|
22
|
+
create_fetcher
|
|
23
|
+
assert_raise(NotImplementedError) { @fetcher.fetch }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_should_require_server
|
|
27
|
+
assert_raise(ArgumentError) { create_fetcher(:server => nil) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_should_require_username
|
|
31
|
+
assert_raise(ArgumentError) { create_fetcher(:username => nil) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_should_require_password
|
|
35
|
+
assert_raise(ArgumentError) { create_fetcher(:password => nil) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_should_require_receiver
|
|
39
|
+
assert_raise(ArgumentError) { create_fetcher(:receiver => nil) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create_fetcher(options={})
|
|
43
|
+
@fetcher = Fetcher::Base.new({:server => 'test.host', :username => 'name', :password => 'password', :receiver => @receiver}.merge(options))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class FactoryFetcherTest < Test::Unit::TestCase
|
|
49
|
+
|
|
50
|
+
def setup
|
|
51
|
+
@receiver = mock()
|
|
52
|
+
@pop_fetcher = Fetcher.create(:type => :pop, :server => 'test.host',
|
|
53
|
+
:username => 'name',
|
|
54
|
+
:password => 'password',
|
|
55
|
+
:receiver => @receiver)
|
|
56
|
+
|
|
57
|
+
@imap_fetcher = Fetcher.create(:type => :imap, :server => 'test.host',
|
|
58
|
+
:username => 'name',
|
|
59
|
+
:password => 'password',
|
|
60
|
+
:receiver => @receiver)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_should_be_sublcass
|
|
64
|
+
assert_equal Fetcher::Pop, @pop_fetcher.class
|
|
65
|
+
assert_equal Fetcher::Imap, @imap_fetcher.class
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_should_require_type
|
|
69
|
+
assert_raise(ArgumentError) { Fetcher.create({}) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Write tests for sub-classes
|