gmail_xoauth 0.1.0 → 0.2.0

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/.gitignore CHANGED
@@ -17,6 +17,8 @@ tmtags
17
17
  coverage
18
18
  rdoc
19
19
  pkg
20
+ *.gemspec
21
+ *.gem
20
22
 
21
23
  ## PROJECT::SPECIFIC
22
24
  test/valid_credentials.yml
data/README.markdown CHANGED
@@ -1,10 +1,12 @@
1
- # gmail-xoauth
1
+ # gmail_xoauth
2
2
 
3
3
  Get access to [Gmail IMAP and STMP via OAuth](http://code.google.com/apis/gmail/oauth), using the standard Ruby Net libraries.
4
4
 
5
+ The gem only supports 3-legged OAuth. If you need [2-legged OAuth feel](http://code.google.com/apis/accounts/docs/OAuth.html) free to fork!
6
+
5
7
  ## Install
6
8
 
7
- $ gem install gmail-xoauth
9
+ $ gem install gmail_xoauth
8
10
 
9
11
  ## Usage
10
12
 
@@ -33,7 +35,21 @@ Note that the [Net::IMAP#login](http://www.ruby-doc.org/core/classes/Net/IMAP.ht
33
35
 
34
36
  ### SMTP
35
37
 
36
- [wip]
38
+ For your tests, Gmail allows to set 'anonymous' as the consumer key and secret.
39
+
40
+ require 'gmail_xoauth'
41
+ smtp = Net::SMTP.new('smtp.gmail.com', 587)
42
+ smtp.enable_starttls_auto
43
+ secret = {
44
+ :consumer_key => 'anonymous',
45
+ :consumer_secret => 'anonymous',
46
+ :token => '4/nM2QAaunKUINb4RrXPC55F-mix_k',
47
+ :token_secret => '41r18IyXjIvuyabS/NDyW6+m'
48
+ }
49
+ smtp.start('gmail.com', 'myemail@gmail.com', secret, :xoauth)
50
+ smtp.finish
51
+
52
+ Note that +Net::SMTP#enable_starttls_auto+ is not defined in Ruby 1.8.6.
37
53
 
38
54
  ## Compatibility
39
55
 
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ begin
11
11
  gem.homepage = "http://github.com/nfo/gmail_xoauth"
12
12
  gem.authors = ["Nicolas Fouch\303\251"]
13
13
  gem.add_dependency "oauth", ">= 0.3.6"
14
+ gem.add_development_dependency "shoulda", ">= 0"
14
15
  end
15
16
  Jeweler::GemcutterTasks.new
16
17
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/lib/gmail_xoauth.rb CHANGED
@@ -1 +1,3 @@
1
+ require 'gmail_xoauth/oauth_string'
1
2
  require 'gmail_xoauth/imap_xoauth_authenticator'
3
+ require 'gmail_xoauth/smtp_xoauth_authenticator'
@@ -3,58 +3,22 @@ require 'oauth'
3
3
 
4
4
  module GmailXoauth
5
5
  class ImapXoauthAuthenticator
6
-
6
+
7
7
  def process(data)
8
- 'GET ' + @request_url + ' ' + @oauth_string
8
+ build_sasl_client_request(@request_url, @oauth_string)
9
9
  end
10
-
11
- private
12
-
10
+
11
+ private
12
+
13
13
  # +user+ is an email address: roger@gmail.com
14
14
  # +password+ is a hash of oauth parameters, see +build_oauth_string+
15
15
  def initialize(user, password)
16
16
  @request_url = "https://mail.google.com/mail/b/#{user}/imap/"
17
17
  @oauth_string = build_oauth_string(@request_url, password)
18
18
  end
19
-
20
- #
21
- # Builds the "oauth protocol parameter string". See http://code.google.com/apis/gmail/oauth/protocol.html#sasl
22
- #
23
- # +request_url+ https://mail.google.com/mail/b/user_name@gmail.com/imap/
24
- # +oauth_params+ contains the following keys:
25
- # * :consumer_key (default 'anonymous')
26
- # * :consumer_secret (default 'anonymous')
27
- # * :token (mandatory)
28
- # * :token_secret (mandatory)
29
- def build_oauth_string(request_url, oauth_params = {})
30
- oauth_params[:consumer_key] ||= 'anonymous'
31
- oauth_params[:consumer_secret] ||= 'anonymous'
32
-
33
- oauth_request_params = {
34
- "oauth_consumer_key" => oauth_params[:consumer_key],
35
- 'oauth_nonce' => OAuth::Helper.generate_key,
36
- "oauth_signature_method" => 'HMAC-SHA1',
37
- 'oauth_timestamp' => OAuth::Helper.generate_timestamp,
38
- "oauth_token" => oauth_params[:token],
39
- 'oauth_version' => '1.0'
40
- }
41
-
42
- request = OAuth::RequestProxy.proxy(
43
- 'method' => 'GET',
44
- 'uri' => request_url,
45
- 'parameters' => oauth_request_params
46
- )
47
-
48
- oauth_request_params['oauth_signature'] =
49
- OAuth::Signature.sign(
50
- request,
51
- :consumer_secret => oauth_params[:consumer_secret],
52
- :token_secret => oauth_params[:token_secret]
53
- )
54
-
55
- # Inspired from oauth_header OAuth::RequestProxy::Base#oauth_header
56
- oauth_request_params.map { |k,v| "#{k}=\"#{OAuth::Helper.escape(v)}\"" }.sort.join(',')
57
- end
19
+
20
+ include OauthString
21
+
58
22
  end
59
23
  end
60
24
 
@@ -0,0 +1,51 @@
1
+ module GmailXoauth
2
+ module OauthString
3
+
4
+ private
5
+
6
+ #
7
+ # Builds the "oauth protocol parameter string". See http://code.google.com/apis/gmail/oauth/protocol.html#sasl
8
+ #
9
+ # +request_url+ https://mail.google.com/mail/b/user_name@gmail.com/{imap|smtp}/
10
+ # +oauth_params+ contains the following keys:
11
+ # * :consumer_key (default 'anonymous')
12
+ # * :consumer_secret (default 'anonymous')
13
+ # * :token (mandatory)
14
+ # * :token_secret (mandatory)
15
+ def build_oauth_string(request_url, oauth_params = {})
16
+ oauth_params[:consumer_key] ||= 'anonymous'
17
+ oauth_params[:consumer_secret] ||= 'anonymous'
18
+
19
+ oauth_request_params = {
20
+ "oauth_consumer_key" => oauth_params[:consumer_key],
21
+ 'oauth_nonce' => OAuth::Helper.generate_key,
22
+ "oauth_signature_method" => 'HMAC-SHA1',
23
+ 'oauth_timestamp' => OAuth::Helper.generate_timestamp,
24
+ "oauth_token" => oauth_params[:token],
25
+ 'oauth_version' => '1.0'
26
+ }
27
+
28
+ request = OAuth::RequestProxy.proxy(
29
+ 'method' => 'GET',
30
+ 'uri' => request_url,
31
+ 'parameters' => oauth_request_params
32
+ )
33
+
34
+ oauth_request_params['oauth_signature'] =
35
+ OAuth::Signature.sign(
36
+ request,
37
+ :consumer_secret => oauth_params[:consumer_secret],
38
+ :token_secret => oauth_params[:token_secret]
39
+ )
40
+
41
+ # Inspired from OAuth::RequestProxy::Base#oauth_header
42
+ oauth_request_params.map { |k,v| "#{k}=\"#{OAuth::Helper.escape(v)}\"" }.sort.join(',')
43
+ end
44
+
45
+ # See http://code.google.com/apis/gmail/oauth/protocol.html#sasl
46
+ def build_sasl_client_request(request_url, oauth_string)
47
+ 'GET ' + request_url + ' ' + oauth_string
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'net/smtp'
2
+ require 'oauth'
3
+
4
+ module GmailXoauth
5
+ module SmtpXoauthAuthenticator
6
+
7
+ def auth_xoauth(user, secret)
8
+ check_auth_args user, secret
9
+
10
+ request_url = "https://mail.google.com/mail/b/#{user}/smtp/"
11
+ oauth_string = build_oauth_string(request_url, secret)
12
+ sasl_client_request = build_sasl_client_request(request_url, oauth_string)
13
+
14
+ res = critical {
15
+ get_response("AUTH XOAUTH #{base64_encode(sasl_client_request)}")
16
+ }
17
+
18
+ check_auth_response res
19
+ res
20
+ end
21
+
22
+ include OauthString
23
+
24
+ end
25
+ end
26
+
27
+ # Not pretty, right ?
28
+ Net::SMTP.__send__('include', GmailXoauth::SmtpXoauthAuthenticator)
data/test/helper.rb CHANGED
@@ -2,7 +2,7 @@ require 'yaml'
2
2
 
3
3
  require 'rubygems'
4
4
  require 'test/unit'
5
- # require 'pony'
5
+ require 'mocha'
6
6
 
7
7
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
8
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -0,0 +1,54 @@
1
+ require 'helper'
2
+
3
+ class TestOauthString < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_build_oauth_string_should_accept_custom_consumer
9
+ OAuth::Helper.stubs(:generate_key).returns('abc')
10
+ OAuth::Helper.stubs(:generate_timestamp).returns(1274215474)
11
+
12
+ request_url = "https://mail.google.com/mail/b/user_name@gmail.com/imap/"
13
+ oauth_params = {
14
+ :consumer_key => 'c',
15
+ :consumer_secret => 'd',
16
+ :token => 'a',
17
+ :token_secret => 'b',
18
+ }
19
+
20
+ oauth_string = C.new.__send__('build_oauth_string', request_url, oauth_params)
21
+
22
+ assert_equal(
23
+ 'oauth_consumer_key="c",oauth_nonce="abc",oauth_signature="eseW9YybDf3fPToiwyLdUwSlfUw%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1274215474",oauth_token="a",oauth_version="1.0"',
24
+ oauth_string
25
+ )
26
+ end
27
+
28
+ def test_build_oauth_string_should_set_consumer_anonymous_by_default
29
+ OAuth::Helper.stubs(:generate_key).returns('abc')
30
+ OAuth::Helper.stubs(:generate_timestamp).returns(1274215474)
31
+
32
+ request_url = "https://mail.google.com/mail/b/user_name@gmail.com/imap/"
33
+ oauth_params = {
34
+ :token => 'a',
35
+ :token_secret => 'b',
36
+ }
37
+
38
+ oauth_string = C.new.__send__('build_oauth_string', request_url, oauth_params)
39
+
40
+ assert_equal(
41
+ 'oauth_consumer_key="anonymous",oauth_nonce="abc",oauth_signature="weu3Z%2Baqn6YUNnSLJmIvUwnCEmo%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1274215474",oauth_token="a",oauth_version="1.0"',
42
+ oauth_string
43
+ )
44
+ end
45
+
46
+ def test_build_sasl_client_request
47
+ assert_equal 'GET 1 2', C.new.__send__('build_sasl_client_request', '1', '2')
48
+ end
49
+
50
+ end
51
+
52
+ class C
53
+ include GmailXoauth::OauthString
54
+ end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ class TestSmtpXoauthAuthenticator < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_smtp_authenticator_is_enabled
9
+ assert Net::SMTP.new(nil).respond_to?(:auth_xoauth), 'The Net::SMTP class should define the method :auth_xoauth'
10
+ end
11
+
12
+ def test_authenticate_with_invalid_credentials
13
+ smtp = Net::SMTP.new('smtp.gmail.com', 587)
14
+ smtp.enable_starttls_auto
15
+ assert_raise(Net::SMTPAuthenticationError) do
16
+ smtp.start('gmail.com', 'roger@moore.com', {:token => 'a', :token_secret => 'b'}, :xoauth)
17
+ end
18
+ end
19
+
20
+ def test_authenticate_with_valid_credentials
21
+ return unless VALID_CREDENTIALS
22
+
23
+ smtp = Net::SMTP.new('smtp.gmail.com', 587)
24
+ smtp.enable_starttls_auto
25
+
26
+ secret = {
27
+ :consumer_key => VALID_CREDENTIALS[:consumer_key],
28
+ :consumer_secret => VALID_CREDENTIALS[:consumer_secret],
29
+ :token => VALID_CREDENTIALS[:token],
30
+ :token_secret => VALID_CREDENTIALS[:token_secret],
31
+ }
32
+
33
+ assert_nothing_raised do
34
+ smtp.start('gmail.com', VALID_CREDENTIALS[:email], secret, :xoauth)
35
+ end
36
+ ensure
37
+ smtp.finish if smtp
38
+ end
39
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Nicolas Fouch\xC3\xA9"
@@ -31,6 +31,18 @@ dependencies:
31
31
  version: 0.3.6
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: shoulda
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
34
46
  description: Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Net libraries
35
47
  email: nicolas@silentale.com
36
48
  executables: []
@@ -48,8 +60,12 @@ files:
48
60
  - VERSION
49
61
  - lib/gmail_xoauth.rb
50
62
  - lib/gmail_xoauth/imap_xoauth_authenticator.rb
63
+ - lib/gmail_xoauth/oauth_string.rb
64
+ - lib/gmail_xoauth/smtp_xoauth_authenticator.rb
51
65
  - test/helper.rb
52
66
  - test/test_imap_xoauth_authenticator.rb
67
+ - test/test_oauth_string.rb
68
+ - test/test_smtp_xoauth_authenticator.rb
53
69
  has_rdoc: true
54
70
  homepage: http://github.com/nfo/gmail_xoauth
55
71
  licenses: []
@@ -83,3 +99,5 @@ summary: Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Ne
83
99
  test_files:
84
100
  - test/helper.rb
85
101
  - test/test_imap_xoauth_authenticator.rb
102
+ - test/test_oauth_string.rb
103
+ - test/test_smtp_xoauth_authenticator.rb