gmail_xoauth 0.1.0 → 0.2.0

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