gmail_xoauth 0.1.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 +22 -0
- data/LICENSE +14 -0
- data/README.markdown +56 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/gmail_xoauth.rb +1 -0
- data/lib/gmail_xoauth/imap_xoauth_authenticator.rb +61 -0
- data/test/helper.rb +44 -0
- data/test/test_imap_xoauth_authenticator.rb +40 -0
- metadata +85 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Author: Nicolas Fouché <nicolas@silentale.com>
|
2
|
+
Copyright: (C) 2010 Silentale SAS
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
data/README.markdown
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# gmail-xoauth
|
2
|
+
|
3
|
+
Get access to [Gmail IMAP and STMP via OAuth](http://code.google.com/apis/gmail/oauth), using the standard Ruby Net libraries.
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
$ gem install gmail-xoauth
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
### Get your OAuth tokens
|
12
|
+
|
13
|
+
For testing, you can generate and validate your OAuth tokens thanks to the awesome [xoauth.py tool](http://code.google.com/p/google-mail-xoauth-tools/wiki/XoauthDotPyRunThrough).
|
14
|
+
|
15
|
+
$ python xoauth.py --generate_oauth_token --user=myemail@gmail.com
|
16
|
+
|
17
|
+
### IMAP
|
18
|
+
|
19
|
+
For your tests, Gmail allows to set 'anonymous' as the consumer key and secret.
|
20
|
+
|
21
|
+
require 'gmail_xoauth'
|
22
|
+
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
|
23
|
+
imap.authenticate('XOAUTH', 'myemail@gmail.com',
|
24
|
+
:consumer_key => 'anonymous',
|
25
|
+
:consumer_secret => 'anonymous',
|
26
|
+
:token => '4/nM2QAaunKUINb4RrXPC55F-mix_k',
|
27
|
+
:token_secret => '41r18IyXjIvuyabS/NDyW6+m'
|
28
|
+
)
|
29
|
+
messages_count = imap.status('INBOX', ['MESSAGES'])['MESSAGES']
|
30
|
+
puts "Seeing #{messages_count} messages in INBOX"
|
31
|
+
|
32
|
+
Note that the [Net::IMAP#login](http://www.ruby-doc.org/core/classes/Net/IMAP.html#M004191) method does not use support custom authenticators, so you have to use the [Net::IMAP#authenticate](http://www.ruby-doc.org/core/classes/Net/IMAP.html#M004190) method.
|
33
|
+
|
34
|
+
### SMTP
|
35
|
+
|
36
|
+
[wip]
|
37
|
+
|
38
|
+
## Compatibility
|
39
|
+
|
40
|
+
Tested on Ruby MRI 1.8.6, 1.8.7 and 1.9.1. Feel free to send me a message if you tested this code with other implementations of Ruby.
|
41
|
+
|
42
|
+
The only external dependency is the [oauth gem](http://rubygems.org/gems/oauth).
|
43
|
+
|
44
|
+
## Note on Patches/Pull Requests
|
45
|
+
|
46
|
+
* Fork the project.
|
47
|
+
* Make your feature addition or bug fix.
|
48
|
+
* Add tests for it. This is important so I don't break it in a
|
49
|
+
future version unintentionally.
|
50
|
+
* Commit, do not mess with rakefile, version, or history.
|
51
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
52
|
+
* Send me a pull request. Bonus points for topic branches.
|
53
|
+
|
54
|
+
## Copyright
|
55
|
+
|
56
|
+
Copyright (c) 2010 Silentale SAS. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "gmail_xoauth"
|
8
|
+
gem.summary = %Q{Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Net libraries}
|
9
|
+
gem.description = %Q{Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Net libraries}
|
10
|
+
gem.email = "nicolas@silentale.com"
|
11
|
+
gem.homepage = "http://github.com/nfo/gmail_xoauth"
|
12
|
+
gem.authors = ["Nicolas Fouch\303\251"]
|
13
|
+
gem.add_dependency "oauth", ">= 0.3.6"
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "gmail_xoauth #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/gmail_xoauth.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'gmail_xoauth/imap_xoauth_authenticator'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'net/imap'
|
2
|
+
require 'oauth'
|
3
|
+
|
4
|
+
module GmailXoauth
|
5
|
+
class ImapXoauthAuthenticator
|
6
|
+
|
7
|
+
def process(data)
|
8
|
+
'GET ' + @request_url + ' ' + @oauth_string
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# +user+ is an email address: roger@gmail.com
|
14
|
+
# +password+ is a hash of oauth parameters, see +build_oauth_string+
|
15
|
+
def initialize(user, password)
|
16
|
+
@request_url = "https://mail.google.com/mail/b/#{user}/imap/"
|
17
|
+
@oauth_string = build_oauth_string(@request_url, password)
|
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
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Net::IMAP.add_authenticator('XOAUTH', GmailXoauth::ImapXoauthAuthenticator)
|
data/test/helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
# require 'pony'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
require 'gmail_xoauth'
|
10
|
+
|
11
|
+
# Wanna debug ? Activate the IMAP debug mode, it will show the client/server conversation
|
12
|
+
# Net::IMAP.debug = true
|
13
|
+
|
14
|
+
# SMTP debugging can only be enabled on Net::SMTP instances
|
15
|
+
# Net::SMTP.class_eval do
|
16
|
+
# def initialize_with_debug(*args)
|
17
|
+
# initialize_without_debug(*args)
|
18
|
+
# @debug_output = STDERR
|
19
|
+
# end
|
20
|
+
# alias_method :initialize_without_debug, :initialize
|
21
|
+
# alias_method :initialize, :initialize_with_debug
|
22
|
+
# end
|
23
|
+
|
24
|
+
VALID_CREDENTIALS = begin
|
25
|
+
YAML.load_file(File.join(File.dirname(__FILE__), 'valid_credentials.yml'))
|
26
|
+
rescue Errno::ENOENT
|
27
|
+
STDERR.puts %(
|
28
|
+
Warning: some tests are disabled because they require valid credentials. To enable them, create a file \"test/valid_credentials.yml\".
|
29
|
+
It should contain valid OAuth tokens. Valid tokens can be generated thanks to \"xoauth.py\":http://code.google.com/p/google-mail-xoauth-tools/.
|
30
|
+
Of course, this file is .gitignored. Template:
|
31
|
+
|
32
|
+
---
|
33
|
+
:email: someuser@gmail.com
|
34
|
+
:consumer_key: anonymous # "anonymous" is a valid value for testing
|
35
|
+
:consumer_secret: anonymous # "anonymous" is a valid value for testing
|
36
|
+
:token: 1/nE2xBCDOU0429bTeJySE11kRE95qzKQNlfTaaBcDeFg
|
37
|
+
:token_secret: 123Z/bMsi9fFhN6qHFWOabcd
|
38
|
+
|
39
|
+
)
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
class Test::Unit::TestCase
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestImapXoauthAuthenticator < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_xoauth_authenticator_is_enabled
|
9
|
+
authenticators = Net::IMAP.__send__('class_variable_get', '@@authenticators')
|
10
|
+
assert_not_nil authenticators['XOAUTH']
|
11
|
+
assert_equal authenticators['XOAUTH'], GmailXoauth::ImapXoauthAuthenticator
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_authenticate_with_invalid_credentials
|
15
|
+
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
|
16
|
+
assert_raise(Net::IMAP::NoResponseError) do
|
17
|
+
imap.authenticate('XOAUTH', 'roger@moore.com',
|
18
|
+
:token => 'a',
|
19
|
+
:token_secret => 'b'
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_authenticate_with_valid_credentials
|
25
|
+
return unless VALID_CREDENTIALS
|
26
|
+
|
27
|
+
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
|
28
|
+
imap.authenticate('XOAUTH', VALID_CREDENTIALS[:email],
|
29
|
+
:consumer_key => VALID_CREDENTIALS[:consumer_key],
|
30
|
+
:consumer_secret => VALID_CREDENTIALS[:consumer_secret],
|
31
|
+
:token => VALID_CREDENTIALS[:token],
|
32
|
+
:token_secret => VALID_CREDENTIALS[:token_secret]
|
33
|
+
)
|
34
|
+
mailboxes = imap.list('', '*')
|
35
|
+
assert_instance_of Array, mailboxes
|
36
|
+
assert_instance_of Net::IMAP::MailboxList, mailboxes.first
|
37
|
+
ensure
|
38
|
+
imap.disconnect if imap
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gmail_xoauth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- "Nicolas Fouch\xC3\xA9"
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-18 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: oauth
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 3
|
30
|
+
- 6
|
31
|
+
version: 0.3.6
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Net libraries
|
35
|
+
email: nicolas@silentale.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- LICENSE
|
42
|
+
- README.markdown
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- LICENSE
|
46
|
+
- README.markdown
|
47
|
+
- Rakefile
|
48
|
+
- VERSION
|
49
|
+
- lib/gmail_xoauth.rb
|
50
|
+
- lib/gmail_xoauth/imap_xoauth_authenticator.rb
|
51
|
+
- test/helper.rb
|
52
|
+
- test/test_imap_xoauth_authenticator.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/nfo/gmail_xoauth
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- --charset=UTF-8
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.3.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Get access to Gmail IMAP and STMP via OAuth, using the standard Ruby Net libraries
|
83
|
+
test_files:
|
84
|
+
- test/helper.rb
|
85
|
+
- test/test_imap_xoauth_authenticator.rb
|