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 +2 -0
- data/README.markdown +19 -3
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/gmail_xoauth.rb +2 -0
- data/lib/gmail_xoauth/imap_xoauth_authenticator.rb +8 -44
- data/lib/gmail_xoauth/oauth_string.rb +51 -0
- data/lib/gmail_xoauth/smtp_xoauth_authenticator.rb +28 -0
- data/test/helper.rb +1 -1
- data/test/test_oauth_string.rb +54 -0
- data/test/test_smtp_xoauth_authenticator.rb +39 -0
- metadata +20 -2
data/.gitignore
CHANGED
data/README.markdown
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
#
|
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
|
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
|
-
|
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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/gmail_xoauth.rb
CHANGED
@@ -3,58 +3,22 @@ require 'oauth'
|
|
3
3
|
|
4
4
|
module GmailXoauth
|
5
5
|
class ImapXoauthAuthenticator
|
6
|
-
|
6
|
+
|
7
7
|
def process(data)
|
8
|
-
|
8
|
+
build_sasl_client_request(@request_url, @oauth_string)
|
9
9
|
end
|
10
|
-
|
11
|
-
|
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
|
-
|
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
@@ -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
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
version: 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
|