unfuddle_my_email 0.1.3

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.
@@ -0,0 +1,29 @@
1
+ require 'yaml'
2
+
3
+ module UnfuddleMyEmail
4
+ # Configuration loads the given +path+ as a YAML file and enables
5
+ # method-like access to configuration information.
6
+ #
7
+ # The expected format of the YAML file is:
8
+ #
9
+ # configuration_key: configuration_value
10
+ # configuration_second_key: configuration_value
11
+ #
12
+ # etc.
13
+ #
14
+ # Example usage:
15
+ #
16
+ # configuration = Configuration.new("path/to/yaml.yml")
17
+ # configuration.key # => value
18
+ class Configuration
19
+ attr_accessor :settings
20
+
21
+ def initialize(path)
22
+ @settings = YAML.load_file(path)
23
+ end
24
+
25
+ def method_missing(method_symbol, *args)
26
+ @settings[method_symbol.to_s]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'builder'
2
+
3
+ module UnfuddleMyEmail
4
+ # Create an XML formatted ticket.
5
+ #
6
+ # Expects an object that responds to the following methods:
7
+ #
8
+ # * +subject+: The summary for the ticket
9
+ # * +from+: An array of authors
10
+ # * +body+: Will be added the the ticket description
11
+ class EmailTicket
12
+ attr_accessor :message
13
+
14
+ def initialize(message)
15
+ @message = message
16
+ end
17
+
18
+
19
+ # Returns an XML representation of an Unfuddle ticket.
20
+ def to_xml
21
+ builder = Builder::XmlMarkup.new
22
+ return xml = builder.ticket { |ticket|
23
+ ticket.priority "1"
24
+ ticket.summary subject
25
+ ticket.description description
26
+ }
27
+ end
28
+
29
+ private
30
+
31
+ def subject
32
+ @message.subject
33
+ end
34
+
35
+ def description
36
+ "From: #{from}\n\n#{body}"
37
+ end
38
+
39
+ def from
40
+ @message.from.join(',')
41
+ end
42
+
43
+ def body
44
+ @message.body
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ require 'net/pop3_ssl'
2
+ require 'tmail'
3
+
4
+ module UnfuddleMyEmail
5
+ # Fetcher iterates through all emails in the given POP3 mailbox and
6
+ # yields each one, optionally deleting the message after yield. The
7
+ # message yielded is an instance of TMail::Mail.
8
+ #
9
+ # Example:
10
+ #
11
+ # fetch = Fetcher.new('pop.example.com',995,true,'username','password',false)
12
+ # fetcher.each do |message|
13
+ # puts message.subject
14
+ # end
15
+ #
16
+ # # Enumerable is included so you can use those features (except for sort,min,max) as well:
17
+ # fetcher.to_a # => [#<TMail::Mail instance>]
18
+ class Fetcher
19
+ def initialize(server, port, ssl, username, password, delete=false)
20
+ @pop3_server = server
21
+ @pop3_port = port
22
+ @pop3_ssl = ssl
23
+ @pop3_username = username
24
+ @pop3_password = password
25
+ @pop3_delete = delete
26
+ end
27
+
28
+ def each
29
+ if @pop3_ssl
30
+ Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
31
+ end
32
+ Net::POP3.start(@pop3_server, @pop3_port, @pop3_username, @pop3_password) do |pop|
33
+ pop.each_mail { |message|
34
+ mail_item = TMail::Mail.parse(message.pop)
35
+ yield mail_item
36
+ message.delete if @pop3_delete
37
+ }
38
+ end
39
+ end
40
+ include Enumerable
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+ require 'net/https'
2
+
3
+ module UnfuddleMyEmail
4
+ class Poster
5
+ # Return a new Net::HTTP session for the given +domain+. Optionally,
6
+ # enable +ssl+.
7
+ def self.http(domain, ssl = false)
8
+ http = Net::HTTP.new(domain, ssl ? 443 : 80)
9
+ if ssl
10
+ http.use_ssl = true
11
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
12
+ end
13
+ return http
14
+ end
15
+
16
+ # Post XML content with basic authentication.
17
+ #
18
+ # Arguments:
19
+ # * +domain+: The domain name to use
20
+ # * +uri+: The url minuse the domain
21
+ # * +ssl+: Set true to enable SSL.
22
+ # * +username+: The username to use for Basic Auth.
23
+ # * +password+: The password to use for Basic Auth.
24
+ # * +content+: The content to POST via HTTP.
25
+ #
26
+ # Example:
27
+ #
28
+ # Poster::post('example.com','/tickets',false,'john','doe','<data>value</data>')
29
+ #
30
+ # Raises error on anything but success or redirect.
31
+ def self.post(domain, uri, ssl, username, password, content)
32
+ request = Net::HTTP::Post.new(uri, {'Content-type' => 'application/xml'})
33
+ request.basic_auth username, password
34
+ request.body = content
35
+ response = http(domain, ssl).request(request)
36
+ case response
37
+ when Net::HTTPSuccess, Net::HTTPRedirection
38
+ return true
39
+ else
40
+ response.error!
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ module UnfuddleMyEmail
2
+ class Runner
3
+ def initialize(configuration_path)
4
+ @options = Configuration.new(configuration_path)
5
+ end
6
+
7
+ def run
8
+ fetcher = Fetcher.new(@options.pop3_server, @options.pop3_port, @options.pop3_ssl, @options.pop3_username, @options.pop3_password, @options.pop3_delete)
9
+ fetcher.each do |message|
10
+ ticket = EmailTicket.new(message)
11
+ p "Posting ticket: #{ticket.message.subject}"
12
+ Poster::post(domain, url, @options.unfuddle_ssl, @options.unfuddle_username, @options.unfuddle_password, ticket.to_xml)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def domain
19
+ "#{@options.unfuddle_subdomain}.unfuddle.com"
20
+ end
21
+
22
+ def url
23
+ "#{@options.unfuddle_api_url}/projects/#{@options.unfuddle_project_id}/tickets"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'unfuddle_my_email/configuration'
2
+ require 'unfuddle_my_email/email_ticket'
3
+ require 'unfuddle_my_email/fetcher'
4
+ require 'unfuddle_my_email/poster'
5
+ require 'unfuddle_my_email/runner'
6
+
7
+ module UnfuddleMyEmail
8
+
9
+ end
@@ -0,0 +1,29 @@
1
+ require 'shoulda'
2
+ require 'test/unit'
3
+ require 'unfuddle_my_email'
4
+
5
+ class ConfigurationTest < Test::Unit::TestCase
6
+ include UnfuddleMyEmail
7
+
8
+ context "a Configuration instance" do
9
+ setup do
10
+ @configuration = Configuration.new("test/test_configuration.yml")
11
+ end
12
+
13
+ should "assign Hash from configuration to settings accessor" do
14
+ assert @configuration.settings.is_a?(Hash)
15
+ end
16
+
17
+ context "for each key in configuration.yml file" do
18
+ setup do
19
+ @data = YAML.load_file("test/test_configuration.yml")
20
+ end
21
+
22
+ should "return value for key when called as a method" do
23
+ @data.each_pair do |key,value|
24
+ assert_equal value, @configuration.send(key)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ require 'flexmock/test_unit'
2
+ require 'shoulda'
3
+ require 'test/unit'
4
+ require 'unfuddle_my_email'
5
+
6
+ class EmailTicketTest < Test::Unit::TestCase
7
+ include UnfuddleMyEmail
8
+
9
+ context "a EmailTicket instance" do
10
+ setup do
11
+ message = flexmock('message',
12
+ :subject => 'Hello, world',
13
+ :from => ['Matt Haley <matt@example.com>'],
14
+ :body => 'Message body.')
15
+ @email_ticket = EmailTicket.new(message)
16
+ end
17
+
18
+ should "assign a message" do
19
+ assert @email_ticket.message = "a message"
20
+ end
21
+
22
+ should "return xml" do
23
+ assert_equal "<ticket><priority>1</priority><summary>Hello, world</summary><description>From: Matt Haley &lt;matt@example.com&gt;\n\nMessage body.</description></ticket>",
24
+ @email_ticket.to_xml
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ require 'flexmock/test_unit'
2
+ require 'net/pop3_ssl'
3
+ require 'shoulda'
4
+ require 'test/unit'
5
+ require 'tmail'
6
+ require 'unfuddle_my_email'
7
+
8
+ class FetcherTest < Test::Unit::TestCase
9
+ include UnfuddleMyEmail
10
+
11
+ context "a Fetcher instance" do
12
+ setup do
13
+ @fetcher = Fetcher.new('pop.example.com', 110, false, 'user', 'password')
14
+
15
+ @message = flexmock('message', :test => true)
16
+ @message.should_receive(:pop).and_return(
17
+ "From: john@example.com\n" +
18
+ "Subject: Test subject\n\n" +
19
+ "This is a test.\n.\n"
20
+ )
21
+
22
+ @pop3_int = flexmock('pop3_int')
23
+ @pop3_int.should_receive(:each_mail).and_yield(@message)
24
+
25
+ @pop3_lib = flexmock(Net::POP3)
26
+ @pop3_lib.should_receive(:start).and_yield(@pop3_int)
27
+
28
+ @tmail_lib = flexmock(TMail::Mail)
29
+ @tmail_lib.should_receive(:parse).and_return(@message)
30
+ end
31
+
32
+ should "yield each message" do
33
+ success = false
34
+ @fetcher.each do |message|
35
+ success = message.test
36
+ end
37
+ assert success
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,38 @@
1
+ require 'net/http'
2
+ require 'unfuddle_my_email'
3
+ require 'test/unit'
4
+ require 'flexmock/test_unit'
5
+ require 'shoulda'
6
+
7
+ class PosterTest < Test::Unit::TestCase
8
+ include UnfuddleMyEmail
9
+
10
+ context "a Poster class" do
11
+ should "return a Net::HTTP instance when http called" do
12
+ http = Poster.http('example.com')
13
+ assert http.is_a?(Net::HTTP)
14
+ end
15
+
16
+ should "set SSL mode" do
17
+ http = Poster.http('example.com', ssl = true)
18
+ assert http.use_ssl?
19
+ end
20
+
21
+ should "post content" do
22
+ post_i = flexmock('post_i')
23
+ post_i.should_receive(:basic_auth).with(String, String)
24
+ post_i.should_receive(:body=).with(String)
25
+ post = flexmock('post')
26
+ post.should_receive(:new).with(String).and_return(post_i)
27
+
28
+ http_request = flexmock('request')
29
+ http_request.should_receive(:request).and_return(Net::HTTPSuccess.new('','',''))
30
+
31
+ http_lib = flexmock(Net::HTTP)
32
+ http_lib.should_receive(:new).and_return(http_request)
33
+ http_lib.should_receive(:post).and_return(post)
34
+
35
+ assert Poster.post('example.com','/', false, 'user','password','test content')
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ unfuddle_subdomain: 'mysubdomain'
2
+ unfuddle_username: 'username'
3
+ unfuddle_password: 'password'
4
+ unfuddle_ssl: true
5
+ unfuddle_project_id: 1234
6
+ unfuddle_api_url: '/api/v1/'
7
+ pop3_server: 'pop.example.com'
8
+ pop3_port: 110
9
+ pop3_username: 'username'
10
+ pop3_password: 'password'
11
+ pop3_delete: false
12
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unfuddle_my_email
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Matt Haley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-25 00:00:00 -07:00
13
+ default_executable: unfuddle_my_email
14
+ dependencies: []
15
+
16
+ description: Post emails from POP server as Unfuddle Tickets.
17
+ email: matt@smajn.net
18
+ executables:
19
+ - unfuddle_my_email
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - LICENSE
27
+ - VERSION.yml
28
+ - bin/unfuddle_my_email
29
+ - configuration-sample.yml
30
+ - lib/net/pop3_ssl.rb
31
+ - lib/unfuddle_my_email.rb
32
+ - lib/unfuddle_my_email/configuration.rb
33
+ - lib/unfuddle_my_email/email_ticket.rb
34
+ - lib/unfuddle_my_email/fetcher.rb
35
+ - lib/unfuddle_my_email/poster.rb
36
+ - lib/unfuddle_my_email/runner.rb
37
+ - test/configuration_test.rb
38
+ - test/email_ticket_test.rb
39
+ - test/fetcher_test.rb
40
+ - test/poster_test.rb
41
+ - test/test_configuration.yml
42
+ - README.rdoc
43
+ has_rdoc: true
44
+ homepage: http://github.com/smajn/unfuddle_my_email
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project: mhaley
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Post emails from POP server as Unfuddle Tickets.
71
+ test_files:
72
+ - test/poster_test.rb
73
+ - test/configuration_test.rb
74
+ - test/fetcher_test.rb
75
+ - test/email_ticket_test.rb