unfuddle_my_email 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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